Update aosp/master clang for rebase to r235153
Change-Id: Ia94bbcb6da7c75b6e7c2afedd1001094d62a7324
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index dddc886..0a61cfe 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -124,7 +124,7 @@
}
}
- virtual ~CaptureDiagnosticConsumer() {
+ ~CaptureDiagnosticConsumer() override {
assert(!HasBegunSourceFile && "FinishCapture not called!");
}
@@ -465,7 +465,7 @@
if (Listener)
Listener->start(ctx);
}
- ~RewritesApplicator() {
+ ~RewritesApplicator() override {
if (Listener)
Listener->finish();
}
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index 38ff72a..9e7be20 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -48,7 +48,7 @@
};
void migrateDecl(Decl *D);
- void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCContainerDecl *D);
+ void migrateObjCContainerDecl(ASTContext &Ctx, ObjCContainerDecl *D);
void migrateProtocolConformance(ASTContext &Ctx,
const ObjCImplementationDecl *ImpDecl);
void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
@@ -578,7 +578,7 @@
return false;
}
-void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
+void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,
ObjCContainerDecl *D) {
if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D))
return;
@@ -1790,9 +1790,7 @@
: SourceMgr(SM), OS(OS) {
OS << "[\n";
}
- ~JSONEditWriter() {
- OS << "]\n";
- }
+ ~JSONEditWriter() override { OS << "]\n"; }
private:
struct EntryWriter {
@@ -1876,13 +1874,16 @@
if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
if (canModify(CDecl))
- migrateObjCInterfaceDecl(Ctx, CDecl);
+ migrateObjCContainerDecl(Ctx, CDecl);
if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
if (canModify(CatDecl))
- migrateObjCInterfaceDecl(Ctx, CatDecl);
+ migrateObjCContainerDecl(Ctx, CatDecl);
}
- else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D))
+ else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) {
ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
+ if (canModify(PDecl))
+ migrateObjCContainerDecl(Ctx, PDecl);
+ }
else if (const ObjCImplementationDecl *ImpDecl =
dyn_cast<ObjCImplementationDecl>(*D)) {
if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) &&
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 57621a7..899f8c5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3358,7 +3358,7 @@
(void)CheckT;
}
- T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon);
+ T = new (*this, TypeAlignment) ElaboratedType(Keyword, NNS, NamedType, Canon);
Types.push_back(T);
ElaboratedTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3382,7 +3382,7 @@
(void)CheckT;
}
- T = new (*this) ParenType(InnerType, Canon);
+ T = new (*this, TypeAlignment) ParenType(InnerType, Canon);
Types.push_back(T);
ParenTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3411,7 +3411,7 @@
if (T)
return QualType(T, 0);
- T = new (*this) DependentNameType(Keyword, NNS, Name, Canon);
+ T = new (*this, TypeAlignment) DependentNameType(Keyword, NNS, Name, Canon);
Types.push_back(T);
DependentNameTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3513,7 +3513,8 @@
}
}
- T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions);
+ T = new (*this, TypeAlignment)
+ PackExpansionType(Pattern, Canon, NumExpansions);
Types.push_back(T);
PackExpansionTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 2442e8e..eb9b00a 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -67,6 +67,7 @@
// FIXME: DependentDecltypeType
QualType VisitRecordType(const RecordType *T);
QualType VisitEnumType(const EnumType *T);
+ QualType VisitAttributedType(const AttributedType *T);
// FIXME: TemplateTypeParmType
// FIXME: SubstTemplateTypeParmType
QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
@@ -1724,6 +1725,27 @@
return Importer.getToContext().getTagDeclType(ToDecl);
}
+QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
+ QualType FromModifiedType = T->getModifiedType();
+ QualType FromEquivalentType = T->getEquivalentType();
+ QualType ToModifiedType;
+ QualType ToEquivalentType;
+
+ if (!FromModifiedType.isNull()) {
+ ToModifiedType = Importer.Import(FromModifiedType);
+ if (ToModifiedType.isNull())
+ return QualType();
+ }
+ if (!FromEquivalentType.isNull()) {
+ ToEquivalentType = Importer.Import(FromEquivalentType);
+ if (ToEquivalentType.isNull())
+ return QualType();
+ }
+
+ return Importer.getToContext().getAttributedType(T->getAttrKind(),
+ ToModifiedType, ToEquivalentType);
+}
+
QualType ASTNodeImporter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
TemplateName ToTemplate = Importer.Import(T->getTemplateName());
diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp
index 06a08bd..98b7e36 100644
--- a/lib/AST/CommentLexer.cpp
+++ b/lib/AST/CommentLexer.cpp
@@ -514,6 +514,12 @@
if (CommentState == LCS_InsideCComment)
skipLineStartingDecorations();
+ if (BufferPtr == CommentEnd) {
+ formTokenWithChars(T, BufferPtr, tok::verbatim_block_line);
+ T.setVerbatimBlockText("");
+ return;
+ }
+
lexVerbatimBlockFirstLine(T);
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index ba6fd2e..628c9b0 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1737,8 +1737,7 @@
if (NumTPLists > 0) {
TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
NumTemplParamLists = NumTPLists;
- for (unsigned i = NumTPLists; i-- > 0; )
- TemplParamLists[i] = TPLists[i];
+ std::copy(TPLists, TPLists + NumTPLists, TemplParamLists);
}
}
@@ -1878,9 +1877,8 @@
VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }
-VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
- ASTContext &C) const
-{
+VarDecl::DefinitionKind
+VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
// C++ [basic.def]p2:
// A declaration is a definition unless [...] it contains the 'extern'
// specifier or a linkage-specification and neither an initializer [...],
@@ -1917,7 +1915,7 @@
if (hasInit())
return Definition;
- if (hasAttr<AliasAttr>())
+ if (hasAttr<AliasAttr>() || hasAttr<SelectAnyAttr>())
return Definition;
// A variable template specialization (other than a static data member
@@ -2823,6 +2821,18 @@
return RTRange;
}
+bool FunctionDecl::hasUnusedResultAttr() const {
+ QualType RetType = getReturnType();
+ if (RetType->isRecordType()) {
+ const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
+ const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this);
+ if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() &&
+ !(MD && MD->getCorrespondingMethodInClass(Ret, true)))
+ return true;
+ }
+ return hasAttr<WarnUnusedResultAttr>();
+}
+
/// \brief For an inline function definition in C, or for a gnu_inline function
/// in C++, determine whether the definition will be externally visible.
///
@@ -3104,6 +3114,8 @@
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
const TemplateArgumentListInfo &TArgs)
: AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
+ static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
+ "Trailing data is unaligned!");
d.NumTemplates = Ts.size();
d.NumArgs = TArgs.size();
diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp
index 9861f22..512837f 100644
--- a/lib/AST/DeclGroup.cpp
+++ b/lib/AST/DeclGroup.cpp
@@ -18,6 +18,8 @@
using namespace clang;
DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+ static_assert(sizeof(DeclGroup) % llvm::AlignOf<void *>::Alignment == 0,
+ "Trailing data is unaligned!");
assert(NumDecls > 1 && "Invalid DeclGroup");
unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index d13a11c..76a4da2 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2161,12 +2161,16 @@
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
if (const Decl *FD = CE->getCalleeDecl()) {
+ const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
+ bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr()
+ : FD->hasAttr<WarnUnusedResultAttr>();
+
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
//
// Note: If new cases are added here, DiagnoseUnusedExprResult should be
// updated to match for QoI.
- if (FD->hasAttr<WarnUnusedResultAttr>() ||
+ if (HasWarnUnusedResultAttr ||
FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) {
WarnE = this;
Loc = CE->getCallee()->getLocStart();
@@ -2942,11 +2946,19 @@
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass:
case CUDAKernelCallExprClass:
+ case UserDefinedLiteralClass: {
+ // We don't know a call definitely has side effects, except for calls
+ // to pure/const functions that definitely don't.
+ // If the call itself is considered side-effect free, check the operands.
+ const Decl *FD = cast<CallExpr>(this)->getCalleeDecl();
+ bool IsPure = FD && (FD->hasAttr<ConstAttr>() || FD->hasAttr<PureAttr>());
+ if (IsPure || !IncludePossibleEffects)
+ break;
+ return true;
+ }
+
case BlockExprClass:
case CXXBindTemporaryExprClass:
- case UserDefinedLiteralClass:
- // We don't know a call definitely has side effects, but we can check the
- // call's operands.
if (!IncludePossibleEffects)
break;
return true;
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index f890719..6e55655 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -166,6 +166,8 @@
raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
+ void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override;
void mangleItaniumThreadLocalWrapper(const VarDecl *D,
raw_ostream &) override;
@@ -3967,6 +3969,16 @@
Mangler.getStream() << EnclosingDecl->getName();
}
+void ItaniumMangleContextImpl::mangleSEHFinallyBlock(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "__fin_";
+ if (shouldMangleDeclName(EnclosingDecl))
+ Mangler.mangle(EnclosingDecl);
+ else
+ Mangler.getStream() << EnclosingDecl->getName();
+}
+
void ItaniumMangleContextImpl::mangleItaniumThreadLocalInit(const VarDecl *D,
raw_ostream &Out) {
// <special-name> ::= TH <object name>
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 563ea7f..3689102 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -94,6 +94,7 @@
llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier;
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
+ llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
public:
MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
@@ -122,8 +123,8 @@
CXXCtorType CT, uint32_t Size, uint32_t NVOffset,
int32_t VBPtrOffset, uint32_t VBIndex,
raw_ostream &Out) override;
- void mangleCXXHandlerMapEntry(QualType T, bool IsConst, bool IsVolatile,
- bool IsReference, raw_ostream &Out) override;
+ void mangleCXXCatchHandlerType(QualType T, uint32_t Flags,
+ raw_ostream &Out) override;
void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
@@ -151,6 +152,8 @@
raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
+ void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
raw_ostream &Out) override;
@@ -1677,7 +1680,7 @@
Out << 'X';
} else {
// Happens for function pointer type arguments for example.
- for (const QualType Arg : Proto->param_types())
+ for (const QualType &Arg : Proto->param_types())
mangleArgumentType(Arg, Range);
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
@@ -2345,20 +2348,13 @@
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
}
-void MicrosoftMangleContextImpl::mangleCXXHandlerMapEntry(QualType T,
- bool IsConst,
- bool IsVolatile,
- bool IsReference,
- raw_ostream &Out) {
+void MicrosoftMangleContextImpl::mangleCXXCatchHandlerType(QualType T,
+ uint32_t Flags,
+ raw_ostream &Out) {
MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "llvm.eh.handlermapentry.";
- if (IsConst)
- Mangler.getStream() << "const.";
- if (IsVolatile)
- Mangler.getStream() << "volatile.";
- if (IsReference)
- Mangler.getStream() << "reference.";
+ Mangler.getStream() << "llvm.eh.handlertype.";
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+ Mangler.getStream() << '.' << Flags;
}
void MicrosoftMangleContextImpl::mangleCXXThrowInfo(QualType T,
@@ -2476,6 +2472,17 @@
Mangler.mangleName(EnclosingDecl);
}
+void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ // The function body is in the same comdat as the function with the handler,
+ // so the numbering here doesn't have to be the same across TUs.
+ //
+ // <mangled-name> ::= ?fin$ <filter-number> @0
+ Mangler.getStream() << "\01?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
+ Mangler.mangleName(EnclosingDecl);
+}
+
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
// This is just a made up unique string for the purposes of tbaa. undname
// does *not* know how to demangle it.
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 8c76009..0e8652f 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -940,8 +940,7 @@
}
SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond)
- : Stmt(SwitchStmtClass), FirstCase(nullptr), AllEnumCasesCovered(0)
-{
+ : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {
setConditionVariable(C, Var);
SubExprs[COND] = cond;
SubExprs[BODY] = nullptr;
@@ -1247,17 +1246,47 @@
return new (Mem) OMPFirstprivateClause(N);
}
-OMPLastprivateClause *OMPLastprivateClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) {
+ assert(PrivateCopies.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end());
+}
+
+void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end());
+}
+
+void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPLastprivateClause *OMPLastprivateClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 5 * sizeof(Expr *) * VL.size());
OMPLastprivateClause *Clause =
new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
@@ -1265,7 +1294,7 @@
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 5 * sizeof(Expr *) * N);
return new (Mem) OMPLastprivateClause(N);
}
@@ -1366,17 +1395,41 @@
return new (Mem) OMPAlignedClause(NumVars);
}
-OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
+}
+
+void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPCopyinClause *OMPCopyinClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 4 * sizeof(Expr *) * VL.size());
OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc,
EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
@@ -1384,7 +1437,7 @@
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 4 * sizeof(Expr *) * N);
return new (Mem) OMPCopyinClause(N);
}
@@ -1458,16 +1511,42 @@
std::copy(A.begin(), A.end(), getFinals().begin());
}
+void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
+ assert(
+ LHSExprs.size() == varlist_size() &&
+ "Number of LHS expressions is not the same as the preallocated buffer");
+ std::copy(LHSExprs.begin(), LHSExprs.end(), varlist_end());
+}
+
+void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
+ assert(
+ RHSExprs.size() == varlist_size() &&
+ "Number of RHS expressions is not the same as the preallocated buffer");
+ std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
+}
+
+void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
+ assert(ReductionOps.size() == varlist_size() && "Number of reduction "
+ "expressions is not the same "
+ "as the preallocated buffer");
+ std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
+}
+
OMPReductionClause *OMPReductionClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
- NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) {
+ NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
+ ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
+ ArrayRef<Expr *> ReductionOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 4 * sizeof(Expr *) * VL.size());
OMPReductionClause *Clause = new (Mem) OMPReductionClause(
StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
Clause->setVarRefs(VL);
+ Clause->setLHSExprs(LHSExprs);
+ Clause->setRHSExprs(RHSExprs);
+ Clause->setReductionOps(ReductionOps);
return Clause;
}
@@ -1475,7 +1554,7 @@
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 4 * sizeof(Expr *) * N);
return new (Mem) OMPReductionClause(N);
}
@@ -2007,24 +2086,24 @@
return new (Mem) OMPOrderedDirective();
}
-OMPAtomicDirective *
-OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt, BinaryOperatorKind OpKind,
- Expr *X, Expr *XRVal, Expr *V, Expr *E) {
+OMPAtomicDirective *OMPAtomicDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
+ Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
llvm::alignOf<OMPClause *>());
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
5 * sizeof(Stmt *));
OMPAtomicDirective *Dir =
new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setOpKind(OpKind);
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
Dir->setX(X);
- Dir->setXRVal(X);
Dir->setV(V);
Dir->setExpr(E);
+ Dir->setUpdateExpr(UE);
+ Dir->IsXLHSInRHSPart = IsXLHSInRHSPart;
+ Dir->IsPostfixUpdate = IsPostfixUpdate;
return Dir;
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 8f0edd0..b68f3a3 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1622,6 +1622,15 @@
const TemplateArgumentList *Args =
cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs();
assert(Args);
+
+ if (Args->size() != 1) {
+ OS << "operator \"\" " << Node->getUDSuffix()->getName();
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, Args->data(), Args->size(), Policy);
+ OS << "()";
+ return;
+ }
+
const TemplateArgument &Pack = Args->get(0);
for (const auto &P : Pack.pack_elements()) {
char C = (char)P.getAsIntegral().getZExtValue();
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index f29f6a8..f6df1ca 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -346,6 +346,15 @@
void
OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
VisitOMPClauseList(C);
@@ -356,6 +365,15 @@
C->getQualifierLoc().getNestedNameSpecifier());
Profiler->VisitName(C->getNameInfo().getName());
VisitOMPClauseList(C);
+ for (auto *E : C->lhs_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->rhs_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->reduction_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
@@ -377,6 +395,15 @@
}
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void
OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 0e8b1e8..0eb5d8c 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2371,6 +2371,11 @@
return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
return false;
}
+bool Type::isObjCIndependentClassType() const {
+ if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+ return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
+ return false;
+}
bool Type::isObjCRetainableType() const {
return isObjCObjectPointerType() ||
isBlockPointerType() ||
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index fa7968a..c5f3063 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -300,7 +300,7 @@
const MatchFinder::MatchFinderOptions &Options)
: Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
- ~MatchASTVisitor() {
+ ~MatchASTVisitor() override {
if (Options.CheckProfiling) {
Options.CheckProfiling->Records = std::move(TimeByBucket);
}
diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
index b78bc03..36a6415 100644
--- a/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -181,18 +181,20 @@
ArgKinds(ArgKinds.begin(), ArgKinds.end()) {}
VariantMatcher create(const SourceRange &NameRange,
- ArrayRef<ParserValue> Args, Diagnostics *Error) const {
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const override {
return Marshaller(Func, MatcherName, NameRange, Args, Error);
}
- bool isVariadic() const { return false; }
- unsigned getNumArgs() const { return ArgKinds.size(); }
+ bool isVariadic() const override { return false; }
+ unsigned getNumArgs() const override { return ArgKinds.size(); }
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
- std::vector<ArgKind> &Kinds) const {
+ std::vector<ArgKind> &Kinds) const override {
Kinds.push_back(ArgKinds[ArgNo]);
}
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
- ast_type_traits::ASTNodeKind *LeastDerivedKind) const {
+ bool isConvertibleTo(
+ ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
+ ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
return isRetKindConvertibleTo(RetKinds, Kind, Specificity,
LeastDerivedKind);
}
@@ -333,18 +335,20 @@
}
VariantMatcher create(const SourceRange &NameRange,
- ArrayRef<ParserValue> Args, Diagnostics *Error) const {
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const override {
return Func(MatcherName, NameRange, Args, Error);
}
- bool isVariadic() const { return true; }
- unsigned getNumArgs() const { return 0; }
+ bool isVariadic() const override { return true; }
+ unsigned getNumArgs() const override { return 0; }
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
- std::vector<ArgKind> &Kinds) const {
+ std::vector<ArgKind> &Kinds) const override {
Kinds.push_back(ArgsKind);
}
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
- ast_type_traits::ASTNodeKind *LeastDerivedKind) const {
+ bool isConvertibleTo(
+ ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
+ ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
return isRetKindConvertibleTo(RetKinds, Kind, Specificity,
LeastDerivedKind);
}
@@ -487,11 +491,11 @@
OverloadedMatcherDescriptor(ArrayRef<MatcherDescriptor *> Callbacks)
: Overloads(Callbacks.begin(), Callbacks.end()) {}
- virtual ~OverloadedMatcherDescriptor() {}
+ ~OverloadedMatcherDescriptor() override {}
- virtual VariantMatcher create(const SourceRange &NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error) const {
+ VariantMatcher create(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const override {
std::vector<VariantMatcher> Constructed;
Diagnostics::OverloadContext Ctx(Error);
for (const auto &O : Overloads) {
@@ -512,7 +516,7 @@
return Constructed[0];
}
- bool isVariadic() const {
+ bool isVariadic() const override {
bool Overload0Variadic = Overloads[0]->isVariadic();
#ifndef NDEBUG
for (const auto &O : Overloads) {
@@ -522,7 +526,7 @@
return Overload0Variadic;
}
- unsigned getNumArgs() const {
+ unsigned getNumArgs() const override {
unsigned Overload0NumArgs = Overloads[0]->getNumArgs();
#ifndef NDEBUG
for (const auto &O : Overloads) {
@@ -533,15 +537,16 @@
}
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
- std::vector<ArgKind> &Kinds) const {
+ std::vector<ArgKind> &Kinds) const override {
for (const auto &O : Overloads) {
if (O->isConvertibleTo(ThisKind))
O->getArgKinds(ThisKind, ArgNo, Kinds);
}
}
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
- ast_type_traits::ASTNodeKind *LeastDerivedKind) const {
+ bool isConvertibleTo(
+ ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
+ ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
for (const auto &O : Overloads) {
if (O->isConvertibleTo(Kind, Specificity, LeastDerivedKind))
return true;
@@ -562,9 +567,9 @@
: MinCount(MinCount), MaxCount(MaxCount), Op(Op),
MatcherName(MatcherName) {}
- virtual VariantMatcher create(const SourceRange &NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error) const override {
+ VariantMatcher create(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const override {
if (Args.size() < MinCount || MaxCount < Args.size()) {
const std::string MaxStr =
(MaxCount == UINT_MAX ? "" : Twine(MaxCount)).str();
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 169f1df..94fa1d9 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -3950,9 +3950,8 @@
}
}
}
-
- virtual ~StmtPrinterHelper() {}
+ ~StmtPrinterHelper() override {}
const LangOptions &getLangOpts() const { return LangOpts; }
void setBlockID(signed i) { currentBlock = i; }
diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index 967f3e1..fa985ee 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -1442,7 +1442,7 @@
CurrStates,
WarningsHandler);
- if (BlockInfo.allBackEdgesVisited(*SI, CurrBlock))
+ if (BlockInfo.allBackEdgesVisited(CurrBlock, *SI))
BlockInfo.discardInfo(*SI);
} else {
BlockInfo.addInfo(*SI, CurrStates, OwnershipTaken);
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index 8a6870f..3c7bc4e 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -837,7 +837,7 @@
: hadUse(numBlocks, false), hadAnyUse(false),
currentBlock(0) {}
- virtual ~PruneBlocksHandler() {}
+ ~PruneBlocksHandler() override {}
/// Records if a CFGBlock had a potential use of an uninitialized variable.
llvm::BitVector hadUse;
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index 6e98d48..b83a069 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -374,7 +374,6 @@
}
bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) {
- return Kind == OMPC_threadprivate ||
- Kind == OMPC_copyin; // TODO add next clauses like 'copyprivate'.
+ return Kind == OMPC_threadprivate || Kind == OMPC_copyin;
}
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 118e3f3..c0b0453 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -110,8 +110,8 @@
// possible.
if (!BufferOrError) {
StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
- Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(),
- "<invalid>").release());
+ Buffer.setPointer(MemoryBuffer::getNewUninitMemBuffer(
+ ContentsEntry->getSize(), "<invalid>").release());
char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart());
for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
Ptr[i] = FillStr[i % FillStr.size()];
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index fb73231..fd8215b 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -445,6 +445,7 @@
public:
NetBSDTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
this->UserLabelPrefix = "";
+ this->MCountName = "_mcount";
}
};
@@ -713,8 +714,7 @@
// RegParmMax is inherited from the underlying architecture
this->LongDoubleFormat = &llvm::APFloat::IEEEdouble;
if (Triple.getArch() == llvm::Triple::arm) {
- this->DescriptionString =
- "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128";
+ // Handled in ARM's setABI().
} else if (Triple.getArch() == llvm::Triple::x86) {
this->DescriptionString = "e-m:e-p:32:32-i64:64-n8:16:32-S128";
} else if (Triple.getArch() == llvm::Triple::x86_64) {
@@ -743,8 +743,11 @@
bool HasVSX;
bool HasP8Vector;
bool HasP8Crypto;
+ bool HasDirectMove;
bool HasQPX;
bool HasHTM;
+ bool HasBPERMD;
+ bool HasExtDiv;
protected:
std::string ABI;
@@ -752,7 +755,8 @@
public:
PPCTargetInfo(const llvm::Triple &Triple)
: TargetInfo(Triple), HasVSX(false), HasP8Vector(false),
- HasP8Crypto(false), HasQPX(false), HasHTM(false) {
+ HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false),
+ HasBPERMD(false), HasExtDiv(false) {
BigEndian = (Triple.getArch() != llvm::Triple::ppc64le);
LongDoubleWidth = LongDoubleAlign = 128;
LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble;
@@ -1012,6 +1016,16 @@
continue;
}
+ if (Feature == "bpermd") {
+ HasBPERMD = true;
+ continue;
+ }
+
+ if (Feature == "extdiv") {
+ HasExtDiv = true;
+ continue;
+ }
+
if (Feature == "power8-vector") {
HasP8Vector = true;
continue;
@@ -1022,6 +1036,11 @@
continue;
}
+ if (Feature == "direct-move") {
+ HasDirectMove = true;
+ continue;
+ }
+
if (Feature == "qpx") {
HasQPX = true;
continue;
@@ -1234,6 +1253,20 @@
.Case("ppc64le", true)
.Case("pwr8", true)
.Default(false);
+ Features["bpermd"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["extdiv"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["direct-move"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr8", true)
+ .Default(false);
}
bool PPCTargetInfo::hasFeature(StringRef Feature) const {
@@ -1242,8 +1275,11 @@
.Case("vsx", HasVSX)
.Case("power8-vector", HasP8Vector)
.Case("crypto", HasP8Crypto)
+ .Case("direct-move", HasDirectMove)
.Case("qpx", HasQPX)
.Case("htm", HasHTM)
+ .Case("bpermd", HasBPERMD)
+ .Case("extdiv", HasExtDiv)
.Default(false);
}
@@ -1477,6 +1513,7 @@
GK_SM21,
GK_SM30,
GK_SM35,
+ GK_SM37,
} GPU;
public:
@@ -1512,6 +1549,9 @@
case GK_SM35:
CUDAArchCode = "350";
break;
+ case GK_SM37:
+ CUDAArchCode = "370";
+ break;
default:
llvm_unreachable("Unhandled target CPU");
}
@@ -1564,6 +1604,7 @@
.Case("sm_21", GK_SM21)
.Case("sm_30", GK_SM30)
.Case("sm_35", GK_SM35)
+ .Case("sm_37", GK_SM37)
.Default(GK_NONE);
return GPU != GK_NONE;
@@ -1591,20 +1632,22 @@
public:
NVPTX32TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) {
PointerWidth = PointerAlign = 32;
- SizeType = PtrDiffType = TargetInfo::UnsignedInt;
+ SizeType = TargetInfo::UnsignedInt;
+ PtrDiffType = TargetInfo::SignedInt;
IntPtrType = TargetInfo::SignedInt;
DescriptionString = "e-p:32:32-i64:64-v16:16-v32:32-n16:32:64";
- }
+ }
};
class NVPTX64TargetInfo : public NVPTXTargetInfo {
public:
NVPTX64TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) {
PointerWidth = PointerAlign = 64;
- SizeType = PtrDiffType = TargetInfo::UnsignedLongLong;
- IntPtrType = TargetInfo::SignedLongLong;
+ SizeType = TargetInfo::UnsignedLong;
+ PtrDiffType = TargetInfo::SignedLong;
+ IntPtrType = TargetInfo::SignedLong;
DescriptionString = "e-i64:64-v16:16-v32:32-n16:32:64";
- }
+ }
};
static const unsigned R600AddrSpaceMap[] = {
@@ -1635,6 +1678,7 @@
class R600TargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
+ static const char * const GCCRegNames[];
/// \brief The GPU profiles supported by the R600 target.
enum GPUKind {
@@ -1685,10 +1729,7 @@
}
void getGCCRegNames(const char * const *&Names,
- unsigned &numNames) const override {
- Names = nullptr;
- numNames = 0;
- }
+ unsigned &NumNames) const override;
void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const override {
@@ -1791,6 +1832,64 @@
{ #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
#include "clang/Basic/BuiltinsR600.def"
};
+const char * const R600TargetInfo::GCCRegNames[] = {
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+ "v32", "v33", "v34", "v35", "v36", "v37", "v38", "v39",
+ "v40", "v41", "v42", "v43", "v44", "v45", "v46", "v47",
+ "v48", "v49", "v50", "v51", "v52", "v53", "v54", "v55",
+ "v56", "v57", "v58", "v59", "v60", "v61", "v62", "v63",
+ "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71",
+ "v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79",
+ "v80", "v81", "v82", "v83", "v84", "v85", "v86", "v87",
+ "v88", "v89", "v90", "v91", "v92", "v93", "v94", "v95",
+ "v96", "v97", "v98", "v99", "v100", "v101", "v102", "v103",
+ "v104", "v105", "v106", "v107", "v108", "v109", "v110", "v111",
+ "v112", "v113", "v114", "v115", "v116", "v117", "v118", "v119",
+ "v120", "v121", "v122", "v123", "v124", "v125", "v126", "v127",
+ "v128", "v129", "v130", "v131", "v132", "v133", "v134", "v135",
+ "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143",
+ "v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151",
+ "v152", "v153", "v154", "v155", "v156", "v157", "v158", "v159",
+ "v160", "v161", "v162", "v163", "v164", "v165", "v166", "v167",
+ "v168", "v169", "v170", "v171", "v172", "v173", "v174", "v175",
+ "v176", "v177", "v178", "v179", "v180", "v181", "v182", "v183",
+ "v184", "v185", "v186", "v187", "v188", "v189", "v190", "v191",
+ "v192", "v193", "v194", "v195", "v196", "v197", "v198", "v199",
+ "v200", "v201", "v202", "v203", "v204", "v205", "v206", "v207",
+ "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215",
+ "v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223",
+ "v224", "v225", "v226", "v227", "v228", "v229", "v230", "v231",
+ "v232", "v233", "v234", "v235", "v236", "v237", "v238", "v239",
+ "v240", "v241", "v242", "v243", "v244", "v245", "v246", "v247",
+ "v248", "v249", "v250", "v251", "v252", "v253", "v254", "v255",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
+ "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+ "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+ "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39",
+ "s40", "s41", "s42", "s43", "s44", "s45", "s46", "s47",
+ "s48", "s49", "s50", "s51", "s52", "s53", "s54", "s55",
+ "s56", "s57", "s58", "s59", "s60", "s61", "s62", "s63",
+ "s64", "s65", "s66", "s67", "s68", "s69", "s70", "s71",
+ "s72", "s73", "s74", "s75", "s76", "s77", "s78", "s79",
+ "s80", "s81", "s82", "s83", "s84", "s85", "s86", "s87",
+ "s88", "s89", "s90", "s91", "s92", "s93", "s94", "s95",
+ "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103",
+ "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111",
+ "s112", "s113", "s114", "s115", "s116", "s117", "s118", "s119",
+ "s120", "s121", "s122", "s123", "s124", "s125", "s126", "s127"
+ "exec", "vcc", "scc", "m0", "flat_scr", "exec_lo", "exec_hi",
+ "vcc_lo", "vcc_hi", "flat_scr_lo", "flat_scr_hi"
+};
+
+void R600TargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
// Namespace for x86 abstract base class
const Builtin::Info BuiltinInfo[] = {
@@ -3430,7 +3529,10 @@
: WindowsTargetInfo<X86_32TargetInfo>(Triple) {
WCharType = UnsignedShort;
DoubleAlign = LongLongAlign = 64;
- DescriptionString = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-S32";
+ bool IsWinCOFF =
+ getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
+ DescriptionString = IsWinCOFF ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-S32"
+ : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-S32";
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -3897,6 +3999,9 @@
"-a:0:32"
"-n32"
"-S64";
+ } else if (T.isOSNaCl()) {
+ assert(!BigEndian && "NaCl on ARM does not support big endian");
+ DescriptionString = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128";
} else {
DescriptionString =
BigEndian ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
@@ -4080,7 +4185,7 @@
Features["hwdiv"] = true;
Features["hwdiv-arm"] = true;
} else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7" ||
- CPU == "sc300") {
+ CPU == "sc300" || CPU == "cortex-r4" || CPU == "cortex-r4f") {
Features["hwdiv"] = true;
}
}
@@ -4181,7 +4286,7 @@
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "7A")
.Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait",
"7A")
- .Cases("cortex-r4", "cortex-r5", "cortex-r7", "7R")
+ .Cases("cortex-r4", "cortex-r4f", "cortex-r5", "cortex-r7", "7R")
.Case("swift", "7S")
.Case("cyclone", "8A")
.Cases("sc300", "cortex-m3", "7M")
@@ -4198,7 +4303,7 @@
.Cases("cortex-a53", "cortex-a57", "cortex-a72", "A")
.Cases("cortex-m3", "cortex-m4", "cortex-m0", "cortex-m0plus", "M")
.Cases("cortex-m1", "cortex-m7", "sc000", "sc300", "M")
- .Cases("cortex-r4", "cortex-r5", "cortex-r7", "R")
+ .Cases("cortex-r4", "cortex-r4f", "cortex-r5", "cortex-r7", "R")
.Default("");
}
bool setCPU(const std::string &Name) override {
@@ -4560,8 +4665,8 @@
public:
ARMleTargetInfo(const llvm::Triple &Triple)
: ARMTargetInfo(Triple, false) { }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
Builder.defineMacro("__ARMEL__");
ARMTargetInfo::getTargetDefines(Opts, Builder);
}
@@ -4571,8 +4676,8 @@
public:
ARMbeTargetInfo(const llvm::Triple &Triple)
: ARMTargetInfo(Triple, true) { }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
Builder.defineMacro("__ARMEB__");
Builder.defineMacro("__ARM_BIG_ENDIAN");
ARMTargetInfo::getTargetDefines(Opts, Builder);
@@ -4744,8 +4849,8 @@
return CPUKnown;
}
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
// Target identification.
Builder.defineMacro("__aarch64__");
@@ -4804,8 +4909,8 @@
Builder.defineMacro("__ARM_FEATURE_CRYPTO");
}
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
+ void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const override {
Records = BuiltinInfo;
NumRecords = clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin;
}
@@ -4841,14 +4946,13 @@
return TargetInfo::AArch64ABIBuiltinVaList;
}
- virtual void getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const override;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
+ void getGCCRegNames(const char *const *&Names,
+ unsigned &NumNames) const override;
+ void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const override;
- virtual bool
- validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
default:
return false;
@@ -5402,10 +5506,16 @@
};
class SystemZTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
static const char *const GCCRegNames[];
+ std::string CPU;
+ bool HasTransactionalExecution;
public:
- SystemZTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ SystemZTargetInfo(const llvm::Triple &Triple)
+ : TargetInfo(Triple), CPU("z10"), HasTransactionalExecution(false) {
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
TLSSupported = true;
IntWidth = IntAlign = 32;
LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
@@ -5423,12 +5533,13 @@
Builder.defineMacro("__s390x__");
Builder.defineMacro("__zarch__");
Builder.defineMacro("__LONG_DOUBLE_128__");
+ if (HasTransactionalExecution)
+ Builder.defineMacro("__HTM__");
}
void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const override {
- // FIXME: Implement.
- Records = nullptr;
- NumRecords = 0;
+ Records = BuiltinInfo;
+ NumRecords = clang::SystemZ::LastTSBuiltin-Builtin::FirstTSBuiltin;
}
void getGCCRegNames(const char *const *&Names,
@@ -5449,16 +5560,42 @@
return TargetInfo::SystemZBuiltinVaList;
}
bool setCPU(const std::string &Name) override {
+ CPU = Name;
bool CPUKnown = llvm::StringSwitch<bool>(Name)
.Case("z10", true)
.Case("z196", true)
.Case("zEC12", true)
.Default(false);
- // No need to store the CPU yet. There aren't any CPU-specific
- // macros to define.
return CPUKnown;
}
+ void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
+ if (CPU == "zEC12")
+ Features["transactional-execution"] = true;
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ HasTransactionalExecution = false;
+ for (unsigned i = 0, e = Features.size(); i != e; ++i) {
+ if (Features[i] == "+transactional-execution")
+ HasTransactionalExecution = true;
+ }
+ return true;
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("systemz", true)
+ .Case("htm", HasTransactionalExecution)
+ .Default(false);
+ }
+};
+
+const Builtin::Info SystemZTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+#include "clang/Basic/BuiltinsSystemZ.def"
};
const char *const SystemZTargetInfo::GCCRegNames[] = {
@@ -5859,9 +5996,30 @@
case 'R': // An address that can be used in a non-macro load or store
Info.setAllowsMemory();
return true;
+ case 'Z':
+ if (Name[1] == 'C') { // An address usable by ll, and sc.
+ Info.setAllowsMemory();
+ Name++; // Skip over 'Z'.
+ return true;
+ }
+ return false;
}
}
+ std::string convertConstraint(const char *&Constraint) const override {
+ std::string R;
+ switch (*Constraint) {
+ case 'Z': // Two-character constraint; add "^" hint for later parsing.
+ if (Constraint[1] == 'C') {
+ R = std::string("^") + std::string(Constraint, 2);
+ Constraint++;
+ return R;
+ }
+ break;
+ }
+ return TargetInfo::convertConstraint(Constraint);
+ }
+
const char *getClobbers() const override {
// In GCC, $1 is not widely used in generated code (it's used only in a few
// specific situations), so there is no real need for users to add it to
@@ -6752,6 +6910,8 @@
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<PPC64TargetInfo>(Triple);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<PPC64TargetInfo>(Triple);
default:
return new PPC64TargetInfo(Triple);
}
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index 5164bcf..8a882e1 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/lib/Basic/VirtualFileSystem.cpp
@@ -92,7 +92,7 @@
}
public:
- ~RealFile();
+ ~RealFile() override;
ErrorOr<Status> status() override;
ErrorOr<std::unique_ptr<MemoryBuffer>>
getBuffer(const Twine &Name, int64_t FileSize = -1,
@@ -362,7 +362,7 @@
Status S;
public:
- virtual ~DirectoryEntry();
+ ~DirectoryEntry() override;
DirectoryEntry(StringRef Name, std::vector<Entry *> Contents, Status S)
: Entry(EK_Directory, Name), Contents(std::move(Contents)),
S(std::move(S)) {}
@@ -498,7 +498,7 @@
ErrorOr<Status> status(const Twine &Path, Entry *E);
public:
- ~VFSFromYAML();
+ ~VFSFromYAML() override;
/// \brief Parses \p Buffer, which is expected to be in YAML format and
/// returns a virtual file system representing its contents.
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index bdab637..7bc351a 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -27,7 +27,6 @@
#include "llvm/IR/Verifier.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/Timer.h"
@@ -97,7 +96,7 @@
void CreatePasses();
- /// CreateTargetMachine - Generates the TargetMachine.
+ /// Generates the TargetMachine.
/// Returns Null if it is unable to create the target machine.
/// Some of our clang tests specify triples which are not built
/// into clang. This is okay because these tests check the generated
@@ -107,10 +106,10 @@
/// the requested target.
TargetMachine *CreateTargetMachine(bool MustCreateTM);
- /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR.
+ /// Add passes necessary to emit assembly or LLVM IR.
///
/// \return True on success.
- bool AddEmitPasses(BackendAction Action, formatted_raw_ostream &OS);
+ bool AddEmitPasses(BackendAction Action, raw_pwrite_stream &OS);
public:
EmitAssemblyHelper(DiagnosticsEngine &_Diags,
@@ -133,7 +132,7 @@
std::unique_ptr<TargetMachine> TM;
- void EmitAssembly(BackendAction Action, raw_ostream *OS);
+ void EmitAssembly(BackendAction Action, raw_pwrite_stream *OS);
};
// We need this wrapper to access LangOpts and CGOpts from extension functions
@@ -437,8 +436,6 @@
BackendArgs.push_back("-time-passes");
for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i)
BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str());
- if (CodeGenOpts.NoGlobalMerge)
- BackendArgs.push_back("-enable-global-merge=false");
BackendArgs.push_back(nullptr);
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
BackendArgs.data());
@@ -549,7 +546,7 @@
}
bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
- formatted_raw_ostream &OS) {
+ raw_pwrite_stream &OS) {
// Create the code generator passes.
legacy::PassManager *PM = getCodeGenPasses();
@@ -586,9 +583,9 @@
return true;
}
-void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
+void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
+ raw_pwrite_stream *OS) {
TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
- llvm::formatted_raw_ostream FormattedOS;
bool UsesCodeGen = (Action != Backend_EmitNothing &&
Action != Backend_EmitBC &&
@@ -604,17 +601,17 @@
break;
case Backend_EmitBC:
- getPerModulePasses()->add(createBitcodeWriterPass(*OS));
+ getPerModulePasses()->add(
+ createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists));
break;
case Backend_EmitLL:
- FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
- getPerModulePasses()->add(createPrintModulePass(FormattedOS));
+ getPerModulePasses()->add(
+ createPrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists));
break;
default:
- FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
- if (!AddEmitPasses(Action, FormattedOS))
+ if (!AddEmitPasses(Action, *OS))
return;
}
@@ -651,7 +648,7 @@
const clang::TargetOptions &TOpts,
const LangOptions &LOpts, StringRef TDesc,
Module *M, BackendAction Action,
- raw_ostream *OS) {
+ raw_pwrite_stream *OS) {
EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);
AsmHelper.EmitAssembly(Action, OS);
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index b7222fc..2de9cb2 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -189,7 +189,7 @@
assert(LVal.isSimple());
llvm::Value *addr = getAtomicAddress();
if (hasPadding())
- addr = CGF.Builder.CreateStructGEP(addr, 0);
+ addr = CGF.Builder.CreateStructGEP(nullptr, addr, 0);
return LValue::MakeAddr(addr, getValueType(), LVal.getAlignment(),
CGF.getContext(), LVal.getTBAAInfo());
@@ -209,7 +209,7 @@
/// \param IsWeak true if atomic operation is weak, false otherwise.
/// \returns Pair of values: previous value from storage (value type) and
/// boolean flag (i1 type) with true if success and false otherwise.
- std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchange(
+ std::pair<RValue, llvm::Value *> EmitAtomicCompareExchange(
RValue Expected, RValue Desired,
llvm::AtomicOrdering Success = llvm::SequentiallyConsistent,
llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent,
@@ -235,13 +235,13 @@
/// \brief Emits atomic load as LLVM instruction.
llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile);
/// \brief Emits atomic compare-and-exchange op as a libcall.
- std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeLibcall(
- llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
+ std::pair<RValue, llvm::Value *> EmitAtomicCompareExchangeLibcall(
+ RValue Expected, RValue DesiredAddr,
llvm::AtomicOrdering Success = llvm::SequentiallyConsistent,
llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent);
/// \brief Emits atomic compare-and-exchange op as LLVM instruction.
- std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeOp(
- llvm::Value *Expected, llvm::Value *Desired,
+ std::pair<RValue, llvm::Value *> EmitAtomicCompareExchangeOp(
+ RValue Expected, RValue Desired,
llvm::AtomicOrdering Success = llvm::SequentiallyConsistent,
llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent,
bool IsWeak = false);
@@ -1060,19 +1060,20 @@
// Drill into the padding structure if we have one.
if (hasPadding())
- addr = CGF.Builder.CreateStructGEP(addr, 0);
+ addr = CGF.Builder.CreateStructGEP(nullptr, addr, 0);
// Otherwise, just convert the temporary to an r-value using the
// normal conversion routine.
return CGF.convertTempToRValue(addr, getValueType(), loc);
- } else if (!AsValue)
+ }
+ if (!AsValue)
// Get RValue from temp memory as atomic for non-simple lvalues
return RValue::get(
CGF.Builder.CreateAlignedLoad(addr, AtomicAlign.getQuantity()));
- else if (LVal.isBitField())
+ if (LVal.isBitField())
return CGF.EmitLoadOfBitfieldLValue(LValue::MakeBitfield(
addr, LVal.getBitFieldInfo(), LVal.getType(), LVal.getAlignment()));
- else if (LVal.isVectorElt())
+ if (LVal.isVectorElt())
return CGF.EmitLoadOfLValue(LValue::MakeVectorElt(addr, LVal.getVectorIdx(),
LVal.getType(),
LVal.getAlignment()),
@@ -1291,7 +1292,7 @@
if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple())) {
llvm::Value *Value = RVal.getScalarVal();
if (isa<llvm::IntegerType>(Value->getType()))
- return Value;
+ return CGF.EmitToMemory(Value, ValueTy);
else {
llvm::IntegerType *InputIntTy = llvm::IntegerType::get(
CGF.getLLVMContext(),
@@ -1312,13 +1313,15 @@
getAtomicAlignment().getQuantity());
}
-std::pair<llvm::Value *, llvm::Value *> AtomicInfo::EmitAtomicCompareExchangeOp(
- llvm::Value *Expected, llvm::Value *Desired, llvm::AtomicOrdering Success,
+std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchangeOp(
+ RValue Expected, RValue Desired, llvm::AtomicOrdering Success,
llvm::AtomicOrdering Failure, bool IsWeak) {
// Do the atomic store.
+ auto *ExpectedVal = convertRValueToInt(Expected);
+ auto *DesiredVal = convertRValueToInt(Desired);
auto *Addr = emitCastToAtomicIntPointer(getAtomicAddress());
- auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr, Expected, Desired, Success,
- Failure);
+ auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,
+ Success, Failure);
// Other decoration.
Inst->setVolatile(LVal.isVolatileQualified());
Inst->setWeak(IsWeak);
@@ -1326,16 +1329,20 @@
// Okay, turn that back into the original value type.
auto *PreviousVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/0);
auto *SuccessFailureVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/1);
- return std::make_pair(PreviousVal, SuccessFailureVal);
+ return std::make_pair(
+ ConvertIntToValueOrAtomic(PreviousVal, AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false),
+ SuccessFailureVal);
}
-std::pair<llvm::Value *, llvm::Value *>
-AtomicInfo::EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedAddr,
- llvm::Value *DesiredAddr,
+std::pair<RValue, llvm::Value *>
+AtomicInfo::EmitAtomicCompareExchangeLibcall(RValue Expected, RValue Desired,
llvm::AtomicOrdering Success,
llvm::AtomicOrdering Failure) {
// bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
// void *desired, int success, int failure);
+ auto *ExpectedAddr = materializeRValue(Expected);
+ auto *DesiredAddr = materializeRValue(Desired);
CallArgList Args;
Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());
Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicAddress())),
@@ -1352,12 +1359,14 @@
CGF.getContext().IntTy);
auto SuccessFailureRVal = emitAtomicLibcall(CGF, "__atomic_compare_exchange",
CGF.getContext().BoolTy, Args);
- auto *PreviousVal = CGF.Builder.CreateAlignedLoad(
- ExpectedAddr, getValueAlignment().getQuantity());
- return std::make_pair(PreviousVal, SuccessFailureRVal.getScalarVal());
+
+ return std::make_pair(
+ convertTempToRValue(ExpectedAddr, AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false),
+ SuccessFailureRVal.getScalarVal());
}
-std::pair<llvm::Value *, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
+std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
RValue Expected, RValue Desired, llvm::AtomicOrdering Success,
llvm::AtomicOrdering Failure, bool IsWeak) {
if (Failure >= Success)
@@ -1366,20 +1375,15 @@
// Check whether we should use a library call.
if (shouldUseLibcall()) {
- auto *ExpectedAddr = materializeRValue(Expected);
// Produce a source address.
- auto *DesiredAddr = materializeRValue(Desired);
- return EmitAtomicCompareExchangeLibcall(ExpectedAddr, DesiredAddr, Success,
+ return EmitAtomicCompareExchangeLibcall(Expected, Desired, Success,
Failure);
}
// If we've got a scalar value of the right size, try to avoid going
// through memory.
- auto *ExpectedIntVal = convertRValueToInt(Expected);
- auto *DesiredIntVal = convertRValueToInt(Desired);
-
- return EmitAtomicCompareExchangeOp(ExpectedIntVal, DesiredIntVal, Success,
- Failure, IsWeak);
+ return EmitAtomicCompareExchangeOp(Expected, Desired, Success, Failure,
+ IsWeak);
}
void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue lvalue,
@@ -1498,20 +1502,14 @@
atomics.getAtomicType(), SourceLocation()));
// Try to write new value using cmpxchg operation
auto Pair = atomics.EmitAtomicCompareExchange(OriginalRValue, NewRValue, AO);
- llvm::Value *OldValue = Pair.first;
- if (!atomics.shouldUseLibcall())
- // Convert integer value to original atomic type
- OldValue = atomics.ConvertIntToValueOrAtomic(
- OldValue, AggValueSlot::ignored(), SourceLocation(),
- /*AsValue=*/false).getScalarVal();
- PHI->addIncoming(OldValue, ContBB);
+ PHI->addIncoming(Pair.first.getScalarVal(), ContBB);
Builder.CreateCondBr(Pair.second, ExitBB, ContBB);
EmitBlock(ExitBB, /*IsFinished=*/true);
}
/// Emit a compare-and-exchange op for atomic type.
///
-std::pair<RValue, RValue> CodeGenFunction::EmitAtomicCompareExchange(
+std::pair<RValue, llvm::Value *> CodeGenFunction::EmitAtomicCompareExchange(
LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc,
llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak,
AggValueSlot Slot) {
@@ -1525,13 +1523,78 @@
Obj.getAddress()->getType()->getPointerElementType());
AtomicInfo Atomics(*this, Obj);
- auto Pair = Atomics.EmitAtomicCompareExchange(Expected, Desired, Success,
- Failure, IsWeak);
- return std::make_pair(Atomics.shouldUseLibcall()
- ? RValue::get(Pair.first)
- : Atomics.ConvertIntToValueOrAtomic(
- Pair.first, Slot, Loc, /*AsValue=*/true),
- RValue::get(Pair.second));
+ return Atomics.EmitAtomicCompareExchange(Expected, Desired, Success, Failure,
+ IsWeak);
+}
+
+void CodeGenFunction::EmitAtomicUpdate(
+ LValue LVal, llvm::AtomicOrdering AO,
+ const std::function<RValue(RValue)> &UpdateOp, bool IsVolatile) {
+ AtomicInfo Atomics(*this, LVal);
+ LValue AtomicLVal = Atomics.getAtomicLValue();
+
+ // Atomic load of prev value.
+ RValue OldRVal =
+ Atomics.EmitAtomicLoad(AggValueSlot::ignored(), SourceLocation(),
+ /*AsValue=*/false, AO, IsVolatile);
+ bool IsScalar = OldRVal.isScalar();
+ auto *OldVal =
+ IsScalar ? OldRVal.getScalarVal() : Atomics.convertRValueToInt(OldRVal);
+ // For non-simple lvalues perform compare-and-swap procedure.
+ auto *ContBB = createBasicBlock("atomic_cont");
+ auto *ExitBB = createBasicBlock("atomic_exit");
+ auto *CurBB = Builder.GetInsertBlock();
+ EmitBlock(ContBB);
+ llvm::PHINode *PHI = Builder.CreatePHI(OldVal->getType(),
+ /*NumReservedValues=*/2);
+ PHI->addIncoming(OldVal, CurBB);
+ RValue OriginalRValue =
+ IsScalar ? RValue::get(PHI) : Atomics.ConvertIntToValueOrAtomic(
+ PHI, AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false);
+ // Build new lvalue for temp address
+ LValue UpdateLVal;
+ llvm::Value *Ptr = nullptr;
+ RValue UpRVal;
+ if (AtomicLVal.isSimple()) {
+ UpRVal = OriginalRValue;
+ } else {
+ // Build new lvalue for temp address
+ Ptr = Atomics.materializeRValue(OriginalRValue);
+ if (AtomicLVal.isBitField())
+ UpdateLVal =
+ LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(),
+ AtomicLVal.getType(), AtomicLVal.getAlignment());
+ else if (AtomicLVal.isVectorElt())
+ UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(),
+ AtomicLVal.getType(),
+ AtomicLVal.getAlignment());
+ else {
+ assert(AtomicLVal.isExtVectorElt());
+ UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(),
+ AtomicLVal.getType(),
+ AtomicLVal.getAlignment());
+ }
+ UpdateLVal.setTBAAInfo(LVal.getTBAAInfo());
+ UpRVal = EmitLoadOfLValue(UpdateLVal, SourceLocation());
+ }
+ // Store new value in the corresponding memory area
+ RValue NewRVal = UpdateOp(UpRVal);
+ if (!AtomicLVal.isSimple()) {
+ EmitStoreThroughLValue(NewRVal, UpdateLVal);
+ // Load new value
+ NewRVal = RValue::get(
+ EmitLoadOfScalar(Ptr, AtomicLVal.isVolatile(),
+ Atomics.getAtomicAlignment().getQuantity(),
+ Atomics.getAtomicType(), SourceLocation()));
+ }
+ // Try to write new value using cmpxchg operation
+ auto Pair = Atomics.EmitAtomicCompareExchange(OriginalRValue, NewRVal, AO);
+ OldVal = IsScalar ? Pair.first.getScalarVal()
+ : Atomics.convertRValueToInt(Pair.first);
+ PHI->addIncoming(OldVal, ContBB);
+ Builder.CreateCondBr(Pair.second, ExitBB, ContBB);
+ EmitBlock(ExitBB, /*IsFinished=*/true);
}
void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 7b8e839..202996b 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -621,8 +621,8 @@
}
// GEP down to the address.
- llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address,
- capture.getIndex());
+ llvm::Value *addr = CGF.Builder.CreateStructGEP(
+ blockInfo.StructureType, blockInfo.Address, capture.getIndex());
// We can use that GEP as the dominating IP.
if (!blockInfo.DominatingIP)
@@ -721,6 +721,7 @@
// Build the block descriptor.
llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo);
+ llvm::Type *blockTy = blockInfo.StructureType;
llvm::AllocaInst *blockAddr = blockInfo.Address;
assert(blockAddr && "block has no address!");
@@ -732,14 +733,17 @@
if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
// Initialize the block literal.
- Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa"));
- Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(blockAddr, 1, "block.flags"));
- Builder.CreateStore(llvm::ConstantInt::get(IntTy, 0),
- Builder.CreateStructGEP(blockAddr, 2, "block.reserved"));
- Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3,
- "block.invoke"));
- Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4,
+ Builder.CreateStore(
+ isa, Builder.CreateStructGEP(blockTy, blockAddr, 0, "block.isa"));
+ Builder.CreateStore(
+ llvm::ConstantInt::get(IntTy, flags.getBitMask()),
+ Builder.CreateStructGEP(blockTy, blockAddr, 1, "block.flags"));
+ Builder.CreateStore(
+ llvm::ConstantInt::get(IntTy, 0),
+ Builder.CreateStructGEP(blockTy, blockAddr, 2, "block.reserved"));
+ Builder.CreateStore(
+ blockFn, Builder.CreateStructGEP(blockTy, blockAddr, 3, "block.invoke"));
+ Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockTy, blockAddr, 4,
"block.descriptor"));
// Finally, capture all the values into the block.
@@ -747,9 +751,8 @@
// First, 'this'.
if (blockDecl->capturesCXXThis()) {
- llvm::Value *addr = Builder.CreateStructGEP(blockAddr,
- blockInfo.CXXThisIndex,
- "block.captured-this.addr");
+ llvm::Value *addr = Builder.CreateStructGEP(
+ blockTy, blockAddr, blockInfo.CXXThisIndex, "block.captured-this.addr");
Builder.CreateStore(LoadCXXThis(), addr);
}
@@ -766,9 +769,8 @@
// This will be a [[type]]*, except that a byref entry will just be
// an i8**.
- llvm::Value *blockField =
- Builder.CreateStructGEP(blockAddr, capture.getIndex(),
- "block.captured");
+ llvm::Value *blockField = Builder.CreateStructGEP(
+ blockTy, blockAddr, capture.getIndex(), "block.captured");
// Compute the address of the thing we're going to move into the
// block literal.
@@ -779,7 +781,7 @@
BlockInfo->getCapture(variable);
// This is a [[type]]*, except that a byref entry wil just be an i8**.
- src = Builder.CreateStructGEP(LoadBlockStruct(),
+ src = Builder.CreateStructGEP(BlockInfo->StructureType, LoadBlockStruct(),
enclosingCapture.getIndex(),
"block.capture.addr");
} else if (blockDecl->isConversionFromLambda()) {
@@ -964,7 +966,8 @@
Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
// Get the function pointer from the literal.
- llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3);
+ llvm::Value *FuncPtr = Builder.CreateStructGEP(
+ CGM.getGenericBlockLiteralType(), BlockLiteral, 3);
BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy);
@@ -1004,26 +1007,27 @@
if (capture.isConstant()) return LocalDeclMap[variable];
llvm::Value *addr =
- Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(),
- "block.capture.addr");
+ Builder.CreateStructGEP(BlockInfo->StructureType, LoadBlockStruct(),
+ capture.getIndex(), "block.capture.addr");
if (isByRef) {
// addr should be a void** right now. Load, then cast the result
// to byref*.
addr = Builder.CreateLoad(addr);
- llvm::PointerType *byrefPointerType
- = llvm::PointerType::get(BuildByRefType(variable), 0);
+ auto *byrefType = BuildByRefType(variable);
+ llvm::PointerType *byrefPointerType = llvm::PointerType::get(byrefType, 0);
addr = Builder.CreateBitCast(addr, byrefPointerType,
"byref.addr");
// Follow the forwarding pointer.
- addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding");
+ addr = Builder.CreateStructGEP(byrefType, addr, 1, "byref.forwarding");
addr = Builder.CreateLoad(addr, "byref.addr.forwarded");
// Cast back to byref* and GEP over to the actual object.
addr = Builder.CreateBitCast(addr, byrefPointerType);
- addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable),
+ addr = Builder.CreateStructGEP(byrefType, addr,
+ getByRefValueLLVMField(variable).second,
variable->getNameAsString());
}
@@ -1185,9 +1189,9 @@
// If we have a C++ 'this' reference, go ahead and force it into
// existence now.
if (blockDecl->capturesCXXThis()) {
- llvm::Value *addr = Builder.CreateStructGEP(BlockPointer,
- blockInfo.CXXThisIndex,
- "block.captured-this");
+ llvm::Value *addr =
+ Builder.CreateStructGEP(blockInfo.StructureType, BlockPointer,
+ blockInfo.CXXThisIndex, "block.captured-this");
CXXThisValue = Builder.CreateLoad(addr, "this");
}
@@ -1402,8 +1406,10 @@
}
unsigned index = capture.getIndex();
- llvm::Value *srcField = Builder.CreateStructGEP(src, index);
- llvm::Value *dstField = Builder.CreateStructGEP(dst, index);
+ llvm::Value *srcField =
+ Builder.CreateStructGEP(blockInfo.StructureType, src, index);
+ llvm::Value *dstField =
+ Builder.CreateStructGEP(blockInfo.StructureType, dst, index);
// If there's an explicit copy expression, we do that.
if (copyExpr) {
@@ -1560,7 +1566,8 @@
}
unsigned index = capture.getIndex();
- llvm::Value *srcField = Builder.CreateStructGEP(src, index);
+ llvm::Value *srcField =
+ Builder.CreateStructGEP(blockInfo.StructureType, src, index);
// If there's an explicit copy expression, we do that.
if (dtor) {
@@ -1799,13 +1806,15 @@
llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst);
destField = CGF.Builder.CreateLoad(destField);
destField = CGF.Builder.CreateBitCast(destField, byrefPtrType);
- destField = CGF.Builder.CreateStructGEP(destField, valueFieldIndex, "x");
+ destField = CGF.Builder.CreateStructGEP(&byrefType, destField,
+ valueFieldIndex, "x");
// src->x
llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src);
srcField = CGF.Builder.CreateLoad(srcField);
srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType);
- srcField = CGF.Builder.CreateStructGEP(srcField, valueFieldIndex, "x");
+ srcField =
+ CGF.Builder.CreateStructGEP(&byrefType, srcField, valueFieldIndex, "x");
byrefInfo.emitCopy(CGF, destField, srcField);
}
@@ -1866,7 +1875,7 @@
llvm::Value *V = CGF.GetAddrOfLocalVar(&src);
V = CGF.Builder.CreateLoad(V);
V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0));
- V = CGF.Builder.CreateStructGEP(V, byrefValueIndex, "x");
+ V = CGF.Builder.CreateStructGEP(&byrefType, V, byrefValueIndex, "x");
byrefInfo.emitDispose(CGF, V);
}
@@ -1923,7 +1932,7 @@
const VarDecl &var = *emission.Variable;
QualType type = var.getType();
- unsigned byrefValueIndex = getByRefValueLLVMField(&var);
+ unsigned byrefValueIndex = getByRefValueLLVMField(&var).second;
if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var);
@@ -1993,18 +2002,20 @@
return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
}
-unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
+std::pair<llvm::Type *, unsigned>
+CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
assert(ByRefValueInfo.count(VD) && "Did not find value!");
-
- return ByRefValueInfo.find(VD)->second.second;
+
+ return ByRefValueInfo.find(VD)->second;
}
llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
const VarDecl *V) {
- llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding");
+ auto P = getByRefValueLLVMField(V);
+ llvm::Value *Loc =
+ Builder.CreateStructGEP(P.first, BaseAddr, 1, "forwarding");
Loc = Builder.CreateLoad(Loc);
- Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V),
- V->getNameAsString());
+ Loc = Builder.CreateStructGEP(P.first, Loc, P.second, V->getNameAsString());
return Loc;
}
@@ -2141,11 +2152,12 @@
if (type.isObjCGCWeak())
isa = 1;
V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
- Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa"));
+ Builder.CreateStore(V,
+ Builder.CreateStructGEP(nullptr, addr, 0, "byref.isa"));
// Store the address of the variable into its own forwarding pointer.
- Builder.CreateStore(addr,
- Builder.CreateStructGEP(addr, 1, "byref.forwarding"));
+ Builder.CreateStore(
+ addr, Builder.CreateStructGEP(nullptr, addr, 1, "byref.forwarding"));
// Blocks ABI:
// c) the flags field is set to either 0 if no helper functions are
@@ -2191,25 +2203,26 @@
printf("\n");
}
}
-
+
Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(addr, 2, "byref.flags"));
+ Builder.CreateStructGEP(nullptr, addr, 2, "byref.flags"));
CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType);
V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity());
- Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size"));
+ Builder.CreateStore(V,
+ Builder.CreateStructGEP(nullptr, addr, 3, "byref.size"));
if (helpers) {
- llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4);
+ llvm::Value *copy_helper = Builder.CreateStructGEP(nullptr, addr, 4);
Builder.CreateStore(helpers->CopyHelper, copy_helper);
- llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5);
+ llvm::Value *destroy_helper = Builder.CreateStructGEP(nullptr, addr, 5);
Builder.CreateStore(helpers->DisposeHelper, destroy_helper);
}
if (ByRefHasLifetime && HasByrefExtendedLayout) {
llvm::Constant* ByrefLayoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);
- llvm::Value *ByrefInfoAddr = Builder.CreateStructGEP(addr, helpers ? 6 : 4,
- "byref.layout");
+ llvm::Value *ByrefInfoAddr =
+ Builder.CreateStructGEP(nullptr, addr, helpers ? 6 : 4, "byref.layout");
// cast destination to pointer to source type.
llvm::Type *DesTy = ByrefLayoutInfo->getType();
DesTy = DesTy->getPointerTo();
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 35597fe..2653d7c 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -1865,6 +1865,8 @@
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
return EmitR600BuiltinExpr(BuiltinID, E);
+ case llvm::Triple::systemz:
+ return EmitSystemZBuiltinExpr(BuiltinID, E);
default:
return nullptr;
}
@@ -3105,7 +3107,7 @@
Indices.push_back(Builder.getInt32(i+vi));
Indices.push_back(Builder.getInt32(i+e+vi));
}
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vtrn");
SV = Builder.CreateStore(SV, Addr);
@@ -3133,7 +3135,7 @@
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
Indices.push_back(ConstantInt::get(Int32Ty, 2*i+vi));
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vuzp");
SV = Builder.CreateStore(SV, Addr);
@@ -3153,7 +3155,7 @@
Indices.push_back(ConstantInt::get(Int32Ty, (i + vi*e) >> 1));
Indices.push_back(ConstantInt::get(Int32Ty, ((i + vi*e) >> 1)+e));
}
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vzip");
SV = Builder.CreateStore(SV, Addr);
@@ -5768,7 +5770,7 @@
Indices.push_back(ConstantInt::get(Int32Ty, i+vi));
Indices.push_back(ConstantInt::get(Int32Ty, i+e+vi));
}
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vtrn");
SV = Builder.CreateStore(SV, Addr);
@@ -5787,7 +5789,7 @@
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
Indices.push_back(ConstantInt::get(Int32Ty, 2*i+vi));
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vuzp");
SV = Builder.CreateStore(SV, Addr);
@@ -5807,7 +5809,7 @@
Indices.push_back(ConstantInt::get(Int32Ty, (i + vi*e) >> 1));
Indices.push_back(ConstantInt::get(Int32Ty, ((i + vi*e) >> 1)+e));
}
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vzip");
SV = Builder.CreateStore(SV, Addr);
@@ -6371,119 +6373,6 @@
llvm::Function *F = CGM.getIntrinsic(ID);
return Builder.CreateCall(F, Ops, "");
}
-
- // P8 Crypto builtins
- case PPC::BI__builtin_altivec_crypto_vshasigmaw:
- case PPC::BI__builtin_altivec_crypto_vshasigmad:
- {
- ConstantInt *CI1 = dyn_cast<ConstantInt>(Ops[1]);
- ConstantInt *CI2 = dyn_cast<ConstantInt>(Ops[2]);
- assert(CI1 && CI2);
- if (CI1->getZExtValue() > 1) {
- CGM.Error(E->getArg(1)->getExprLoc(),
- "argument out of range (should be 0-1).");
- return llvm::UndefValue::get(Ops[0]->getType());
- }
- if (CI2->getZExtValue() > 15) {
- CGM.Error(E->getArg(2)->getExprLoc(),
- "argument out of range (should be 0-15).");
- return llvm::UndefValue::get(Ops[0]->getType());
- }
- switch (BuiltinID) {
- default: llvm_unreachable("Unsupported sigma intrinsic!");
- case PPC::BI__builtin_altivec_crypto_vshasigmaw:
- ID = Intrinsic::ppc_altivec_crypto_vshasigmaw;
- break;
- case PPC::BI__builtin_altivec_crypto_vshasigmad:
- ID = Intrinsic::ppc_altivec_crypto_vshasigmad;
- break;
- }
- llvm::Function *F = CGM.getIntrinsic(ID);
- return Builder.CreateCall(F, Ops, "");
- }
-
- // HTM builtins
- case PPC::BI__builtin_tbegin:
- case PPC::BI__builtin_tend:
- case PPC::BI__builtin_tsr: {
- unsigned int MaxValue;
- // The HTM instructions only accept one argument and with limited range.
- ConstantInt *CI = dyn_cast<ConstantInt>(Ops[0]);
- assert(CI);
- switch (BuiltinID) {
- case PPC::BI__builtin_tbegin:
- ID = Intrinsic::ppc_tbegin;
- MaxValue = 1;
- break;
- case PPC::BI__builtin_tend:
- ID = Intrinsic::ppc_tend;
- MaxValue = 1;
- break;
- case PPC::BI__builtin_tsr:
- ID = Intrinsic::ppc_tsr;
- MaxValue = 7;
- break;
- }
- if (CI->getZExtValue() > MaxValue) {
- std::stringstream ss;
- ss << "argument out of range (should be 0 or " << MaxValue << ")";
- CGM.Error(E->getArg(0)->getExprLoc(), ss.str());
- return llvm::UndefValue::get(Ops[0]->getType());
- }
-
- llvm::Function *F = CGM.getIntrinsic(ID);
- return Builder.CreateCall(F, Ops, "");
- }
- case PPC::BI__builtin_tabortdc:
- case PPC::BI__builtin_tabortwc: {
- // For wd and dc variant of tabort first argument must be a 5-bit constant
- // integer
- ConstantInt *CI = dyn_cast<ConstantInt>(Ops[0]);
- assert(CI);
- if (CI->getZExtValue() > 31) {
- CGM.ErrorUnsupported(E->getArg(0), "argument out of range (should be 0-31)");
- return llvm::UndefValue::get(Ops[0]->getType());
- }
- switch (BuiltinID) {
- case PPC::BI__builtin_tabortdc:
- ID = Intrinsic::ppc_tabortdc;
- break;
- case PPC::BI__builtin_tabortwc:
- ID = Intrinsic::ppc_tabortwc;
- break;
- }
- llvm::Function *F = CGM.getIntrinsic(ID);
- return Builder.CreateCall(F, Ops, "");
- }
- case PPC::BI__builtin_tabortdci:
- case PPC::BI__builtin_tabortwci: {
- // For wd and dc variant of tabort first and third argument must be a
- // 5-bit constant integer
- ConstantInt *CI = dyn_cast<ConstantInt>(Ops[0]);
- assert(CI);
- if (CI->getZExtValue() > 31) {
- CGM.ErrorUnsupported(E->getArg(0), "argument out of range (should be 0-31)");
- return llvm::UndefValue::get(Ops[0]->getType());
- }
- CI = dyn_cast<ConstantInt>(Ops[2]);
- assert(CI);
- if (CI->getZExtValue() > 31) {
- CGM.ErrorUnsupported(E->getArg(2), "argument out of range (should be 0-31)");
- return llvm::UndefValue::get(Ops[2]->getType());
- }
- switch (BuiltinID) {
- default: llvm_unreachable("Unsupported htm intrinsic!");
- case PPC::BI__builtin_tabortdci:
- ID = Intrinsic::ppc_tabortdci;
- break;
- case PPC::BI__builtin_tabortwci:
- ID = Intrinsic::ppc_tabortwci;
- break;
- }
- llvm::Function *F = CGM.getIntrinsic(ID);
- return Builder.CreateCall(F, Ops, "");
- }
-
}
}
@@ -6588,3 +6477,41 @@
return nullptr;
}
}
+
+Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ switch (BuiltinID) {
+ case SystemZ::BI__builtin_tbegin: {
+ Value *TDB = EmitScalarExpr(E->getArg(0));
+ Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_tbegin);
+ return Builder.CreateCall2(F, TDB, Control);
+ }
+ case SystemZ::BI__builtin_tbegin_nofloat: {
+ Value *TDB = EmitScalarExpr(E->getArg(0));
+ Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_tbegin_nofloat);
+ return Builder.CreateCall2(F, TDB, Control);
+ }
+ case SystemZ::BI__builtin_tbeginc: {
+ Value *TDB = llvm::ConstantPointerNull::get(Int8PtrTy);
+ Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff08);
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_tbeginc);
+ return Builder.CreateCall2(F, TDB, Control);
+ }
+ case SystemZ::BI__builtin_tabort: {
+ Value *Data = EmitScalarExpr(E->getArg(0));
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_tabort);
+ return Builder.CreateCall(F, Builder.CreateSExt(Data, Int64Ty, "tabort"));
+ }
+ case SystemZ::BI__builtin_non_tx_store: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *Data = EmitScalarExpr(E->getArg(1));
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_ntstg);
+ return Builder.CreateCall2(F, Data, Address);
+ }
+
+ default:
+ return nullptr;
+ }
+}
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index b6a94f9..2c73921 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -226,7 +226,7 @@
virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0;
virtual llvm::Constant *
- getAddrOfCXXHandlerMapEntry(QualType Ty, QualType CatchHandlerType) = 0;
+ getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) = 0;
virtual bool shouldTypeidBeNullChecked(bool IsDeref,
QualType SrcRecordTy) = 0;
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index d397761..c031bd7 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -734,7 +734,8 @@
auto Exp = getTypeExpansion(Ty, getContext());
if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
for (int i = 0, n = CAExp->NumElts; i < n; i++) {
- llvm::Value *EltAddr = Builder.CreateConstGEP2_32(LV.getAddress(), 0, i);
+ llvm::Value *EltAddr =
+ Builder.CreateConstGEP2_32(nullptr, LV.getAddress(), 0, i);
LValue LV = MakeAddrLValue(EltAddr, CAExp->EltTy);
ExpandTypeFromArgs(CAExp->EltTy, LV, AI);
}
@@ -756,10 +757,12 @@
ExpandTypeFromArgs(FD->getType(), SubLV, AI);
}
} else if (auto CExp = dyn_cast<ComplexExpansion>(Exp.get())) {
- llvm::Value *RealAddr = Builder.CreateStructGEP(LV.getAddress(), 0, "real");
+ llvm::Value *RealAddr =
+ Builder.CreateStructGEP(nullptr, LV.getAddress(), 0, "real");
EmitStoreThroughLValue(RValue::get(*AI++),
MakeAddrLValue(RealAddr, CExp->EltTy));
- llvm::Value *ImagAddr = Builder.CreateStructGEP(LV.getAddress(), 1, "imag");
+ llvm::Value *ImagAddr =
+ Builder.CreateStructGEP(nullptr, LV.getAddress(), 1, "imag");
EmitStoreThroughLValue(RValue::get(*AI++),
MakeAddrLValue(ImagAddr, CExp->EltTy));
} else {
@@ -775,7 +778,7 @@
if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
llvm::Value *Addr = RV.getAggregateAddr();
for (int i = 0, n = CAExp->NumElts; i < n; i++) {
- llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, i);
+ llvm::Value *EltAddr = Builder.CreateConstGEP2_32(nullptr, Addr, 0, i);
RValue EltRV =
convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation());
ExpandTypeToArgs(CAExp->EltTy, EltRV, IRFuncTy, IRCallArgs, IRCallArgPos);
@@ -843,7 +846,7 @@
return SrcPtr;
// GEP into the first element.
- SrcPtr = CGF.Builder.CreateConstGEP2_32(SrcPtr, 0, 0, "coerce.dive");
+ SrcPtr = CGF.Builder.CreateConstGEP2_32(SrcSTy, SrcPtr, 0, 0, "coerce.dive");
// If the first element is a struct, recurse.
llvm::Type *SrcTy =
@@ -981,7 +984,7 @@
if (llvm::StructType *STy =
dyn_cast<llvm::StructType>(Val->getType())) {
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- llvm::Value *EltPtr = CGF.Builder.CreateConstGEP2_32(DestPtr, 0, i);
+ llvm::Value *EltPtr = CGF.Builder.CreateConstGEP2_32(STy, DestPtr, 0, i);
llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i);
llvm::StoreInst *SI = CGF.Builder.CreateStore(Elt, EltPtr,
DestIsVolatile);
@@ -1772,8 +1775,9 @@
switch (ArgI.getKind()) {
case ABIArgInfo::InAlloca: {
assert(NumIRArgs == 0);
- llvm::Value *V = Builder.CreateStructGEP(
- ArgStruct, ArgI.getInAllocaFieldIndex(), Arg->getName());
+ llvm::Value *V =
+ Builder.CreateStructGEP(FI.getArgStruct(), ArgStruct,
+ ArgI.getInAllocaFieldIndex(), Arg->getName());
ArgVals.push_back(ValueAndIsPtr(V, HavePointer));
break;
}
@@ -1939,7 +1943,7 @@
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = ArgI.getDirectOffset()) {
Ptr = Builder.CreateBitCast(Ptr, Builder.getInt8PtrTy());
- Ptr = Builder.CreateConstGEP1_32(Ptr, Offs);
+ Ptr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), Ptr, Offs);
Ptr = Builder.CreateBitCast(Ptr,
llvm::PointerType::getUnqual(ArgI.getCoerceToType()));
}
@@ -1961,7 +1965,7 @@
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
auto AI = FnArgs[FirstIRArg + i];
AI->setName(Arg->getName() + ".coerce" + Twine(i));
- llvm::Value *EltPtr = Builder.CreateConstGEP2_32(Ptr, 0, i);
+ llvm::Value *EltPtr = Builder.CreateConstGEP2_32(STy, Ptr, 0, i);
Builder.CreateStore(AI, EltPtr);
}
} else {
@@ -1974,7 +1978,8 @@
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
auto AI = FnArgs[FirstIRArg + i];
AI->setName(Arg->getName() + ".coerce" + Twine(i));
- llvm::Value *EltPtr = Builder.CreateConstGEP2_32(TempV, 0, i);
+ llvm::Value *EltPtr =
+ Builder.CreateConstGEP2_32(ArgI.getCoerceToType(), TempV, 0, i);
Builder.CreateStore(AI, EltPtr);
}
@@ -2269,8 +2274,8 @@
llvm::Function::arg_iterator EI = CurFn->arg_end();
--EI;
llvm::Value *ArgStruct = EI;
- llvm::Value *SRet =
- Builder.CreateStructGEP(ArgStruct, RetAI.getInAllocaFieldIndex());
+ llvm::Value *SRet = Builder.CreateStructGEP(
+ nullptr, ArgStruct, RetAI.getInAllocaFieldIndex());
RV = Builder.CreateLoad(SRet, "sret");
}
break;
@@ -2334,7 +2339,7 @@
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = RetAI.getDirectOffset()) {
V = Builder.CreateBitCast(V, Builder.getInt8PtrTy());
- V = Builder.CreateConstGEP1_32(V, Offs);
+ V = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), V, Offs);
V = Builder.CreateBitCast(V,
llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
}
@@ -2380,7 +2385,7 @@
Ret = Builder.CreateRetVoid();
}
- if (!RetDbgLoc.isUnknown())
+ if (RetDbgLoc)
Ret->setDebugLoc(std::move(RetDbgLoc));
}
@@ -2992,7 +2997,7 @@
if (CGM.getLangOpts().ObjCAutoRefCount)
AddObjCARCExceptionMetadata(Inst);
- return Inst;
+ return llvm::CallSite(Inst);
}
/// \brief Store a non-aggregate value to an address to initialize it. For
@@ -3029,7 +3034,7 @@
// If we're using inalloca, insert the allocation after the stack save.
// FIXME: Do this earlier rather than hacking it in here!
- llvm::Value *ArgMemory = nullptr;
+ llvm::AllocaInst *ArgMemory = nullptr;
if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) {
llvm::Instruction *IP = CallArgs.getStackBase();
llvm::AllocaInst *AI;
@@ -3058,7 +3063,8 @@
IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr;
} else {
llvm::Value *Addr =
- Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex());
+ Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
+ RetAI.getInAllocaFieldIndex());
Builder.CreateStore(SRetPtr, Addr);
}
}
@@ -3092,14 +3098,16 @@
cast<llvm::Instruction>(RV.getAggregateAddr());
CGBuilderTy::InsertPoint IP = Builder.saveIP();
Builder.SetInsertPoint(Placeholder);
- llvm::Value *Addr = Builder.CreateStructGEP(
- ArgMemory, ArgInfo.getInAllocaFieldIndex());
+ llvm::Value *Addr =
+ Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
+ ArgInfo.getInAllocaFieldIndex());
Builder.restoreIP(IP);
deferPlaceholderReplacement(Placeholder, Addr);
} else {
// Store the RValue into the argument struct.
llvm::Value *Addr =
- Builder.CreateStructGEP(ArgMemory, ArgInfo.getInAllocaFieldIndex());
+ Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
+ ArgInfo.getInAllocaFieldIndex());
unsigned AS = Addr->getType()->getPointerAddressSpace();
llvm::Type *MemType = ConvertTypeForMem(I->Ty)->getPointerTo(AS);
// There are some cases where a trivial bitcast is not avoidable. The
@@ -3201,7 +3209,7 @@
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = ArgInfo.getDirectOffset()) {
SrcPtr = Builder.CreateBitCast(SrcPtr, Builder.getInt8PtrTy());
- SrcPtr = Builder.CreateConstGEP1_32(SrcPtr, Offs);
+ SrcPtr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), SrcPtr, Offs);
SrcPtr = Builder.CreateBitCast(SrcPtr,
llvm::PointerType::getUnqual(ArgInfo.getCoerceToType()));
@@ -3233,7 +3241,7 @@
assert(NumIRArgs == STy->getNumElements());
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- llvm::Value *EltPtr = Builder.CreateConstGEP2_32(SrcPtr, 0, i);
+ llvm::Value *EltPtr = Builder.CreateConstGEP2_32(STy, SrcPtr, 0, i);
llvm::LoadInst *LI = Builder.CreateLoad(EltPtr);
// We don't know what we're loading from.
LI->setAlignment(1);
@@ -3463,7 +3471,8 @@
llvm::Value *StorePtr = DestPtr;
if (unsigned Offs = RetAI.getDirectOffset()) {
StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy());
- StorePtr = Builder.CreateConstGEP1_32(StorePtr, Offs);
+ StorePtr =
+ Builder.CreateConstGEP1_32(Builder.getInt8Ty(), StorePtr, Offs);
StorePtr = Builder.CreateBitCast(StorePtr,
llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
}
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 84d6437..bd15c12 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -2088,14 +2088,6 @@
return VTable;
}
-void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXMethodDecl *MD,
- llvm::Value *VTable) {
- if (!SanOpts.has(SanitizerKind::CFIVptr))
- return;
-
- EmitVTablePtrCheck(MD->getParent(), VTable);
-}
-
// If a class has a single non-virtual base and does not introduce or override
// virtual member functions or fields, it will have the same layout as its base.
// This function returns the least derived such class.
@@ -2131,6 +2123,15 @@
RD->bases_begin()->getType()->getAsCXXRecordDecl());
}
+void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXMethodDecl *MD,
+ llvm::Value *VTable) {
+ const CXXRecordDecl *ClassDecl = MD->getParent();
+ if (!SanOpts.has(SanitizerKind::CFICastStrict))
+ ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
+
+ EmitVTablePtrCheck(ClassDecl, VTable);
+}
+
void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T,
llvm::Value *Derived,
bool MayBeNull) {
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index 566befc..299969a 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -52,8 +52,10 @@
llvm::StructType::get(V.first->getType(), V.second->getType(),
(void*) nullptr);
llvm::Value *addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex");
- CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0));
- CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1));
+ CGF.Builder.CreateStore(V.first,
+ CGF.Builder.CreateStructGEP(ComplexTy, addr, 0));
+ CGF.Builder.CreateStore(V.second,
+ CGF.Builder.CreateStructGEP(ComplexTy, addr, 1));
return saved_type(addr, ComplexAddress);
}
@@ -82,9 +84,9 @@
return RValue::getAggregate(CGF.Builder.CreateLoad(Value));
case ComplexAddress: {
llvm::Value *real =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 0));
+ CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(nullptr, Value, 0));
llvm::Value *imag =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 1));
+ CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(nullptr, Value, 1));
return RValue::getComplex(real, imag);
}
}
@@ -469,8 +471,14 @@
EHScopeStack::Cleanup *Fn,
EHScopeStack::Cleanup::Flags flags,
llvm::Value *ActiveFlag) {
- // EH cleanups always occur within a terminate scope.
- if (flags.isForEHCleanup()) CGF.EHStack.pushTerminate();
+ // Itanium EH cleanups occur within a terminate scope. Microsoft SEH doesn't
+ // have this behavior, and the Microsoft C++ runtime will call terminate for
+ // us if the cleanup throws.
+ bool PushedTerminate = false;
+ if (flags.isForEHCleanup() && !CGF.getTarget().getCXXABI().isMicrosoft()) {
+ CGF.EHStack.pushTerminate();
+ PushedTerminate = true;
+ }
// If there's an active flag, load it and skip the cleanup if it's
// false.
@@ -493,7 +501,8 @@
CGF.EmitBlock(ContBB);
// Leave the terminate scope.
- if (flags.isForEHCleanup()) CGF.EHStack.popTerminate();
+ if (PushedTerminate)
+ CGF.EHStack.popTerminate();
}
static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit,
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 186c522..4af49c2 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -92,7 +92,7 @@
: CGF(CGF) {
if (CGF.getDebugInfo()) {
OriginalLocation = CGF.Builder.getCurrentDebugLocation();
- if (!Loc.isUnknown())
+ if (Loc)
CGF.Builder.SetCurrentDebugLocation(std::move(Loc));
}
}
@@ -120,20 +120,20 @@
return;
SourceManager &SM = CGM.getContext().getSourceManager();
- llvm::DIScope Scope(LexicalBlockStack.back());
+ auto *Scope = cast<llvm::MDScope>(LexicalBlockStack.back());
PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
- if (PCLoc.isInvalid() || Scope.getFilename() == PCLoc.getFilename())
+ if (PCLoc.isInvalid() || Scope->getFilename() == PCLoc.getFilename())
return;
- if (Scope.isLexicalBlockFile()) {
- llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(Scope);
+ if (auto *LBF = dyn_cast<llvm::MDLexicalBlockFile>(Scope)) {
llvm::DIDescriptor D = DBuilder.createLexicalBlockFile(
- LBF.getScope(), getOrCreateFile(CurLoc));
+ LBF->getScope(), getOrCreateFile(CurLoc));
llvm::MDNode *N = D;
LexicalBlockStack.pop_back();
LexicalBlockStack.emplace_back(N);
- } else if (Scope.isLexicalBlock() || Scope.isSubprogram()) {
+ } else if (isa<llvm::MDLexicalBlock>(Scope) ||
+ isa<llvm::MDSubprogram>(Scope)) {
llvm::DIDescriptor D =
DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc));
llvm::MDNode *N = D;
@@ -150,7 +150,7 @@
auto I = RegionMap.find(Context);
if (I != RegionMap.end()) {
llvm::Metadata *V = I->second;
- return llvm::DIScope(dyn_cast_or_null<llvm::MDNode>(V));
+ return dyn_cast_or_null<llvm::MDScope>(V);
}
// Check namespace.
@@ -250,14 +250,14 @@
llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())
// If the location is not valid then use main input file.
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
// Cache the results.
const char *fname = PLoc.getFilename();
@@ -266,7 +266,7 @@
if (it != DIFileCache.end()) {
// Verify that the information still exists.
if (llvm::Metadata *V = it->second)
- return llvm::DIFile(cast<llvm::MDNode>(V));
+ return cast<llvm::MDFile>(V);
}
llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
@@ -277,7 +277,7 @@
/// getOrCreateMainFile - Get the file info for main compile unit.
llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
}
/// getLineNumber - Get line number for the location. If location is invalid
@@ -606,7 +606,7 @@
// FIXME: ODR should apply to ObjC++ exactly the same wasy it does to C++.
// For now, only apply ODR with C++.
const TagDecl *TD = Ty->getDecl();
- if (TheCU.getLanguage() != llvm::dwarf::DW_LANG_C_plus_plus ||
+ if (TheCU->getSourceLanguage() != llvm::dwarf::DW_LANG_C_plus_plus ||
!TD->isExternallyVisible())
return FullName;
// Microsoft Mangler does not have support for mangleCXXRTTIName yet.
@@ -637,12 +637,12 @@
}
// Creates a forward declaration for a RecordDecl in the given context.
-llvm::DICompositeType
+llvm::MDCompositeType *
CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
- llvm::DIDescriptor Ctx) {
+ llvm::MDScope *Ctx) {
const RecordDecl *RD = Ty->getDecl();
- if (llvm::DIType T = getTypeOrNull(CGM.getContext().getRecordType(RD)))
- return llvm::DICompositeType(T);
+ if (llvm::MDType *T = getTypeOrNull(CGM.getContext().getRecordType(RD)))
+ return cast<llvm::MDCompositeType>(T);
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
@@ -658,9 +658,9 @@
// Create the type.
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
- llvm::DICompositeType RetTy = DBuilder.createReplaceableCompositeType(
+ llvm::MDCompositeType *RetTy = DBuilder.createReplaceableCompositeType(
getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align,
- llvm::DIDescriptor::FlagFwdDecl, FullName);
+ llvm::DebugNode::FlagFwdDecl, FullName);
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
@@ -718,7 +718,7 @@
Elements = DBuilder.getOrCreateArray(EltTys);
EltTys.clear();
- unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
+ unsigned Flags = llvm::DebugNode::FlagAppleBlock;
unsigned LineNo = getLineNumber(CurLoc);
EltTy = DBuilder.createStructType(Unit, "__block_descriptor", Unit, LineNo,
@@ -777,31 +777,21 @@
Ty->getTemplateName().getAsTemplateDecl())->getTemplatedDecl();
SourceLocation Loc = AliasDecl->getLocation();
- llvm::DIFile File = getOrCreateFile(Loc);
- unsigned Line = getLineNumber(Loc);
-
- llvm::DIDescriptor Ctxt =
- getContextDescriptor(cast<Decl>(AliasDecl->getDeclContext()));
-
- return DBuilder.createTypedef(Src, internString(OS.str()), File, Line, Ctxt);
+ return DBuilder.createTypedef(
+ Src, internString(OS.str()), getOrCreateFile(Loc), getLineNumber(Loc),
+ getContextDescriptor(cast<Decl>(AliasDecl->getDeclContext())));
}
llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) {
- // Typedefs are derived from some other type. If we have a typedef of a
- // typedef, make sure to emit the whole chain.
- llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
// We don't set size information, but do specify where the typedef was
// declared.
SourceLocation Loc = Ty->getDecl()->getLocation();
- llvm::DIFile File = getOrCreateFile(Loc);
- unsigned Line = getLineNumber(Loc);
- const TypedefNameDecl *TyDecl = Ty->getDecl();
- llvm::DIDescriptor TypedefContext =
- getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
-
- return DBuilder.createTypedef(Src, TyDecl->getName(), File, Line,
- TypedefContext);
+ // Typedefs are derived from some other type.
+ return DBuilder.createTypedef(
+ getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit),
+ Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc),
+ getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext())));
}
llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
@@ -841,11 +831,11 @@
switch (Access) {
case clang::AS_private:
- return llvm::DIDescriptor::FlagPrivate;
+ return llvm::DebugNode::FlagPrivate;
case clang::AS_protected:
- return llvm::DIDescriptor::FlagProtected;
+ return llvm::DebugNode::FlagProtected;
case clang::AS_public:
- return llvm::DIDescriptor::FlagPublic;
+ return llvm::DebugNode::FlagPublic;
case clang::AS_none:
return 0;
}
@@ -1003,8 +993,7 @@
if (MI != StaticDataMemberCache.end()) {
assert(MI->second &&
"Static data member declaration should still exist");
- elements.push_back(
- llvm::DIDerivedType(cast<llvm::MDNode>(MI->second)));
+ elements.push_back(cast<llvm::MDDerivedTypeBase>(MI->second));
} else {
auto Field = CreateRecordStaticField(V, RecordTy, record);
elements.push_back(Field);
@@ -1022,27 +1011,29 @@
/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
/// function type is not updated to include implicit "this" pointer. Use this
/// routine to get a method type which includes "this" pointer.
-llvm::DICompositeType
+llvm::MDSubroutineType *
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile Unit) {
const FunctionProtoType *Func = Method->getType()->getAs<FunctionProtoType>();
if (Method->isStatic())
- return llvm::DICompositeType(getOrCreateType(QualType(Func, 0), Unit));
+ return cast_or_null<llvm::MDSubroutineType>(
+ getOrCreateType(QualType(Func, 0), Unit));
return getOrCreateInstanceMethodType(Method->getThisType(CGM.getContext()),
Func, Unit);
}
-llvm::DICompositeType CGDebugInfo::getOrCreateInstanceMethodType(
+llvm::MDSubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit) {
// Add "this" pointer.
- llvm::DITypeArray Args = llvm::DISubroutineType(
- getOrCreateType(QualType(Func, 0), Unit)).getTypeArray();
- assert(Args.getNumElements() && "Invalid number of arguments!");
+ llvm::DITypeArray Args(
+ cast<llvm::MDSubroutineType>(getOrCreateType(QualType(Func, 0), Unit))
+ ->getTypeArray());
+ assert(Args.size() && "Invalid number of arguments!");
SmallVector<llvm::Metadata *, 16> Elts;
// First element is always return type. For 'void' functions it is NULL.
- Elts.push_back(Args.getElement(0));
+ Elts.push_back(Args[0]);
// "this" pointer is always first argument.
const CXXRecordDecl *RD = ThisPtr->getPointeeCXXRecordDecl();
@@ -1070,16 +1061,16 @@
}
// Copy rest of the arguments.
- for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
- Elts.push_back(Args.getElement(i));
+ for (unsigned i = 1, e = Args.size(); i != e; ++i)
+ Elts.push_back(Args[i]);
llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
unsigned Flags = 0;
if (Func->getExtProtoInfo().RefQualifier == RQ_LValue)
- Flags |= llvm::DIDescriptor::FlagLValueReference;
+ Flags |= llvm::DebugNode::FlagLValueReference;
if (Func->getExtProtoInfo().RefQualifier == RQ_RValue)
- Flags |= llvm::DIDescriptor::FlagRValueReference;
+ Flags |= llvm::DebugNode::FlagRValueReference;
return DBuilder.createSubroutineType(Unit, EltTypeArray, Flags);
}
@@ -1103,7 +1094,7 @@
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
StringRef MethodName = getFunctionName(Method);
- llvm::DICompositeType MethodTy = getOrCreateMethodType(Method, Unit);
+ llvm::MDSubroutineType *MethodTy = getOrCreateMethodType(Method, Unit);
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
// make sense to give a single ctor/dtor a linkage name.
@@ -1143,29 +1134,29 @@
unsigned Flags = 0;
if (Method->isImplicit())
- Flags |= llvm::DIDescriptor::FlagArtificial;
+ Flags |= llvm::DebugNode::FlagArtificial;
Flags |= getAccessFlag(Method->getAccess(), Method->getParent());
if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
if (CXXC->isExplicit())
- Flags |= llvm::DIDescriptor::FlagExplicit;
+ Flags |= llvm::DebugNode::FlagExplicit;
} else if (const CXXConversionDecl *CXXC =
dyn_cast<CXXConversionDecl>(Method)) {
if (CXXC->isExplicit())
- Flags |= llvm::DIDescriptor::FlagExplicit;
+ Flags |= llvm::DebugNode::FlagExplicit;
}
if (Method->hasPrototype())
- Flags |= llvm::DIDescriptor::FlagPrototyped;
+ Flags |= llvm::DebugNode::FlagPrototyped;
if (Method->getRefQualifier() == RQ_LValue)
- Flags |= llvm::DIDescriptor::FlagLValueReference;
+ Flags |= llvm::DebugNode::FlagLValueReference;
if (Method->getRefQualifier() == RQ_RValue)
- Flags |= llvm::DIDescriptor::FlagRValueReference;
+ Flags |= llvm::DebugNode::FlagRValueReference;
llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
llvm::DISubprogram SP = DBuilder.createMethod(
RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine,
MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/false, Virtuality, VIndex, ContainingType, Flags,
- CGM.getLangOpts().Optimize, nullptr, TParamsArray);
+ CGM.getLangOpts().Optimize, nullptr, TParamsArray.get());
SPCache[Method->getCanonicalDecl()].reset(SP);
@@ -1240,7 +1231,7 @@
BaseOffset =
4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base);
}
- BFlags = llvm::DIDescriptor::FlagVirtual;
+ BFlags = llvm::DebugNode::FlagVirtual;
} else
BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
// FIXME: Inconsistent units for BaseOffset. It is in bytes when
@@ -1399,7 +1390,7 @@
/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
- if (VTablePtrType.isValid())
+ if (VTablePtrType)
return VTablePtrType;
ASTContext &Context = CGM.getContext();
@@ -1438,7 +1429,7 @@
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
llvm::DIType VPTR = DBuilder.createMemberType(
Unit, getVTableName(RD), Unit, 0, Size, 0, 0,
- llvm::DIDescriptor::FlagArtificial, getOrCreateVTablePtrType(Unit));
+ llvm::DebugNode::FlagArtificial, getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
}
@@ -1466,11 +1457,10 @@
QualType Ty = CGM.getContext().getEnumType(ED);
void *TyPtr = Ty.getAsOpaquePtr();
auto I = TypeCache.find(TyPtr);
- if (I == TypeCache.end() ||
- !llvm::DIType(cast<llvm::MDNode>(I->second)).isForwardDecl())
+ if (I == TypeCache.end() || !cast<llvm::MDType>(I->second)->isForwardDecl())
return;
llvm::DIType Res = CreateTypeDefinition(Ty->castAs<EnumType>());
- assert(!Res.isForwardDecl());
+ assert(!Res->isForwardDecl());
TypeCache[TyPtr].reset(Res);
}
@@ -1490,7 +1480,7 @@
QualType Ty = CGM.getContext().getRecordType(RD);
llvm::DIType T = getTypeOrNull(Ty);
- if (T && T.isForwardDecl())
+ if (T && T->isForwardDecl())
completeClassData(RD);
}
@@ -1500,11 +1490,10 @@
QualType Ty = CGM.getContext().getRecordType(RD);
void *TyPtr = Ty.getAsOpaquePtr();
auto I = TypeCache.find(TyPtr);
- if (I != TypeCache.end() &&
- !llvm::DIType(cast<llvm::MDNode>(I->second)).isForwardDecl())
+ if (I != TypeCache.end() && !cast<llvm::MDType>(I->second)->isForwardDecl())
return;
llvm::DIType Res = CreateTypeDefinition(Ty->castAs<RecordType>());
- assert(!Res.isForwardDecl());
+ assert(!Res->isForwardDecl());
TypeCache[TyPtr].reset(Res);
}
@@ -1554,7 +1543,7 @@
/// CreateType - get structure or union type.
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
- llvm::DICompositeType T(getTypeOrNull(QualType(Ty, 0)));
+ llvm::DIType T = cast_or_null<llvm::MDType>(getTypeOrNull(QualType(Ty, 0)));
if (T || shouldOmitDefinition(DebugKind, RD, CGM.getLangOpts())) {
if (!T)
T = getOrCreateRecordFwdDecl(
@@ -1578,9 +1567,8 @@
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
- llvm::DICompositeType FwdDecl(getOrCreateLimitedType(Ty, DefUnit));
- assert(FwdDecl.isCompositeType() &&
- "The debug type of a RecordType should be a llvm::DICompositeType");
+ auto *FwdDecl =
+ cast<llvm::MDCompositeType>(getOrCreateLimitedType(Ty, DefUnit));
const RecordDecl *D = RD->getDefinition();
if (!D || !D->isCompleteDefinition())
@@ -1619,8 +1607,8 @@
DBuilder.replaceArrays(FwdDecl, Elements);
if (FwdDecl->isTemporary())
- FwdDecl = llvm::DICompositeType(llvm::MDNode::replaceWithPermanent(
- llvm::TempMDNode(FwdDecl.get())));
+ FwdDecl =
+ llvm::MDNode::replaceWithPermanent(llvm::TempMDCompositeType(FwdDecl));
RegionMap[Ty->getDecl()].reset(FwdDecl);
return FwdDecl;
@@ -1667,7 +1655,8 @@
// Get overall information about the record type for the debug info.
llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
unsigned Line = getLineNumber(ID->getLocation());
- llvm::dwarf::SourceLanguage RuntimeLang = TheCU.getLanguage();
+ auto RuntimeLang =
+ static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage());
// If this is just a forward declaration return a special forward-declaration
// debug type since we won't be able to lay out the entire type.
@@ -1688,7 +1677,7 @@
ObjCInterfaceDecl *ID = Ty->getDecl();
llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
unsigned Line = getLineNumber(ID->getLocation());
- unsigned RuntimeLang = TheCU.getLanguage();
+ unsigned RuntimeLang = TheCU->getSourceLanguage();
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
@@ -1696,9 +1685,9 @@
unsigned Flags = 0;
if (ID->getImplementation())
- Flags |= llvm::DIDescriptor::FlagObjcClassComplete;
+ Flags |= llvm::DebugNode::FlagObjcClassComplete;
- llvm::DICompositeType RealDecl = DBuilder.createStructType(
+ llvm::MDCompositeType *RealDecl = DBuilder.createStructType(
Unit, ID->getName(), DefUnit, Line, Size, Align, Flags, llvm::DIType(),
llvm::DIArray(), RuntimeLang);
@@ -1706,7 +1695,7 @@
TypeCache[QTy.getAsOpaquePtr()].reset(RealDecl);
// Push the struct on region stack.
- LexicalBlockStack.emplace_back(static_cast<llvm::MDNode *>(RealDecl));
+ LexicalBlockStack.emplace_back(RealDecl);
RegionMap[Ty->getDecl()].reset(RealDecl);
// Convert all the elements.
@@ -1716,7 +1705,7 @@
if (SClass) {
llvm::DIType SClassTy =
getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
- if (!SClassTy.isValid())
+ if (!SClassTy)
return llvm::DIType();
llvm::DIType InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
@@ -1745,7 +1734,7 @@
for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field;
Field = Field->getNextIvar(), ++FieldNo) {
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- if (!FieldTy.isValid())
+ if (!FieldTy)
return llvm::DIType();
StringRef FieldName = Field->getName();
@@ -1788,11 +1777,11 @@
unsigned Flags = 0;
if (Field->getAccessControl() == ObjCIvarDecl::Protected)
- Flags = llvm::DIDescriptor::FlagProtected;
+ Flags = llvm::DebugNode::FlagProtected;
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
- Flags = llvm::DIDescriptor::FlagPrivate;
+ Flags = llvm::DebugNode::FlagPrivate;
else if (Field->getAccessControl() == ObjCIvarDecl::Public)
- Flags = llvm::DIDescriptor::FlagPublic;
+ Flags = llvm::DebugNode::FlagPublic;
llvm::MDNode *PropertyNode = nullptr;
if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {
@@ -1948,14 +1937,14 @@
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!ED->getDefinition()) {
- llvm::DIDescriptor EDContext;
- EDContext = getContextDescriptor(cast<Decl>(ED->getDeclContext()));
+ llvm::MDScope *EDContext =
+ getContextDescriptor(cast<Decl>(ED->getDeclContext()));
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
StringRef EDName = ED->getName();
llvm::DIType RetTy = DBuilder.createReplaceableCompositeType(
llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line,
- 0, Size, Align, llvm::DIDescriptor::FlagFwdDecl, FullName);
+ 0, Size, Align, llvm::DebugNode::FlagFwdDecl, FullName);
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
@@ -1989,7 +1978,7 @@
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
- llvm::DIDescriptor EnumContext =
+ llvm::MDScope *EnumContext =
getContextDescriptor(cast<Decl>(ED->getDeclContext()));
llvm::DIType ClassTy = ED->isFixed()
? getOrCreateType(ED->getIntegerType(), DefUnit)
@@ -2066,10 +2055,10 @@
if (it != TypeCache.end()) {
// Verify that the debug info still exists.
if (llvm::Metadata *V = it->second)
- return llvm::DIType(cast<llvm::MDNode>(V));
+ return cast<llvm::MDType>(V);
}
- return llvm::DIType();
+ return nullptr;
}
void CGDebugInfo::completeTemplateDefinition(
@@ -2218,21 +2207,21 @@
llvm::DIFile Unit) {
QualType QTy(Ty, 0);
- llvm::DICompositeType T(getTypeOrNull(QTy));
+ auto *T = cast_or_null<llvm::MDCompositeTypeBase>(getTypeOrNull(QTy));
// We may have cached a forward decl when we could have created
// a non-forward decl. Go ahead and create a non-forward decl
// now.
- if (T && !T.isForwardDecl())
+ if (T && !T->isForwardDecl())
return T;
// Otherwise create the type.
- llvm::DICompositeType Res = CreateLimitedType(Ty);
+ llvm::MDCompositeType *Res = CreateLimitedType(Ty);
// Propagate members from the declaration to the definition
// CreateType(const RecordType*) will overwrite this with the members in the
// correct order if the full type is needed.
- DBuilder.replaceArrays(Res, T ? T.getElements() : llvm::DIArray());
+ DBuilder.replaceArrays(Res, T ? T->getElements() : llvm::DIArray());
// And update the type cache.
TypeCache[QTy.getAsOpaquePtr()].reset(Res);
@@ -2240,7 +2229,7 @@
}
// TODO: Currently used for context chains when limiting debug info.
-llvm::DICompositeType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
+llvm::MDCompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
// Get overall information about the record type for the debug info.
@@ -2248,13 +2237,14 @@
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
- llvm::DIDescriptor RDContext =
+ llvm::MDScope *RDContext =
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
// If we ended up creating the type during the context chain construction,
// just return that.
- llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD)));
- if (T && (!T.isForwardDecl() || !RD->getDefinition()))
+ auto *T = cast_or_null<llvm::MDCompositeType>(
+ getTypeOrNull(CGM.getContext().getRecordType(RD)));
+ if (T && (!T->isForwardDecl() || !RD->getDefinition()))
return T;
// If this is just a forward or incomplete declaration, construct an
@@ -2265,12 +2255,12 @@
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- llvm::DICompositeType RealDecl;
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
- RealDecl = DBuilder.createReplaceableCompositeType(getTagForRecord(RD),
- RDName, RDContext, DefUnit, Line, 0, Size, Align, 0, FullName);
+ llvm::MDCompositeType *RealDecl = DBuilder.createReplaceableCompositeType(
+ getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, 0,
+ FullName);
RegionMap[Ty->getDecl()].reset(RealDecl);
TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);
@@ -2283,9 +2273,9 @@
}
void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
- llvm::DICompositeType RealDecl) {
+ llvm::MDCompositeType *RealDecl) {
// A class's primary base or the class itself contains the vtable.
- llvm::DICompositeType ContainingType;
+ llvm::MDCompositeType *ContainingType = nullptr;
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
// Seek non-virtual primary base root.
@@ -2297,7 +2287,7 @@
else
break;
}
- ContainingType = llvm::DICompositeType(
+ ContainingType = cast<llvm::MDCompositeType>(
getOrCreateType(QualType(PBase->getTypeForDecl(), 0),
getOrCreateFile(RD->getLocation())));
} else if (RD->isDynamicClass())
@@ -2318,18 +2308,15 @@
return Ty;
}
-void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD,
- llvm::DIFile Unit,
- StringRef &Name, StringRef &LinkageName,
- llvm::DIDescriptor &FDContext,
- llvm::DIArray &TParamsArray,
- unsigned &Flags) {
+void CGDebugInfo::collectFunctionDeclProps(
+ GlobalDecl GD, llvm::DIFile Unit, StringRef &Name, StringRef &LinkageName,
+ llvm::MDScope *&FDContext, llvm::DIArray &TParamsArray, unsigned &Flags) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
Name = getFunctionName(FD);
// Use mangled name as linkage name for C/C++ functions.
if (FD->hasPrototype()) {
LinkageName = CGM.getMangledName(GD);
- Flags |= llvm::DIDescriptor::FlagPrototyped;
+ Flags |= llvm::DebugNode::FlagPrototyped;
}
// No need to replicate the linkage name if it isn't different from the
// subprogram name, no need to have it at all unless coverage is enabled or
@@ -2355,7 +2342,7 @@
void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile &Unit,
unsigned &LineNo, QualType &T,
StringRef &Name, StringRef &LinkageName,
- llvm::DIDescriptor &VDContext) {
+ llvm::MDScope *&VDContext) {
Unit = getOrCreateFile(VD->getLocation());
LineNo = getLineNumber(VD->getLocation());
@@ -2404,7 +2391,7 @@
unsigned Flags = 0;
SourceLocation Loc = FD->getLocation();
llvm::DIFile Unit = getOrCreateFile(Loc);
- llvm::DIDescriptor DContext(Unit);
+ llvm::MDScope *DContext = Unit;
unsigned Line = getLineNumber(Loc);
collectFunctionDeclProps(FD, Unit, Name, LinkageName, DContext,
@@ -2416,17 +2403,15 @@
QualType FnType =
CGM.getContext().getFunctionType(FD->getReturnType(), ArgTypes,
FunctionProtoType::ExtProtoInfo());
- llvm::DISubprogram SP =
- DBuilder.createTempFunctionFwdDecl(DContext, Name, LinkageName, Unit, Line,
- getOrCreateFunctionType(FD, FnType, Unit),
- !FD->isExternallyVisible(),
- false /*declaration*/, 0, Flags,
- CGM.getLangOpts().Optimize, nullptr,
- TParamsArray, getFunctionDeclaration(FD));
+ llvm::MDSubprogram *SP = DBuilder.createTempFunctionFwdDecl(
+ DContext, Name, LinkageName, Unit, Line,
+ getOrCreateFunctionType(FD, FnType, Unit), !FD->isExternallyVisible(),
+ false /*declaration*/, 0, Flags, CGM.getLangOpts().Optimize, nullptr,
+ TParamsArray.get(), getFunctionDeclaration(FD));
const FunctionDecl *CanonDecl = cast<FunctionDecl>(FD->getCanonicalDecl());
- FwdDeclReplaceMap.emplace_back(
- std::piecewise_construct, std::make_tuple(CanonDecl),
- std::make_tuple(static_cast<llvm::Metadata *>(SP)));
+ FwdDeclReplaceMap.emplace_back(std::piecewise_construct,
+ std::make_tuple(CanonDecl),
+ std::make_tuple(SP));
return SP;
}
@@ -2436,7 +2421,7 @@
StringRef Name, LinkageName;
SourceLocation Loc = VD->getLocation();
llvm::DIFile Unit = getOrCreateFile(Loc);
- llvm::DIDescriptor DContext(Unit);
+ llvm::MDScope *DContext = Unit;
unsigned Line = getLineNumber(Loc);
collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext);
@@ -2452,7 +2437,7 @@
return GV;
}
-llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
+llvm::DebugNode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
// We only need a declaration (not a definition) of the type - so use whatever
// we would otherwise do to get a type for a pointee. (forward declarations in
// limited debug info, full definitions (if the type definition is available)
@@ -2463,7 +2448,7 @@
auto I = DeclCache.find(D->getCanonicalDecl());
if (I != DeclCache.end())
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(I->second));
+ return dyn_cast_or_null<llvm::DebugNode>(I->second);
// No definition for now. Emit a forward definition that might be
// merged with a potential upcoming definition.
@@ -2472,7 +2457,7 @@
else if (const auto *VD = dyn_cast<VarDecl>(D))
return getGlobalVariableForwardDeclaration(VD);
- return llvm::DIDescriptor();
+ return nullptr;
}
/// getFunctionDeclaration - Return debug info descriptor to describe method
@@ -2492,23 +2477,23 @@
if (MI == SPCache.end()) {
if (const CXXMethodDecl *MD =
dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) {
- llvm::DICompositeType T(S);
+ llvm::DICompositeType T = cast<llvm::MDCompositeType>(S);
llvm::DISubprogram SP =
CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T);
return SP;
}
}
if (MI != SPCache.end()) {
- llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(MI->second));
- if (SP.isSubprogram() && !SP.isDefinition())
+ auto *SP = dyn_cast_or_null<llvm::MDSubprogram>(MI->second);
+ if (SP && !SP->isDefinition())
return SP;
}
for (auto NextFD : FD->redecls()) {
auto MI = SPCache.find(NextFD->getCanonicalDecl());
if (MI != SPCache.end()) {
- llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(MI->second));
- if (SP.isSubprogram() && !SP.isDefinition())
+ auto *SP = dyn_cast_or_null<llvm::MDSubprogram>(MI->second);
+ if (SP && !SP->isDefinition())
return SP;
}
}
@@ -2517,9 +2502,9 @@
// getOrCreateFunctionType - Construct DIType. If it is a c++ method, include
// implicit parameter "this".
-llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
- QualType FnType,
- llvm::DIFile F) {
+llvm::MDSubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
+ QualType FnType,
+ llvm::DIFile F) {
if (!D || DebugKind <= CodeGenOptions::DebugLineTablesOnly)
// Create fake but valid subroutine type. Otherwise
// llvm::DISubprogram::Verify() would return false, and
@@ -2575,7 +2560,7 @@
return DBuilder.createSubroutineType(F, EltTypeArray);
}
- return llvm::DICompositeType(getOrCreateType(FnType, F));
+ return cast<llvm::MDSubroutineType>(getOrCreateType(FnType, F));
}
/// EmitFunctionStart - Constructs the debug code for entering a function.
@@ -2593,7 +2578,7 @@
unsigned Flags = 0;
llvm::DIFile Unit = getOrCreateFile(Loc);
- llvm::DIDescriptor FDContext(Unit);
+ llvm::MDScope *FDContext = Unit;
llvm::DIArray TParamsArray;
if (!HasDecl) {
// Use llvm function name.
@@ -2602,8 +2587,8 @@
// If there is a DISubprogram for this function available then use it.
auto FI = SPCache.find(FD->getCanonicalDecl());
if (FI != SPCache.end()) {
- llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(FI->second));
- if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) {
+ auto *SP = dyn_cast_or_null<llvm::MDSubprogram>(FI->second);
+ if (SP && SP->isDefinition()) {
llvm::MDNode *SPN = SP;
LexicalBlockStack.emplace_back(SPN);
RegionMap[D].reset(SP);
@@ -2614,17 +2599,17 @@
TParamsArray, Flags);
} else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
Name = getObjCMethodName(OMD);
- Flags |= llvm::DIDescriptor::FlagPrototyped;
+ Flags |= llvm::DebugNode::FlagPrototyped;
} else {
// Use llvm function name.
Name = Fn->getName();
- Flags |= llvm::DIDescriptor::FlagPrototyped;
+ Flags |= llvm::DebugNode::FlagPrototyped;
}
if (!Name.empty() && Name[0] == '\01')
Name = Name.substr(1);
if (!HasDecl || D->isImplicit()) {
- Flags |= llvm::DIDescriptor::FlagArtificial;
+ Flags |= llvm::DebugNode::FlagArtificial;
// Artificial functions without a location should not silently reuse CurLoc.
if (Loc.isInvalid())
CurLoc = SourceLocation();
@@ -2641,7 +2626,7 @@
FDContext, Name, LinkageName, Unit, LineNo,
getOrCreateFunctionType(D, FnType, Unit), Fn->hasInternalLinkage(),
true /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize, Fn,
- TParamsArray, getFunctionDeclaration(D));
+ TParamsArray.get(), getFunctionDeclaration(D));
// We might get here with a VarDecl in the case we're generating
// code for the initialization of globals. Do not record these decls
// as they will overwrite the actual VarDecl Decl in the cache.
@@ -2678,7 +2663,7 @@
if (!LexicalBlockStack.empty())
Back = LexicalBlockStack.back().get();
llvm::DIDescriptor D = DBuilder.createLexicalBlock(
- llvm::DIDescriptor(Back), getOrCreateFile(CurLoc), getLineNumber(CurLoc),
+ cast<llvm::MDScope>(Back), getOrCreateFile(CurLoc), getLineNumber(CurLoc),
getColumnNumber(CurLoc));
llvm::MDNode *DN = D;
LexicalBlockStack.emplace_back(DN);
@@ -2801,7 +2786,7 @@
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
- unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
+ unsigned Flags = llvm::DebugNode::FlagBlockByrefStruct;
return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
llvm::DIType(), Elements);
@@ -2842,20 +2827,20 @@
SmallVector<int64_t, 9> Expr;
unsigned Flags = 0;
if (VD->isImplicit())
- Flags |= llvm::DIDescriptor::FlagArtificial;
+ Flags |= llvm::DebugNode::FlagArtificial;
// If this is the first argument and it is implicit then
// give it an object pointer flag.
// FIXME: There has to be a better way to do this, but for static
// functions there won't be an implicit param at arg1 and
// otherwise it is 'self' or 'this'.
if (isa<ImplicitParamDecl>(VD) && ArgNo == 1)
- Flags |= llvm::DIDescriptor::FlagObjectPointer;
+ Flags |= llvm::DebugNode::FlagObjectPointer;
if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage))
if (Arg->getType()->isPointerTy() && !Arg->hasByValAttr() &&
!VD->getType()->isPointerType())
Expr.push_back(llvm::dwarf::DW_OP_deref);
- llvm::MDNode *Scope = LexicalBlockStack.back();
+ auto *Scope = cast<llvm::MDScope>(LexicalBlockStack.back());
StringRef Name = VD->getName();
if (!Name.empty()) {
@@ -2874,13 +2859,12 @@
// Create the descriptor for the variable.
llvm::DIVariable D = DBuilder.createLocalVariable(
- Tag, llvm::DIDescriptor(Scope), VD->getName(), Unit, Line, Ty, ArgNo);
+ Tag, Scope, VD->getName(), Unit, Line, Ty, ArgNo);
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
- Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
+ llvm::DebugLoc::get(Line, Column, Scope),
+ Builder.GetInsertBlock());
return;
} else if (isa<VariableArrayType>(VD->getType()))
Expr.push_back(llvm::dwarf::DW_OP_deref);
@@ -2899,28 +2883,27 @@
// Use VarDecl's Tag, Scope and Line number.
llvm::DIVariable D = DBuilder.createLocalVariable(
- Tag, llvm::DIDescriptor(Scope), FieldName, Unit, Line, FieldTy,
+ Tag, Scope, FieldName, Unit, Line, FieldTy,
CGM.getLangOpts().Optimize, Flags, ArgNo);
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call = DBuilder.insertDeclare(
- Storage, D, DBuilder.createExpression(Expr),
- Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
+ llvm::DebugLoc::get(Line, Column, Scope),
+ Builder.GetInsertBlock());
}
return;
}
}
// Create the descriptor for the variable.
- llvm::DIVariable D = DBuilder.createLocalVariable(
- Tag, llvm::DIDescriptor(Scope), Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags, ArgNo);
+ llvm::DIVariable D =
+ DBuilder.createLocalVariable(Tag, Scope, Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags, ArgNo);
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call = DBuilder.insertDeclare(
- Storage, D, DBuilder.createExpression(Expr), Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
+ llvm::DebugLoc::get(Line, Column, Scope),
+ Builder.GetInsertBlock());
}
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
@@ -2998,19 +2981,19 @@
}
// Create the descriptor for the variable.
- llvm::DIVariable D =
- DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_auto_variable,
- llvm::DIDescriptor(LexicalBlockStack.back()),
- VD->getName(), Unit, Line, Ty);
+ llvm::DIVariable D = DBuilder.createLocalVariable(
+ llvm::dwarf::DW_TAG_auto_variable,
+ cast<llvm::MDLocalScope>(LexicalBlockStack.back()), VD->getName(), Unit,
+ Line, Ty);
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call = InsertPoint ?
- DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr),
- InsertPoint)
- : DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr),
- Builder.GetInsertBlock());
- Call->setDebugLoc(
- llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back()));
+ auto DL = llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back());
+ if (InsertPoint)
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr), DL,
+ InsertPoint);
+ else
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr), DL,
+ Builder.GetInsertBlock());
}
/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
@@ -3158,27 +3141,25 @@
type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
// Get overall information about the block.
- unsigned flags = llvm::DIDescriptor::FlagArtificial;
- llvm::MDNode *scope = LexicalBlockStack.back();
+ unsigned flags = llvm::DebugNode::FlagArtificial;
+ auto *scope = cast<llvm::MDLocalScope>(LexicalBlockStack.back());
// Create the descriptor for the parameter.
llvm::DIVariable debugVar = DBuilder.createLocalVariable(
- llvm::dwarf::DW_TAG_arg_variable, llvm::DIDescriptor(scope),
- Arg->getName(), tunit, line, type, CGM.getLangOpts().Optimize, flags,
- ArgNo);
+ llvm::dwarf::DW_TAG_arg_variable, scope, Arg->getName(), tunit, line,
+ type, CGM.getLangOpts().Optimize, flags, ArgNo);
if (LocalAddr) {
// Insert an llvm.dbg.value into the current block.
- llvm::Instruction *DbgVal = DBuilder.insertDbgValueIntrinsic(
+ DBuilder.insertDbgValueIntrinsic(
LocalAddr, 0, debugVar, DBuilder.createExpression(),
- Builder.GetInsertBlock());
- DbgVal->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+ llvm::DebugLoc::get(line, column, scope), Builder.GetInsertBlock());
}
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *DbgDecl = DBuilder.insertDeclare(
- Arg, debugVar, DBuilder.createExpression(), Builder.GetInsertBlock());
- DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+ DBuilder.insertDeclare(Arg, debugVar, DBuilder.createExpression(),
+ llvm::DebugLoc::get(line, column, scope),
+ Builder.GetInsertBlock());
}
/// If D is an out-of-class definition of a static data member of a class, find
@@ -3191,24 +3172,23 @@
auto MI = StaticDataMemberCache.find(D->getCanonicalDecl());
if (MI != StaticDataMemberCache.end()) {
assert(MI->second && "Static data member declaration should still exist");
- return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));
+ return cast<llvm::MDDerivedTypeBase>(MI->second);
}
// If the member wasn't found in the cache, lazily construct and add it to the
// type (used when a limited form of the type is emitted).
auto DC = D->getDeclContext();
- llvm::DICompositeType Ctxt(getContextDescriptor(cast<Decl>(DC)));
+ llvm::DICompositeType Ctxt =
+ cast<llvm::MDCompositeType>(getContextDescriptor(cast<Decl>(DC)));
return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC));
}
/// Recursively collect all of the member fields of a global anonymous decl and
/// create static variables for them. The first time this is called it needs
/// to be on a union and then from there we can have additional unnamed fields.
-llvm::DIGlobalVariable
-CGDebugInfo::CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile Unit,
- unsigned LineNo, StringRef LinkageName,
- llvm::GlobalVariable *Var,
- llvm::DIDescriptor DContext) {
+llvm::DIGlobalVariable CGDebugInfo::CollectAnonRecordDecls(
+ const RecordDecl *RD, llvm::DIFile Unit, unsigned LineNo,
+ StringRef LinkageName, llvm::GlobalVariable *Var, llvm::MDScope *DContext) {
llvm::DIGlobalVariable GV;
for (const auto *Field : RD->fields()) {
@@ -3237,7 +3217,7 @@
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
// Create global variable debug descriptor.
llvm::DIFile Unit;
- llvm::DIDescriptor DContext;
+ llvm::MDScope *DContext = nullptr;
unsigned LineNo;
StringRef DeclName, LinkageName;
QualType T;
@@ -3278,7 +3258,7 @@
Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit);
}
// Do not use DIGlobalVariable for enums.
- if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
+ if (Ty->getTag() == llvm::dwarf::DW_TAG_enumeration_type)
return;
// Do not emit separate definitions for function local const/statics.
if (isa<FunctionDecl>(VD->getDeclContext()))
@@ -3294,7 +3274,7 @@
return;
}
- llvm::DIDescriptor DContext =
+ llvm::MDScope *DContext =
getContextDescriptor(dyn_cast<Decl>(VD->getDeclContext()));
auto &GV = DeclCache[VD];
@@ -3307,7 +3287,7 @@
llvm::DIScope CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
if (!LexicalBlockStack.empty())
- return llvm::DIScope(LexicalBlockStack.back());
+ return cast<llvm::MDScope>(LexicalBlockStack.back());
return getContextDescriptor(D);
}
@@ -3328,7 +3308,7 @@
// Emitting one decl is sufficient - debuggers can detect that this is an
// overloaded name & provide lookup for all the overloads.
const UsingShadowDecl &USD = **UD.shadow_begin();
- if (llvm::DIDescriptor Target =
+ if (llvm::DebugNode *Target =
getDeclarationOrDefinition(USD.getUnderlyingDecl()))
DBuilder.createImportedDeclaration(
getCurrentContextDescriptor(cast<Decl>(USD.getDeclContext())), Target,
@@ -3341,7 +3321,7 @@
return llvm::DIImportedEntity();
auto &VH = NamespaceAliasCache[&NA];
if (VH)
- return llvm::DIImportedEntity(cast<llvm::MDNode>(VH));
+ return cast<llvm::MDImportedEntity>(VH);
llvm::DIImportedEntity R;
if (const NamespaceAliasDecl *Underlying =
dyn_cast<NamespaceAliasDecl>(NA.getAliasedNamespace()))
@@ -3366,12 +3346,12 @@
NSDecl = NSDecl->getCanonicalDecl();
auto I = NameSpaceCache.find(NSDecl);
if (I != NameSpaceCache.end())
- return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
+ return cast<llvm::MDNamespace>(I->second);
unsigned LineNo = getLineNumber(NSDecl->getLocation());
llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());
- llvm::DIDescriptor Context =
- getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
+ llvm::MDScope *Context =
+ getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
llvm::DINameSpace NS =
DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
NameSpaceCache[NSDecl].reset(NS);
@@ -3383,23 +3363,23 @@
// element and the size(), so don't cache/reference them.
for (size_t i = 0; i != ObjCInterfaceCache.size(); ++i) {
ObjCInterfaceCacheEntry E = ObjCInterfaceCache[i];
- E.Decl.replaceAllUsesWith(CGM.getLLVMContext(),
- E.Type->getDecl()->getDefinition()
- ? CreateTypeDefinition(E.Type, E.Unit)
- : E.Decl);
+ llvm::MDType *Ty = E.Type->getDecl()->getDefinition()
+ ? CreateTypeDefinition(E.Type, E.Unit)
+ : E.Decl;
+ DBuilder.replaceTemporary(llvm::TempMDType(E.Decl), Ty);
}
for (auto p : ReplaceMap) {
assert(p.second);
- llvm::DIType Ty(cast<llvm::MDNode>(p.second));
- assert(Ty.isForwardDecl());
+ auto *Ty = cast<llvm::MDType>(p.second);
+ assert(Ty->isForwardDecl());
auto it = TypeCache.find(p.first);
assert(it != TypeCache.end());
assert(it->second);
- llvm::DIType RepTy(cast<llvm::MDNode>(it->second));
- Ty.replaceAllUsesWith(CGM.getLLVMContext(), RepTy);
+ DBuilder.replaceTemporary(llvm::TempMDType(Ty),
+ cast<llvm::MDType>(it->second));
}
for (const auto &p : FwdDeclReplaceMap) {
@@ -3416,15 +3396,15 @@
else
Repl = it->second;
- FwdDecl.replaceAllUsesWith(CGM.getLLVMContext(),
- llvm::DIDescriptor(cast<llvm::MDNode>(Repl)));
+ DBuilder.replaceTemporary(llvm::TempMDNode(FwdDecl),
+ cast<llvm::MDNode>(Repl));
}
// We keep our own list of retained types, because we need to look
// up the final type in the type cache.
for (std::vector<void *>::const_iterator RI = RetainedTypes.begin(),
RE = RetainedTypes.end(); RI != RE; ++RI)
- DBuilder.retainType(llvm::DIType(cast<llvm::MDNode>(TypeCache[*RI])));
+ DBuilder.retainType(cast<llvm::MDType>(TypeCache[*RI]));
DBuilder.finalize();
}
@@ -3432,7 +3412,8 @@
void CGDebugInfo::EmitExplicitCastType(QualType Ty) {
if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
return;
- llvm::DIType DieTy = getOrCreateType(Ty, getOrCreateMainFile());
- // Don't ignore in case of explicit cast where it is referenced indirectly.
- DBuilder.retainType(DieTy);
+
+ if (llvm::DIType DieTy = getOrCreateType(Ty, getOrCreateMainFile()))
+ // Don't ignore in case of explicit cast where it is referenced indirectly.
+ DBuilder.retainType(DieTy);
}
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 62ba801..6fcceed 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -56,7 +56,7 @@
SourceLocation CurLoc;
llvm::DIType VTablePtrType;
llvm::DIType ClassTy;
- llvm::DICompositeType ObjTy;
+ llvm::MDCompositeType *ObjTy = nullptr;
llvm::DIType SelTy;
llvm::DIType OCLImage1dDITy, OCLImage1dArrayDITy, OCLImage1dBufferDITy;
llvm::DIType OCLImage2dDITy, OCLImage2dArrayDITy;
@@ -129,8 +129,9 @@
llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const RecordType *Tyg);
llvm::DIType CreateTypeDefinition(const RecordType *Ty);
- llvm::DICompositeType CreateLimitedType(const RecordType *Ty);
- void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType CT);
+ llvm::MDCompositeType *CreateLimitedType(const RecordType *Ty);
+ void CollectContainingType(const CXXRecordDecl *RD,
+ llvm::MDCompositeType *CT);
llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
llvm::DIType CreateTypeDefinition(const ObjCInterfaceType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);
@@ -144,12 +145,13 @@
llvm::DIType CreateTypeDefinition(const EnumType *Ty);
llvm::DIType CreateSelfType(const QualType &QualTy, llvm::DIType Ty);
llvm::DIType getTypeOrNull(const QualType);
- llvm::DICompositeType getOrCreateMethodType(const CXXMethodDecl *Method,
- llvm::DIFile F);
- llvm::DICompositeType getOrCreateInstanceMethodType(
- QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit);
- llvm::DICompositeType getOrCreateFunctionType(const Decl *D, QualType FnType,
+ llvm::MDSubroutineType *getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile F);
+ llvm::MDSubroutineType *
+ getOrCreateInstanceMethodType(QualType ThisPtr, const FunctionProtoType *Func,
+ llvm::DIFile Unit);
+ llvm::MDSubroutineType *
+ getOrCreateFunctionType(const Decl *D, QualType FnType, llvm::DIFile F);
llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);
llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N);
llvm::DIType getOrCreateTypeDeclaration(QualType PointeeTy, llvm::DIFile F);
@@ -323,8 +325,8 @@
llvm::DIScope getCurrentContextDescriptor(const Decl *Decl);
/// \brief Create a forward decl for a RecordType in a given context.
- llvm::DICompositeType getOrCreateRecordFwdDecl(const RecordType *,
- llvm::DIDescriptor);
+ llvm::MDCompositeType *getOrCreateRecordFwdDecl(const RecordType *,
+ llvm::MDScope *);
/// \brief Create a set of decls for the context chain.
llvm::DIDescriptor createContextChain(const Decl *Decl);
@@ -363,7 +365,7 @@
/// \brief Retrieve the DIDescriptor, if any, for the canonical form of this
/// declaration.
- llvm::DIDescriptor getDeclarationOrDefinition(const Decl *D);
+ llvm::DebugNode *getDeclarationOrDefinition(const Decl *D);
/// \brief Return debug info descriptor to describe method
/// declaration for the given method definition.
@@ -385,9 +387,9 @@
/// Return a global variable that represents one of the collection of
/// global variables created for an anonmyous union.
llvm::DIGlobalVariable
- CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile Unit, unsigned LineNo,
- StringRef LinkageName, llvm::GlobalVariable *Var,
- llvm::DIDescriptor DContext);
+ CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile Unit,
+ unsigned LineNo, StringRef LinkageName,
+ llvm::GlobalVariable *Var, llvm::MDScope *DContext);
/// \brief Get function name for the given FunctionDecl. If the
/// name is constructed on demand (e.g. C++ destructor) then the name
@@ -419,18 +421,15 @@
/// \brief Collect various properties of a FunctionDecl.
/// \param GD A GlobalDecl whose getDecl() must return a FunctionDecl.
- void collectFunctionDeclProps(GlobalDecl GD,
- llvm::DIFile Unit,
+ void collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile Unit,
StringRef &Name, StringRef &LinkageName,
- llvm::DIDescriptor &FDContext,
- llvm::DIArray &TParamsArray,
- unsigned &Flags);
+ llvm::MDScope *&FDContext,
+ llvm::DIArray &TParamsArray, unsigned &Flags);
/// \brief Collect various properties of a VarDecl.
void collectVarDeclProps(const VarDecl *VD, llvm::DIFile &Unit,
- unsigned &LineNo, QualType &T,
- StringRef &Name, StringRef &LinkageName,
- llvm::DIDescriptor &VDContext);
+ unsigned &LineNo, QualType &T, StringRef &Name,
+ StringRef &LinkageName, llvm::MDScope *&VDContext);
/// \brief Allocate a copy of \p A using the DebugInfoNames allocator
/// and return a reference to it. If multiple arguments are given the strings
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index f79d137..f1ccb09 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -635,8 +635,9 @@
if (capturedByInit) {
// We can use a simple GEP for this because it can't have been
// moved yet.
- tempLV.setAddress(Builder.CreateStructGEP(tempLV.getAddress(),
- getByRefValueLLVMField(cast<VarDecl>(D))));
+ tempLV.setAddress(Builder.CreateStructGEP(
+ nullptr, tempLV.getAddress(),
+ getByRefValueLLVMField(cast<VarDecl>(D)).second));
}
llvm::PointerType *ty
@@ -797,8 +798,9 @@
// If necessary, get a pointer to the element and emit it.
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
- emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
- isVolatile, Builder);
+ emitStoresForInitAfterMemset(
+ Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i),
+ isVolatile, Builder);
}
return;
}
@@ -811,8 +813,9 @@
// If necessary, get a pointer to the element and emit it.
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
- emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
- isVolatile, Builder);
+ emitStoresForInitAfterMemset(
+ Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i),
+ isVolatile, Builder);
}
}
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 236337b..eb4ddc7 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -298,6 +298,11 @@
CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
llvm::GlobalVariable *Addr,
bool PerformInit) {
+ // Check if we've already initialized this decl.
+ auto I = DelayedCXXInitPosition.find(D);
+ if (I != DelayedCXXInitPosition.end() && I->second == ~0U)
+ return;
+
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
SmallString<256> FnName;
{
@@ -327,11 +332,9 @@
CXXThreadLocalInitVars.push_back(Addr);
} else if (PerformInit && ISA) {
EmitPointerToInitFunc(D, Addr, Fn, ISA);
- DelayedCXXInitPosition.erase(D);
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size());
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
- DelayedCXXInitPosition.erase(D);
} else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) {
// C++ [basic.start.init]p2:
// Definitions of explicitly specialized class template static data
@@ -346,24 +349,24 @@
// minor startup time optimization. In the MS C++ ABI, there are no guard
// variables, so this COMDAT key is required for correctness.
AddGlobalCtor(Fn, 65535, COMDATKey);
- DelayedCXXInitPosition.erase(D);
} else if (D->hasAttr<SelectAnyAttr>()) {
// SelectAny globals will be comdat-folded. Put the initializer into a
// COMDAT group associated with the global, so the initializers get folded
// too.
AddGlobalCtor(Fn, 65535, COMDATKey);
- DelayedCXXInitPosition.erase(D);
} else {
- llvm::DenseMap<const Decl *, unsigned>::iterator I =
- DelayedCXXInitPosition.find(D);
+ I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.
if (I == DelayedCXXInitPosition.end()) {
CXXGlobalInits.push_back(Fn);
- } else {
- assert(CXXGlobalInits[I->second] == nullptr);
+ } else if (I->second != ~0U) {
+ assert(I->second < CXXGlobalInits.size() &&
+ CXXGlobalInits[I->second] == nullptr);
CXXGlobalInits[I->second] = Fn;
- DelayedCXXInitPosition.erase(I);
}
}
+
+ // Remember that we already emitted the initializer for this global.
+ DelayedCXXInitPosition[D] = ~0U;
}
void CodeGenModule::EmitCXXThreadLocalInitFunc() {
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 223b8f7..ff12a9a 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -19,8 +19,11 @@
#include "clang/AST/Mangle.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtVisitor.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -406,13 +409,6 @@
return Builder.CreateLoad(getEHSelectorSlot(), "sel");
}
-llvm::Value *CodeGenFunction::getAbnormalTerminationSlot() {
- if (!AbnormalTerminationSlot)
- AbnormalTerminationSlot =
- CreateTempAlloca(Int8Ty, "abnormal.termination.slot");
- return AbnormalTerminationSlot;
-}
-
void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E,
bool KeepInsertionPoint) {
if (const Expr *SubExpr = E->getSubExpr()) {
@@ -458,6 +454,10 @@
EHStack.pushTerminate();
}
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
+ // TODO: Revisit exception specifications for the MS ABI. There is a way to
+ // encode these in an object file but MSVC doesn't do anything with it.
+ if (getTarget().getCXXABI().isMicrosoft())
+ return;
unsigned NumExceptions = Proto->getNumExceptions();
EHFilterScope *Filter = EHStack.pushFilter(NumExceptions);
@@ -532,6 +532,10 @@
EHStack.popTerminate();
}
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
+ // TODO: Revisit exception specifications for the MS ABI. There is a way to
+ // encode these in an object file but MSVC doesn't do anything with it.
+ if (getTarget().getCXXABI().isMicrosoft())
+ return;
EHFilterScope &filterScope = cast<EHFilterScope>(*EHStack.begin());
emitFilterDispatchBlock(*this, filterScope);
EHStack.popFilter();
@@ -568,7 +572,7 @@
TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
else
TypeInfo =
- CGM.getAddrOfCXXHandlerMapEntry(CaughtType, C->getCaughtType());
+ CGM.getAddrOfCXXCatchHandlerType(CaughtType, C->getCaughtType());
CatchScope->setHandler(I, TypeInfo, Handler);
} else {
// No exception decl indicates '...', a catch-all.
@@ -1277,8 +1281,7 @@
return;
}
- SEHFinallyInfo FI;
- EnterSEHTryStmt(S, FI);
+ EnterSEHTryStmt(S);
{
JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
@@ -1291,109 +1294,224 @@
else
delete TryExit.getBlock();
}
- ExitSEHTryStmt(S, FI);
+ ExitSEHTryStmt(S);
}
namespace {
-struct PerformSEHFinally : EHScopeStack::Cleanup {
- CodeGenFunction::SEHFinallyInfo *FI;
- PerformSEHFinally(CodeGenFunction::SEHFinallyInfo *FI) : FI(FI) {}
+struct PerformSEHFinally : EHScopeStack::Cleanup {
+ llvm::Function *OutlinedFinally;
+ PerformSEHFinally(llvm::Function *OutlinedFinally)
+ : OutlinedFinally(OutlinedFinally) {}
void Emit(CodeGenFunction &CGF, Flags F) override {
- // Cleanups are emitted at most twice: once for normal control flow and once
- // for exception control flow. Branch into the finally block, and remember
- // the continuation block so we can branch out later.
- if (!FI->FinallyBB) {
- FI->FinallyBB = CGF.createBasicBlock("__finally");
- FI->FinallyBB->insertInto(CGF.CurFn);
- FI->FinallyBB->moveAfter(CGF.Builder.GetInsertBlock());
- }
+ ASTContext &Context = CGF.getContext();
+ QualType ArgTys[2] = {Context.BoolTy, Context.VoidPtrTy};
+ FunctionProtoType::ExtProtoInfo EPI;
+ const auto *FTP = cast<FunctionType>(
+ Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
- // Set the termination status and branch in.
- CGF.Builder.CreateStore(
- llvm::ConstantInt::get(CGF.Int8Ty, F.isForEHCleanup()),
- CGF.getAbnormalTerminationSlot());
- CGF.Builder.CreateBr(FI->FinallyBB);
+ CallArgList Args;
+ llvm::Value *IsForEH =
+ llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
+ Args.add(RValue::get(IsForEH), ArgTys[0]);
- // Create a continuation block for normal or exceptional control.
- if (F.isForEHCleanup()) {
- assert(!FI->ResumeBB && "double emission for EH");
- FI->ResumeBB = CGF.createBasicBlock("__finally.resume");
- CGF.EmitBlock(FI->ResumeBB);
- } else {
- assert(F.isForNormalCleanup() && !FI->ContBB && "double normal emission");
- FI->ContBB = CGF.createBasicBlock("__finally.cont");
- CGF.EmitBlock(FI->ContBB);
- // Try to keep source order.
- FI->ContBB->moveAfter(FI->FinallyBB);
- }
+ CodeGenModule &CGM = CGF.CGM;
+ llvm::Value *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0);
+ llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress);
+ llvm::Value *FP = CGF.Builder.CreateCall(FrameAddr, Zero);
+ Args.add(RValue::get(FP), ArgTys[1]);
+
+ const CGFunctionInfo &FnInfo =
+ CGM.getTypes().arrangeFreeFunctionCall(Args, FTP, /*chainCall=*/false);
+ CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
}
};
}
+namespace {
+/// Find all local variable captures in the statement.
+struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
+ CodeGenFunction &ParentCGF;
+ const VarDecl *ParentThis;
+ SmallVector<const VarDecl *, 4> Captures;
+ CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis)
+ : ParentCGF(ParentCGF), ParentThis(ParentThis) {}
+
+ void Visit(const Stmt *S) {
+ // See if this is a capture, then recurse.
+ ConstStmtVisitor<CaptureFinder>::Visit(S);
+ for (const Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
+ }
+
+ void VisitDeclRefExpr(const DeclRefExpr *E) {
+ // If this is already a capture, just make sure we capture 'this'.
+ if (E->refersToEnclosingVariableOrCapture()) {
+ Captures.push_back(ParentThis);
+ return;
+ }
+
+ const auto *D = dyn_cast<VarDecl>(E->getDecl());
+ if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage())
+ Captures.push_back(D);
+ }
+
+ void VisitCXXThisExpr(const CXXThisExpr *E) {
+ Captures.push_back(ParentThis);
+ }
+};
+}
+
+void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
+ const Stmt *OutlinedStmt,
+ llvm::Value *ParentFP) {
+ // Find all captures in the Stmt.
+ CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl);
+ Finder.Visit(OutlinedStmt);
+
+ // Typically there are no captures and we can exit early.
+ if (Finder.Captures.empty())
+ return;
+
+ // Prepare the first two arguments to llvm.framerecover.
+ llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
+ &CGM.getModule(), llvm::Intrinsic::framerecover);
+ llvm::Constant *ParentI8Fn =
+ llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
+
+ // Create llvm.framerecover calls for all captures.
+ for (const VarDecl *VD : Finder.Captures) {
+ if (isa<ImplicitParamDecl>(VD)) {
+ CGM.ErrorUnsupported(VD, "'this' captured by SEH");
+ CXXThisValue = llvm::UndefValue::get(ConvertTypeForMem(VD->getType()));
+ continue;
+ }
+ if (VD->getType()->isVariablyModifiedType()) {
+ CGM.ErrorUnsupported(VD, "VLA captured by SEH");
+ continue;
+ }
+ assert((isa<ImplicitParamDecl>(VD) || VD->isLocalVarDeclOrParm()) &&
+ "captured non-local variable");
+
+ // If this decl hasn't been declared yet, it will be declared in the
+ // OutlinedStmt.
+ auto I = ParentCGF.LocalDeclMap.find(VD);
+ if (I == ParentCGF.LocalDeclMap.end())
+ continue;
+ llvm::Value *ParentVar = I->second;
+
+ llvm::CallInst *RecoverCall = nullptr;
+ CGBuilderTy Builder(AllocaInsertPt);
+ if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
+ // Mark the variable escaped if nobody else referenced it and compute the
+ // frameescape index.
+ auto InsertPair =
+ ParentCGF.EscapedLocals.insert(std::make_pair(ParentAlloca, -1));
+ if (InsertPair.second)
+ InsertPair.first->second = ParentCGF.EscapedLocals.size() - 1;
+ int FrameEscapeIdx = InsertPair.first->second;
+ // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
+ RecoverCall =
+ Builder.CreateCall3(FrameRecoverFn, ParentI8Fn, ParentFP,
+ llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx));
+
+ } else {
+ // If the parent didn't have an alloca, we're doing some nested outlining.
+ // Just clone the existing framerecover call, but tweak the FP argument to
+ // use our FP value. All other arguments are constants.
+ auto *ParentRecover =
+ cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
+ assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover &&
+ "expected alloca or framerecover in parent LocalDeclMap");
+ RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
+ RecoverCall->setArgOperand(1, ParentFP);
+ RecoverCall->insertBefore(AllocaInsertPt);
+ }
+
+ // Bitcast the variable, rename it, and insert it in the local decl map.
+ llvm::Value *ChildVar =
+ Builder.CreateBitCast(RecoverCall, ParentVar->getType());
+ ChildVar->setName(ParentVar->getName());
+ LocalDeclMap[VD] = ChildVar;
+ }
+}
+
+/// Arrange a function prototype that can be called by Windows exception
+/// handling personalities. On Win64, the prototype looks like:
+/// RetTy func(void *EHPtrs, void *ParentFP);
+void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
+ StringRef Name, QualType RetTy,
+ FunctionArgList &Args,
+ const Stmt *OutlinedStmt) {
+ llvm::Function *ParentFn = ParentCGF.CurFn;
+ const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false);
+
+ llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ llvm::Function *Fn = llvm::Function::Create(
+ FnTy, llvm::GlobalValue::InternalLinkage, Name.str(), &CGM.getModule());
+ // The filter is either in the same comdat as the function, or it's internal.
+ if (llvm::Comdat *C = ParentFn->getComdat()) {
+ Fn->setComdat(C);
+ } else if (ParentFn->hasWeakLinkage() || ParentFn->hasLinkOnceLinkage()) {
+ llvm::Comdat *C = CGM.getModule().getOrInsertComdat(ParentFn->getName());
+ ParentFn->setComdat(C);
+ Fn->setComdat(C);
+ } else {
+ Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
+ }
+
+ IsOutlinedSEHHelper = true;
+
+ StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
+ OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart());
+
+ CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn);
+
+ auto AI = Fn->arg_begin();
+ ++AI;
+ EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI);
+}
+
/// Create a stub filter function that will ultimately hold the code of the
/// filter expression. The EH preparation passes in LLVM will outline the code
/// from the main function body into this stub.
llvm::Function *
CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
const SEHExceptStmt &Except) {
- const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
- llvm::Function *ParentFn = ParentCGF.CurFn;
+ const Expr *FilterExpr = Except.getFilterExpr();
+ SourceLocation StartLoc = FilterExpr->getLocStart();
- Expr *FilterExpr = Except.getFilterExpr();
+ SEHPointersDecl = ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
+ FunctionArgList Args;
+ Args.push_back(SEHPointersDecl);
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
// Get the mangled function name.
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
+ const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
CGM.getCXXABI().getMangleContext().mangleSEHFilterExpression(Parent, OS);
}
- // Arrange a function with the declaration:
- // int filt(EXCEPTION_POINTERS *exception_pointers, void *frame_pointer)
- QualType RetTy = getContext().IntTy;
- FunctionArgList Args;
- SEHPointersDecl = ImplicitParamDecl::Create(
- getContext(), nullptr, FilterExpr->getLocStart(),
- &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
- Args.push_back(SEHPointersDecl);
- Args.push_back(ImplicitParamDecl::Create(
- getContext(), nullptr, FilterExpr->getLocStart(),
- &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
- const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
- RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false);
- llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
- llvm::Function *Fn = llvm::Function::Create(FnTy, ParentFn->getLinkage(),
- Name.str(), &CGM.getModule());
- // The filter is either in the same comdat as the function, or it's internal.
- if (llvm::Comdat *C = ParentFn->getComdat()) {
- Fn->setComdat(C);
- } else if (ParentFn->hasWeakLinkage() || ParentFn->hasLinkOnceLinkage()) {
- // FIXME: Unreachable with Rafael's changes?
- llvm::Comdat *C = CGM.getModule().getOrInsertComdat(ParentFn->getName());
- ParentFn->setComdat(C);
- Fn->setComdat(C);
- } else {
- Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
- }
+ startOutlinedSEHHelper(ParentCGF, Name, getContext().IntTy, Args, FilterExpr);
- StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
- FilterExpr->getLocStart(), FilterExpr->getLocStart());
+ // Mark finally block calls as nounwind and noinline to make LLVM's job a
+ // little easier.
+ // FIXME: Remove these restrictions in the future.
+ CurFn->addFnAttr(llvm::Attribute::NoUnwind);
+ CurFn->addFnAttr(llvm::Attribute::NoInline);
EmitSEHExceptionCodeSave();
- // Insert dummy allocas for every local variable in scope. We'll initialize
- // them and prune the unused ones after we find out which ones were
- // referenced.
- for (const auto &DeclPtrs : ParentCGF.LocalDeclMap) {
- const Decl *VD = DeclPtrs.first;
- llvm::Value *Ptr = DeclPtrs.second;
- auto *ValTy = cast<llvm::PointerType>(Ptr->getType())->getElementType();
- LocalDeclMap[VD] = CreateTempAlloca(ValTy, Ptr->getName() + ".filt");
- }
-
// Emit the original filter expression, convert to i32, and return.
llvm::Value *R = EmitScalarExpr(FilterExpr);
R = Builder.CreateIntCast(R, CGM.IntTy,
@@ -1402,18 +1520,42 @@
FinishFunction(FilterExpr->getLocEnd());
- for (const auto &DeclPtrs : ParentCGF.LocalDeclMap) {
- const Decl *VD = DeclPtrs.first;
- auto *Alloca = cast<llvm::AllocaInst>(LocalDeclMap[VD]);
- if (Alloca->hasNUses(0)) {
- Alloca->eraseFromParent();
- continue;
- }
- ErrorUnsupported(FilterExpr,
- "SEH filter expression local variable capture");
+ return CurFn;
+}
+
+llvm::Function *
+CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
+ const SEHFinallyStmt &Finally) {
+ const Stmt *FinallyBlock = Finally.getBlock();
+ SourceLocation StartLoc = FinallyBlock->getLocStart();
+
+ FunctionArgList Args;
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("abnormal_termination"), getContext().BoolTy));
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
+
+ // Get the mangled function name.
+ SmallString<128> Name;
+ {
+ llvm::raw_svector_ostream OS(Name);
+ const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
+ const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
+ assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
+ CGM.getCXXABI().getMangleContext().mangleSEHFinallyBlock(Parent, OS);
}
- return Fn;
+ startOutlinedSEHHelper(ParentCGF, Name, getContext().VoidTy, Args,
+ FinallyBlock);
+
+ // Emit the original filter expression, convert to i32, and return.
+ EmitStmt(FinallyBlock);
+
+ FinishFunction(FinallyBlock->getLocEnd());
+
+ return CurFn;
}
void CodeGenFunction::EmitSEHExceptionCodeSave() {
@@ -1429,7 +1571,7 @@
llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo();
llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr);
Ptrs = Builder.CreateBitCast(Ptrs, PtrsTy->getPointerTo());
- llvm::Value *Rec = Builder.CreateStructGEP(Ptrs, 0);
+ llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0);
Rec = Builder.CreateLoad(Rec);
llvm::Value *Code = Builder.CreateLoad(Rec);
Code = Builder.CreateZExt(Code, CGM.IntPtrTy);
@@ -1457,21 +1599,24 @@
}
llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
- // Load from the abnormal termination slot. It will be uninitialized outside
- // of __finally blocks, which we should warn or error on.
- llvm::Value *IsEH = Builder.CreateLoad(getAbnormalTerminationSlot());
- return Builder.CreateZExt(IsEH, Int32Ty);
+ // Abnormal termination is just the first parameter to the outlined finally
+ // helper.
+ auto AI = CurFn->arg_begin();
+ return Builder.CreateZExt(&*AI, Int32Ty);
}
-void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI) {
- if (S.getFinallyHandler()) {
+void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
+ CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
+ if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
// Push a cleanup for __finally blocks.
- EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, &FI);
+ llvm::Function *FinallyFunc =
+ HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
+ EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
return;
}
// Otherwise, we must have an __except block.
- SEHExceptStmt *Except = S.getExceptHandler();
+ const SEHExceptStmt *Except = S.getExceptHandler();
assert(Except);
EHCatchScope *CatchScope = EHStack.pushCatch(1);
@@ -1486,40 +1631,17 @@
// In general, we have to emit an outlined filter function. Use the function
// in place of the RTTI typeinfo global that C++ EH uses.
- CodeGenFunction FilterCGF(CGM, /*suppressNewContext=*/true);
llvm::Function *FilterFunc =
- FilterCGF.GenerateSEHFilterFunction(*this, *Except);
+ HelperCGF.GenerateSEHFilterFunction(*this, *Except);
llvm::Constant *OpaqueFunc =
llvm::ConstantExpr::getBitCast(FilterFunc, Int8PtrTy);
CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except"));
}
-void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI) {
+void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
// Just pop the cleanup if it's a __finally block.
- if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
+ if (S.getFinallyHandler()) {
PopCleanupBlock();
- assert(FI.ContBB && "did not emit normal cleanup");
-
- // Emit the code into FinallyBB.
- CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();
- Builder.SetInsertPoint(FI.FinallyBB);
- EmitStmt(Finally->getBlock());
-
- if (HaveInsertPoint()) {
- if (FI.ResumeBB) {
- llvm::Value *IsEH = Builder.CreateLoad(getAbnormalTerminationSlot(),
- "abnormal.termination");
- IsEH = Builder.CreateICmpEQ(IsEH, llvm::ConstantInt::get(Int8Ty, 0));
- Builder.CreateCondBr(IsEH, FI.ContBB, FI.ResumeBB);
- } else {
- // There was nothing exceptional in the try body, so we only have normal
- // control flow.
- Builder.CreateBr(FI.ContBB);
- }
- }
-
- Builder.restoreIP(SavedIP);
-
return;
}
@@ -1569,7 +1691,13 @@
if (HaveInsertPoint())
EmitStopPoint(&S);
- assert(!SEHTryEpilogueStack.empty() &&
- "sema should have rejected this __leave");
+ // This must be a __leave from a __finally block, which we warn on and is UB.
+ // Just emit unreachable.
+ if (!isSEHTryScope()) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+ return;
+ }
+
EmitBranchThroughCleanup(*SEHTryEpilogueStack.back());
}
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 5ba51cc..4147317 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -300,26 +300,26 @@
const MaterializeTemporaryExpr *M, const Expr *Inner) {
switch (M->getStorageDuration()) {
case SD_FullExpression:
- case SD_Automatic:
+ case SD_Automatic: {
// If we have a constant temporary array or record try to promote it into a
// constant global under the same rules a normal constant would've been
// promoted. This is easier on the optimizer and generally emits fewer
// instructions.
+ QualType Ty = Inner->getType();
if (CGF.CGM.getCodeGenOpts().MergeAllConstants &&
- (M->getType()->isArrayType() || M->getType()->isRecordType()) &&
- CGF.CGM.isTypeConstant(M->getType(), true))
- if (llvm::Constant *Init =
- CGF.CGM.EmitConstantExpr(Inner, M->getType(), &CGF)) {
+ (Ty->isArrayType() || Ty->isRecordType()) &&
+ CGF.CGM.isTypeConstant(Ty, true))
+ if (llvm::Constant *Init = CGF.CGM.EmitConstantExpr(Inner, Ty, &CGF)) {
auto *GV = new llvm::GlobalVariable(
CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp");
GV->setAlignment(
- CGF.getContext().getTypeAlignInChars(M->getType()).getQuantity());
+ CGF.getContext().getTypeAlignInChars(Ty).getQuantity());
// FIXME: Should we put the new global into a COMDAT?
return GV;
}
- return CGF.CreateMemTemp(Inner->getType(), "ref.tmp");
-
+ return CGF.CreateMemTemp(Ty, "ref.tmp");
+ }
case SD_Thread:
case SD_Static:
return CGF.CGM.GetAddrOfGlobalTemporary(M, Inner);
@@ -2077,9 +2077,8 @@
assert(E->getSubExpr()->getType()->isAnyComplexType());
unsigned Idx = E->getOpcode() == UO_Imag;
- return MakeAddrLValue(Builder.CreateStructGEP(LV.getAddress(),
- Idx, "idx"),
- ExprTy);
+ return MakeAddrLValue(
+ Builder.CreateStructGEP(nullptr, LV.getAddress(), Idx, "idx"), ExprTy);
}
case UO_PreInc:
case UO_PreDec: {
@@ -2675,7 +2674,7 @@
unsigned Idx = RL.getLLVMFieldNo(field);
if (Idx != 0)
// For structs, we GEP to the field that the record layout suggests.
- Addr = Builder.CreateStructGEP(Addr, Idx, field->getName());
+ Addr = Builder.CreateStructGEP(nullptr, Addr, Idx, field->getName());
// Get the access type.
llvm::Type *PtrTy = llvm::Type::getIntNPtrTy(
getLLVMContext(), Info.StorageSize,
@@ -2710,7 +2709,7 @@
} else {
// For structs, we GEP to the field that the record layout suggests.
unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
- addr = Builder.CreateStructGEP(addr, idx, field->getName());
+ addr = Builder.CreateStructGEP(nullptr, addr, idx, field->getName());
// If this is a reference field, load the reference right now.
if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
@@ -2789,7 +2788,7 @@
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(Field->getParent());
unsigned idx = RL.getLLVMFieldNo(Field);
- llvm::Value *V = Builder.CreateStructGEP(Base.getAddress(), idx);
+ llvm::Value *V = Builder.CreateStructGEP(nullptr, Base.getAddress(), idx);
assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
// Make sure that the address is pointing to the right type. This is critical
@@ -3369,7 +3368,7 @@
llvm::Value *CalleePrefixStruct = Builder.CreateBitCast(
Callee, llvm::PointerType::getUnqual(PrefixStructTy));
llvm::Value *CalleeSigPtr =
- Builder.CreateConstGEP2_32(CalleePrefixStruct, 0, 0);
+ Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0);
llvm::Value *CalleeSig = Builder.CreateLoad(CalleeSigPtr);
llvm::Value *CalleeSigMatch = Builder.CreateICmpEQ(CalleeSig, PrefixSig);
@@ -3379,7 +3378,7 @@
EmitBlock(TypeCheck);
llvm::Value *CalleeRTTIPtr =
- Builder.CreateConstGEP2_32(CalleePrefixStruct, 0, 1);
+ Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1);
llvm::Value *CalleeRTTI = Builder.CreateLoad(CalleeRTTIPtr);
llvm::Value *CalleeRTTIMatch =
Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 5b0d9f0..6b4cf68 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -645,7 +645,7 @@
// Build a GEP to refer to the subobject.
llvm::Value *valueAddr =
- CGF.Builder.CreateStructGEP(valueDest.getAddr(), 0);
+ CGF.Builder.CreateStructGEP(nullptr, valueDest.getAddr(), 0);
valueDest = AggValueSlot::forAddr(valueAddr,
valueDest.getAlignment(),
valueDest.getQualifiers(),
@@ -666,7 +666,7 @@
CGF.EmitAggExpr(E->getSubExpr(), atomicSlot);
llvm::Value *valueAddr =
- Builder.CreateStructGEP(atomicSlot.getAddr(), 0);
+ Builder.CreateStructGEP(nullptr, atomicSlot.getAddr(), 0);
RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile());
return EmitFinalDestCopy(valueType, rvalue);
}
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 6852d3a..4bffad3 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -256,6 +256,12 @@
} else if (UseVirtualCall) {
Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty);
} else {
+ if (SanOpts.has(SanitizerKind::CFINVCall) &&
+ MD->getParent()->isDynamicClass()) {
+ llvm::Value *VTable = GetVTablePtr(This, Int8PtrTy);
+ EmitVTablePtrCheckForCall(MD, VTable);
+ }
+
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
else if (!DevirtualizedMethod)
@@ -778,12 +784,10 @@
llvm_unreachable("bad evaluation kind");
}
-void
-CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
- QualType ElementType,
- llvm::Value *BeginPtr,
- llvm::Value *NumElements,
- llvm::Value *AllocSizeWithoutCookie) {
+void CodeGenFunction::EmitNewArrayInitializer(
+ const CXXNewExpr *E, QualType ElementType, llvm::Type *ElementTy,
+ llvm::Value *BeginPtr, llvm::Value *NumElements,
+ llvm::Value *AllocSizeWithoutCookie) {
// If we have a type with trivial initialization and no initializer,
// there's nothing to do.
if (!E->hasInitializer())
@@ -809,7 +813,8 @@
if (const ConstantArrayType *CAT = dyn_cast_or_null<ConstantArrayType>(
AllocType->getAsArrayTypeUnsafe())) {
unsigned AS = CurPtr->getType()->getPointerAddressSpace();
- llvm::Type *AllocPtrTy = ConvertTypeForMem(AllocType)->getPointerTo(AS);
+ ElementTy = ConvertTypeForMem(AllocType);
+ llvm::Type *AllocPtrTy = ElementTy->getPointerTo(AS);
CurPtr = Builder.CreateBitCast(CurPtr, AllocPtrTy);
InitListElements *= getContext().getConstantArrayElementCount(CAT);
}
@@ -839,7 +844,8 @@
// initialization loops.
StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
ILE->getInit(i)->getType(), CurPtr);
- CurPtr = Builder.CreateConstInBoundsGEP1_32(CurPtr, 1, "array.exp.next");
+ CurPtr = Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr, 1,
+ "array.exp.next");
}
// The remaining elements are filled with the array filler expression.
@@ -1000,7 +1006,7 @@
// Advance to the next element by adjusting the pointer type as necessary.
llvm::Value *NextPtr =
- Builder.CreateConstInBoundsGEP1_32(CurPtr, 1, "array.next");
+ Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr, 1, "array.next");
// Check whether we've gotten to the end of the array and, if so,
// exit the loop.
@@ -1012,13 +1018,12 @@
}
static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
- QualType ElementType,
- llvm::Value *NewPtr,
- llvm::Value *NumElements,
+ QualType ElementType, llvm::Type *ElementTy,
+ llvm::Value *NewPtr, llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie) {
ApplyDebugLocation DL(CGF, E);
if (E->isArray())
- CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements,
+ CGF.EmitNewArrayInitializer(E, ElementType, ElementTy, NewPtr, NumElements,
AllocSizeWithoutCookie);
else if (const Expr *Init = E->getInitializer())
StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
@@ -1326,11 +1331,11 @@
E, allocType);
}
- llvm::Type *elementPtrTy
- = ConvertTypeForMem(allocType)->getPointerTo(AS);
+ llvm::Type *elementTy = ConvertTypeForMem(allocType);
+ llvm::Type *elementPtrTy = elementTy->getPointerTo(AS);
llvm::Value *result = Builder.CreateBitCast(allocation, elementPtrTy);
- EmitNewInitializer(*this, E, allocType, result, numElements,
+ EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,
allocSizeWithoutCookie);
if (E->isArray()) {
// NewPtr is a pointer to the base element type. If we're
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index b2228f0..dead1b5 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -317,14 +317,14 @@
llvm::Value *Real=nullptr, *Imag=nullptr;
if (!IgnoreReal || isVolatile) {
- llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0,
+ llvm::Value *RealP = Builder.CreateStructGEP(nullptr, SrcPtr, 0,
SrcPtr->getName() + ".realp");
Real = Builder.CreateAlignedLoad(RealP, AlignR, isVolatile,
SrcPtr->getName() + ".real");
}
if (!IgnoreImag || isVolatile) {
- llvm::Value *ImagP = Builder.CreateStructGEP(SrcPtr, 1,
+ llvm::Value *ImagP = Builder.CreateStructGEP(nullptr, SrcPtr, 1,
SrcPtr->getName() + ".imagp");
Imag = Builder.CreateAlignedLoad(ImagP, AlignI, isVolatile,
SrcPtr->getName() + ".imag");
@@ -341,8 +341,8 @@
return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit);
llvm::Value *Ptr = lvalue.getAddress();
- llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real");
- llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag");
+ llvm::Value *RealPtr = Builder.CreateStructGEP(nullptr, Ptr, 0, "real");
+ llvm::Value *ImagPtr = Builder.CreateStructGEP(nullptr, Ptr, 1, "imag");
unsigned AlignR = lvalue.getAlignment().getQuantity();
ASTContext &C = CGF.getContext();
QualType ComplexTy = lvalue.getType();
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 7406354..b1cf99c 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -1115,7 +1115,7 @@
unsigned AS = C->getType()->getPointerAddressSpace();
llvm::Type *CharPtrTy = Int8Ty->getPointerTo(AS);
llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, CharPtrTy);
- Casted = llvm::ConstantExpr::getGetElementPtr(Casted, Offset);
+ Casted = llvm::ConstantExpr::getGetElementPtr(Int8Ty, Casted, Offset);
C = llvm::ConstantExpr::getPointerCast(Casted, C->getType());
}
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 16ce69d..658bd3e 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1451,13 +1451,13 @@
// anything here.
if (!E->getType()->isVariableArrayType()) {
assert(isa<llvm::PointerType>(V->getType()) && "Expected pointer");
+ llvm::Type *NewTy = ConvertType(E->getType());
V = CGF.Builder.CreatePointerCast(
- V, ConvertType(E->getType())->getPointerTo(
- V->getType()->getPointerAddressSpace()));
+ V, NewTy->getPointerTo(V->getType()->getPointerAddressSpace()));
assert(isa<llvm::ArrayType>(V->getType()->getPointerElementType()) &&
"Expected pointer to array");
- V = Builder.CreateStructGEP(V, 0, "arraydecay");
+ V = Builder.CreateStructGEP(NewTy, V, 0, "arraydecay");
}
// Make sure the array decay ends up being the right type. This matters if
@@ -1845,10 +1845,9 @@
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
auto Pair = CGF.EmitAtomicCompareExchange(
- LV, RValue::get(atomicPHI), RValue::get(CGF.EmitToMemory(value, type)),
- E->getExprLoc());
- llvm::Value *old = Pair.first.getScalarVal();
- llvm::Value *success = Pair.second.getScalarVal();
+ LV, RValue::get(atomicPHI), RValue::get(value), E->getExprLoc());
+ llvm::Value *old = CGF.EmitToMemory(Pair.first.getScalarVal(), type);
+ llvm::Value *success = Pair.second;
atomicPHI->addIncoming(old, opBB);
Builder.CreateCondBr(success, contBB, opBB);
Builder.SetInsertPoint(contBB);
@@ -2189,10 +2188,9 @@
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
auto Pair = CGF.EmitAtomicCompareExchange(
- LHSLV, RValue::get(atomicPHI),
- RValue::get(CGF.EmitToMemory(Result, LHSTy)), E->getExprLoc());
- llvm::Value *old = Pair.first.getScalarVal();
- llvm::Value *success = Pair.second.getScalarVal();
+ LHSLV, RValue::get(atomicPHI), RValue::get(Result), E->getExprLoc());
+ llvm::Value *old = CGF.EmitToMemory(Pair.first.getScalarVal(), LHSTy);
+ llvm::Value *success = Pair.second;
atomicPHI->addIncoming(old, opBB);
Builder.CreateCondBr(success, contBB, opBB);
Builder.SetInsertPoint(contBB);
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 19f5ca2..dfad13a 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -102,8 +102,8 @@
ArrayType::Normal, /*IndexTypeQuals=*/0);
// Allocate the temporary array(s).
- llvm::Value *Objects = CreateMemTemp(ElementArrayType, "objects");
- llvm::Value *Keys = nullptr;
+ llvm::AllocaInst *Objects = CreateMemTemp(ElementArrayType, "objects");
+ llvm::AllocaInst *Keys = nullptr;
if (DLE)
Keys = CreateMemTemp(ElementArrayType, "keys");
@@ -119,10 +119,9 @@
if (ALE) {
// Emit the element and store it to the appropriate array slot.
const Expr *Rhs = ALE->getElement(i);
- LValue LV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i),
- ElementType,
- Context.getTypeAlignInChars(Rhs->getType()),
- Context);
+ LValue LV = LValue::MakeAddr(
+ Builder.CreateStructGEP(Objects->getAllocatedType(), Objects, i),
+ ElementType, Context.getTypeAlignInChars(Rhs->getType()), Context);
llvm::Value *value = EmitScalarExpr(Rhs);
EmitStoreThroughLValue(RValue::get(value), LV, true);
@@ -132,19 +131,17 @@
} else {
// Emit the key and store it to the appropriate array slot.
const Expr *Key = DLE->getKeyValueElement(i).Key;
- LValue KeyLV = LValue::MakeAddr(Builder.CreateStructGEP(Keys, i),
- ElementType,
- Context.getTypeAlignInChars(Key->getType()),
- Context);
+ LValue KeyLV = LValue::MakeAddr(
+ Builder.CreateStructGEP(Keys->getAllocatedType(), Keys, i),
+ ElementType, Context.getTypeAlignInChars(Key->getType()), Context);
llvm::Value *keyValue = EmitScalarExpr(Key);
EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true);
// Emit the value and store it to the appropriate array slot.
- const Expr *Value = DLE->getKeyValueElement(i).Value;
- LValue ValueLV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i),
- ElementType,
- Context.getTypeAlignInChars(Value->getType()),
- Context);
+ const Expr *Value = DLE->getKeyValueElement(i).Value;
+ LValue ValueLV = LValue::MakeAddr(
+ Builder.CreateStructGEP(Objects->getAllocatedType(), Objects, i),
+ ElementType, Context.getTypeAlignInChars(Value->getType()), Context);
llvm::Value *valueValue = EmitScalarExpr(Value);
EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true);
if (TrackNeededObjects) {
@@ -1434,7 +1431,7 @@
// Fast enumeration state.
QualType StateTy = CGM.getObjCFastEnumerationStateType();
- llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
+ llvm::AllocaInst *StatePtr = CreateMemTemp(StateTy, "state.ptr");
EmitNullInitialization(StatePtr, StateTy);
// Number of elements in the items array.
@@ -1518,8 +1515,8 @@
// Save the initial mutations value. This is the value at an
// address that was written into the state object by
// countByEnumeratingWithState:objects:count:.
- llvm::Value *StateMutationsPtrPtr =
- Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr");
+ llvm::Value *StateMutationsPtrPtr = Builder.CreateStructGEP(
+ StatePtr->getAllocatedType(), StatePtr, 2, "mutationsptr.ptr");
llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr,
"mutationsptr");
@@ -1599,8 +1596,8 @@
// Fetch the buffer out of the enumeration state.
// TODO: this pointer should actually be invariant between
// refreshes, which would help us do certain loop optimizations.
- llvm::Value *StateItemsPtr =
- Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr");
+ llvm::Value *StateItemsPtr = Builder.CreateStructGEP(
+ StatePtr->getAllocatedType(), StatePtr, 1, "stateitems.ptr");
llvm::Value *EnumStateItems =
Builder.CreateLoad(StateItemsPtr, "stateitems");
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index da95260..981fe90 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -171,8 +171,9 @@
/// where the C code specifies const char*.
llvm::Constant *MakeConstantString(const std::string &Str,
const std::string &Name="") {
- llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
- return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros);
+ auto *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
+ ConstStr, Zeros);
}
/// Emits a linkonce_odr string, whose name is the prefix followed by the
/// string value. This allows the linker to combine the strings between
@@ -181,13 +182,14 @@
llvm::Constant *ExportUniqueString(const std::string &Str,
const std::string prefix) {
std::string name = prefix + Str;
- llvm::Constant *ConstStr = TheModule.getGlobalVariable(name);
+ auto *ConstStr = TheModule.getGlobalVariable(name);
if (!ConstStr) {
llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true,
llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str);
}
- return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros);
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
+ ConstStr, Zeros);
}
/// Generates a global structure, initialized by the elements in the vector.
/// The element types must match the types of the structure elements in the
@@ -237,8 +239,9 @@
NameAndAttributes += TypeStr;
NameAndAttributes += '\0';
NameAndAttributes += PD->getNameAsString();
- return llvm::ConstantExpr::getGetElementPtr(
- CGM.GetAddrOfConstantCString(NameAndAttributes), Zeros);
+ auto *ConstStr = CGM.GetAddrOfConstantCString(NameAndAttributes);
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
+ ConstStr, Zeros);
}
return MakeConstantString(PD->getNameAsString());
}
@@ -672,8 +675,8 @@
slot->setMetadata(msgSendMDKind, node);
// Load the imp from the slot
- llvm::Value *imp =
- Builder.CreateLoad(Builder.CreateStructGEP(slot.getInstruction(), 4));
+ llvm::Value *imp = Builder.CreateLoad(
+ Builder.CreateStructGEP(nullptr, slot.getInstruction(), 4));
// The lookup function may have changed the receiver, so make sure we use
// the new one.
@@ -690,7 +693,7 @@
CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs);
slot->setOnlyReadsMemory();
- return Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
+ return Builder.CreateLoad(Builder.CreateStructGEP(nullptr, slot, 4));
}
public:
CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNU(Mod, 9, 3) {
@@ -1013,7 +1016,7 @@
llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF,
const std::string &Name,
bool isWeak) {
- llvm::Value *ClassName = CGM.GetAddrOfConstantCString(Name);
+ llvm::GlobalVariable *ClassNameGV = CGM.GetAddrOfConstantCString(Name);
// With the incompatible ABI, this will need to be replaced with a direct
// reference to the class symbol. For the compatible nonfragile ABI we are
// still performing this lookup at run time but emitting the symbol for the
@@ -1023,7 +1026,8 @@
// with memoized versions or with static references if it's safe to do so.
if (!isWeak)
EmitClassRef(Name);
- ClassName = CGF.Builder.CreateStructGEP(ClassName, 0);
+ llvm::Value *ClassName =
+ CGF.Builder.CreateStructGEP(ClassNameGV->getValueType(), ClassNameGV, 0);
llvm::Constant *ClassLookupFn =
CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, PtrToInt8Ty, true),
@@ -1143,21 +1147,22 @@
// It's quite ugly hard-coding this. Ideally we'd generate it using the host
// platform's name mangling.
const char *vtableName = "_ZTVN7gnustep7libobjc22__objc_class_type_infoE";
- llvm::Constant *Vtable = TheModule.getGlobalVariable(vtableName);
+ auto *Vtable = TheModule.getGlobalVariable(vtableName);
if (!Vtable) {
Vtable = new llvm::GlobalVariable(TheModule, PtrToInt8Ty, true,
llvm::GlobalValue::ExternalLinkage,
nullptr, vtableName);
}
llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
- Vtable = llvm::ConstantExpr::getGetElementPtr(Vtable, Two);
- Vtable = llvm::ConstantExpr::getBitCast(Vtable, PtrToInt8Ty);
+ auto *BVtable = llvm::ConstantExpr::getBitCast(
+ llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two),
+ PtrToInt8Ty);
llvm::Constant *typeName =
ExportUniqueString(className, "__objc_eh_typename_");
std::vector<llvm::Constant*> fields;
- fields.push_back(Vtable);
+ fields.push_back(BVtable);
fields.push_back(typeName);
llvm::Constant *TI =
MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
@@ -1275,11 +1280,11 @@
}
}
// Cast the pointer to a simplified version of the class structure
+ llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy, nullptr);
ReceiverClass = Builder.CreateBitCast(ReceiverClass,
- llvm::PointerType::getUnqual(
- llvm::StructType::get(IdTy, IdTy, nullptr)));
+ llvm::PointerType::getUnqual(CastTy));
// Get the superclass pointer
- ReceiverClass = Builder.CreateStructGEP(ReceiverClass, 1);
+ ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
// Load the superclass pointer
ReceiverClass = Builder.CreateLoad(ReceiverClass);
// Construct the structure used to look up the IMP
@@ -1287,8 +1292,10 @@
Receiver->getType(), IdTy, nullptr);
llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
- Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
- Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
+ Builder.CreateStore(Receiver,
+ Builder.CreateStructGEP(ObjCSuperTy, ObjCSuper, 0));
+ Builder.CreateStore(ReceiverClass,
+ Builder.CreateStructGEP(ObjCSuperTy, ObjCSuper, 1));
ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy);
@@ -2294,7 +2301,8 @@
offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
// Get the correct ivar field
llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
- IvarList, offsetPointerIndexes);
+ cast<llvm::GlobalVariable>(IvarList)->getValueType(), IvarList,
+ offsetPointerIndexes);
// Get the existing variable, if one exists.
llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
if (offset) {
@@ -2439,8 +2447,8 @@
// Number of static selectors
Elements.push_back(llvm::ConstantInt::get(LongTy, SelectorCount));
- llvm::Constant *SelectorList = MakeGlobalArray(SelStructTy, Selectors,
- ".objc_selector_list");
+ llvm::GlobalVariable *SelectorList =
+ MakeGlobalArray(SelStructTy, Selectors, ".objc_selector_list");
Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
SelStructPtrTy));
@@ -2450,8 +2458,8 @@
llvm::Constant *Idxs[] = {Zeros[0],
llvm::ConstantInt::get(Int32Ty, i), Zeros[0]};
// FIXME: We're generating redundant loads and stores here!
- llvm::Constant *SelPtr = llvm::ConstantExpr::getGetElementPtr(SelectorList,
- makeArrayRef(Idxs, 2));
+ llvm::Constant *SelPtr = llvm::ConstantExpr::getGetElementPtr(
+ SelectorList->getValueType(), SelectorList, makeArrayRef(Idxs, 2));
// If selectors are defined as an opaque type, cast the pointer to this
// type.
SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, SelectorTy);
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index b9fdf73..a45446a 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -486,7 +486,6 @@
}
ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCCommonTypesHelper(){}
};
/// ObjCTypesHelper - Helper class that encapsulates lazy
@@ -595,7 +594,6 @@
public:
ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCTypesHelper() {}
};
/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
@@ -733,7 +731,6 @@
llvm::Type *EHTypePtrTy;
ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCNonFragileABITypesHelper(){}
};
class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
@@ -1678,14 +1675,13 @@
/// getConstantGEP() - Help routine to construct simple GEPs.
static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
- llvm::Constant *C,
- unsigned idx0,
+ llvm::GlobalVariable *C, unsigned idx0,
unsigned idx1) {
llvm::Value *Idxs[] = {
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
};
- return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
+ return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
}
/// hasObjCExceptionAttribute - Return true if this class or any super
@@ -1791,8 +1787,9 @@
CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
llvm::Value *ReceiverAsObject =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateStore(ReceiverAsObject,
- CGF.Builder.CreateStructGEP(ObjCSuper, 0));
+ CGF.Builder.CreateStore(
+ ReceiverAsObject,
+ CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 0));
// If this is a class message the metaclass is passed as the target.
llvm::Value *Target;
@@ -1805,20 +1802,20 @@
// the class's "isa" pointer. The following assumes that
// isa" is the first ivar in a class (which it must be).
Target = EmitClassRef(CGF, Class->getSuperClass());
- Target = CGF.Builder.CreateStructGEP(Target, 0);
+ Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
Target = CGF.Builder.CreateLoad(Target);
} else {
- llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
- llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
+ llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
+ llvm::Value *SuperPtr =
+ CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
Target = Super;
}
- }
- else if (isCategoryImpl)
+ } else if (isCategoryImpl)
Target = EmitClassRef(CGF, Class->getSuperClass());
else {
llvm::Value *ClassPtr = EmitSuperClassRef(Class);
- ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
+ ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
Target = CGF.Builder.CreateLoad(ClassPtr);
}
// FIXME: We shouldn't need to do this cast, rectify the ASTContext and
@@ -1826,8 +1823,8 @@
llvm::Type *ClassTy =
CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Target = CGF.Builder.CreateBitCast(Target, ClassTy);
- CGF.Builder.CreateStore(Target,
- CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+ CGF.Builder.CreateStore(
+ Target, CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 1));
return EmitMessageSend(CGF, Return, ResultType,
EmitSelector(CGF, Sel),
ObjCSuper, ObjCTypes.SuperPtrCTy,
@@ -3816,8 +3813,8 @@
// - Call setjmp on the exception data buffer.
llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
- llvm::Value *SetJmpBuffer =
- CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
+ llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
+ ObjCTypes.ExceptionDataTy, ExceptionData, GEPIndexes, "setjmp_buffer");
llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
SetJmpResult->setCanReturnTwice();
@@ -5264,6 +5261,7 @@
// const uint32_t size; // sizeof(struct _protocol_t)
// const uint32_t flags; // = 0
// const char ** extendedMethodTypes;
+ // const char *demangledName;
// }
// Holder for struct _protocol_list_t *
@@ -5276,6 +5274,7 @@
MethodListnfABIPtrTy, MethodListnfABIPtrTy,
MethodListnfABIPtrTy, MethodListnfABIPtrTy,
PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
+ Int8PtrTy,
nullptr);
// struct _protocol_t*
@@ -6208,6 +6207,7 @@
/// const uint32_t size; // sizeof(struct _protocol_t)
/// const uint32_t flags; // = 0
/// const char ** extendedMethodTypes;
+/// const char *demangledName;
/// }
/// @endcode
///
@@ -6259,7 +6259,7 @@
MethodTypesExt.insert(MethodTypesExt.end(),
OptMethodTypesExt.begin(), OptMethodTypesExt.end());
- llvm::Constant *Values[11];
+ llvm::Constant *Values[12];
// isa is NULL
Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Values[1] = GetClassName(PD->getObjCRuntimeNameAsString());
@@ -6292,6 +6292,9 @@
Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
+ PD->getObjCRuntimeNameAsString(),
MethodTypesExt, ObjCTypes);
+ // const char *demangledName;
+ Values[11] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Values);
@@ -6563,7 +6566,8 @@
args[1].RV = RValue::get(mref);
// Load the function to call from the message ref table.
- llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
+ llvm::Value *callee =
+ CGF.Builder.CreateStructGEP(ObjCTypes.MessageRefTy, mref, 0);
callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
@@ -6728,8 +6732,9 @@
llvm::Value *ReceiverAsObject =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateStore(ReceiverAsObject,
- CGF.Builder.CreateStructGEP(ObjCSuper, 0));
+ CGF.Builder.CreateStore(
+ ReceiverAsObject,
+ CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 0));
// If this is a class message the metaclass is passed as the target.
llvm::Value *Target;
@@ -6743,8 +6748,8 @@
llvm::Type *ClassTy =
CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Target = CGF.Builder.CreateBitCast(Target, ClassTy);
- CGF.Builder.CreateStore(Target,
- CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+ CGF.Builder.CreateStore(
+ Target, CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 1));
return (isVTableDispatchedSelector(Sel))
? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
@@ -6993,10 +6998,10 @@
llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
llvm::Constant *Values[] = {
- llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
- GetClassName(ID->getObjCRuntimeNameAsString()),
- GetClassGlobal(ClassName.str())
- };
+ llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(), VTableGV,
+ VTableIdx),
+ GetClassName(ID->getObjCRuntimeNameAsString()),
+ GetClassGlobal(ClassName.str())};
llvm::Constant *Init =
llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index ef2d214..5988c78 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -31,47 +31,73 @@
/// \brief Base class for handling code generation inside OpenMP regions.
class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
public:
- CGOpenMPRegionInfo(const OMPExecutableDirective &D, const CapturedStmt &CS)
- : CGCapturedStmtInfo(CS, CR_OpenMP), Directive(D) {}
+ /// \brief Kinds of OpenMP regions used in codegen.
+ enum CGOpenMPRegionKind {
+ /// \brief Region with outlined function for standalone 'parallel'
+ /// directive.
+ ParallelOutlinedRegion,
+ /// \brief Region with outlined function for standalone 'task' directive.
+ TaskOutlinedRegion,
+ /// \brief Region for constructs that do not require function outlining,
+ /// like 'for', 'sections', 'atomic' etc. directives.
+ InlinedRegion,
+ };
- CGOpenMPRegionInfo(const OMPExecutableDirective &D)
- : CGCapturedStmtInfo(CR_OpenMP), Directive(D) {}
+ CGOpenMPRegionInfo(const CapturedStmt &CS,
+ const CGOpenMPRegionKind RegionKind,
+ const RegionCodeGenTy &CodeGen)
+ : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
+ CodeGen(CodeGen) {}
+
+ CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
+ const RegionCodeGenTy &CodeGen)
+ : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind),
+ CodeGen(CodeGen) {}
/// \brief Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
virtual const VarDecl *getThreadIDVariable() const = 0;
+ /// \brief Emit the captured statement body.
+ virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
+
/// \brief Get an LValue for the current ThreadID variable.
/// \return LValue for thread id variable. This LValue always has type int32*.
virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
- /// \brief Emit the captured statement body.
- virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
+ CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
static bool classof(const CGCapturedStmtInfo *Info) {
return Info->getKind() == CR_OpenMP;
}
+
protected:
- /// \brief OpenMP executable directive associated with the region.
- const OMPExecutableDirective &Directive;
+ CGOpenMPRegionKind RegionKind;
+ const RegionCodeGenTy &CodeGen;
};
/// \brief API for captured statement code generation in OpenMP constructs.
class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
public:
- CGOpenMPOutlinedRegionInfo(const OMPExecutableDirective &D,
- const CapturedStmt &CS, const VarDecl *ThreadIDVar)
- : CGOpenMPRegionInfo(D, CS), ThreadIDVar(ThreadIDVar) {
+ CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
+ const RegionCodeGenTy &CodeGen)
+ : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen),
+ ThreadIDVar(ThreadIDVar) {
assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
}
/// \brief Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
- virtual const VarDecl *getThreadIDVariable() const override {
- return ThreadIDVar;
- }
+ const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
+
/// \brief Get the name of the capture helper.
StringRef getHelperName() const override { return ".omp_outlined."; }
+ static bool classof(const CGCapturedStmtInfo *Info) {
+ return CGOpenMPRegionInfo::classof(Info) &&
+ cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
+ ParallelOutlinedRegion;
+ }
+
private:
/// \brief A variable or parameter storing global thread id for OpenMP
/// constructs.
@@ -81,84 +107,121 @@
/// \brief API for captured statement code generation in OpenMP constructs.
class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
public:
- CGOpenMPTaskOutlinedRegionInfo(const OMPExecutableDirective &D,
- const CapturedStmt &CS,
+ CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
- const VarDecl *PartIDVar)
- : CGOpenMPRegionInfo(D, CS), ThreadIDVar(ThreadIDVar),
- PartIDVar(PartIDVar) {
+ const RegionCodeGenTy &CodeGen)
+ : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen),
+ ThreadIDVar(ThreadIDVar) {
assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
}
/// \brief Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
- virtual const VarDecl *getThreadIDVariable() const override {
- return ThreadIDVar;
- }
+ const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
/// \brief Get an LValue for the current ThreadID variable.
- virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
-
- /// \brief Emit the captured statement body.
- virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
+ LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
/// \brief Get the name of the capture helper.
StringRef getHelperName() const override { return ".omp_outlined."; }
+ static bool classof(const CGCapturedStmtInfo *Info) {
+ return CGOpenMPRegionInfo::classof(Info) &&
+ cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
+ TaskOutlinedRegion;
+ }
+
private:
/// \brief A variable or parameter storing global thread id for OpenMP
/// constructs.
const VarDecl *ThreadIDVar;
- /// \brief A variable or parameter storing part id for OpenMP tasking
- /// constructs.
- const VarDecl *PartIDVar;
};
/// \brief API for inlined captured statement code generation in OpenMP
/// constructs.
class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
public:
- CGOpenMPInlinedRegionInfo(const OMPExecutableDirective &D,
- CodeGenFunction::CGCapturedStmtInfo *OldCSI)
- : CGOpenMPRegionInfo(D), OldCSI(OldCSI),
+ CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
+ const RegionCodeGenTy &CodeGen)
+ : CGOpenMPRegionInfo(InlinedRegion, CodeGen), OldCSI(OldCSI),
OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
// \brief Retrieve the value of the context parameter.
- virtual llvm::Value *getContextValue() const override {
+ llvm::Value *getContextValue() const override {
if (OuterRegionInfo)
return OuterRegionInfo->getContextValue();
llvm_unreachable("No context value for inlined OpenMP region");
}
+ virtual void setContextValue(llvm::Value *V) override {
+ if (OuterRegionInfo) {
+ OuterRegionInfo->setContextValue(V);
+ return;
+ }
+ llvm_unreachable("No context value for inlined OpenMP region");
+ }
/// \brief Lookup the captured field decl for a variable.
- virtual const FieldDecl *lookup(const VarDecl *VD) const override {
+ const FieldDecl *lookup(const VarDecl *VD) const override {
if (OuterRegionInfo)
return OuterRegionInfo->lookup(VD);
- llvm_unreachable("Trying to reference VarDecl that is neither local nor "
- "captured in outer OpenMP region");
+ // If there is no outer outlined region,no need to lookup in a list of
+ // captured variables, we can use the original one.
+ return nullptr;
}
- virtual FieldDecl *getThisFieldDecl() const override {
+ FieldDecl *getThisFieldDecl() const override {
if (OuterRegionInfo)
return OuterRegionInfo->getThisFieldDecl();
return nullptr;
}
/// \brief Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
- virtual const VarDecl *getThreadIDVariable() const override {
+ const VarDecl *getThreadIDVariable() const override {
if (OuterRegionInfo)
return OuterRegionInfo->getThreadIDVariable();
return nullptr;
}
/// \brief Get the name of the capture helper.
- virtual StringRef getHelperName() const override {
+ StringRef getHelperName() const override {
+ if (auto *OuterRegionInfo = getOldCSI())
+ return OuterRegionInfo->getHelperName();
llvm_unreachable("No helper name for inlined OpenMP construct");
}
CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
+ static bool classof(const CGCapturedStmtInfo *Info) {
+ return CGOpenMPRegionInfo::classof(Info) &&
+ cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
+ }
+
private:
/// \brief CodeGen info about outer OpenMP region.
CodeGenFunction::CGCapturedStmtInfo *OldCSI;
CGOpenMPRegionInfo *OuterRegionInfo;
};
+
+/// \brief RAII for emitting code of OpenMP constructs.
+class InlinedOpenMPRegionRAII {
+ CodeGenFunction &CGF;
+
+public:
+ /// \brief Constructs region for combined constructs.
+ /// \param CodeGen Code generation sequence for combined directives. Includes
+ /// a list of functions used for code generation of implicitly inlined
+ /// regions.
+ InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen)
+ : CGF(CGF) {
+ // Start emission for the construct.
+ CGF.CapturedStmtInfo =
+ new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen);
+ }
+ ~InlinedOpenMPRegionRAII() {
+ // Restore original CapturedStmtInfo only if we're done with code emission.
+ auto *OldCSI =
+ cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
+ delete CGF.CapturedStmtInfo;
+ CGF.CapturedStmtInfo = OldCSI;
+ }
+};
+
} // namespace
LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
@@ -172,15 +235,18 @@
->getPointeeType());
}
-void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) {
- CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
- CGF.EmitOMPPrivateClause(Directive, PrivateScope);
- CGF.EmitOMPFirstprivateClause(Directive, PrivateScope);
- if (PrivateScope.Privatize())
- // Emit implicit barrier to synchronize threads and avoid data races.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, Directive.getLocStart(),
- /*IsExplicit=*/false);
- CGCapturedStmtInfo::EmitBody(CGF, S);
+void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CGF.EHStack.pushTerminate();
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CodeGen(CGF);
+ }
+ CGF.EHStack.popTerminate();
}
LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
@@ -190,14 +256,6 @@
getThreadIDVariable()->getType());
}
-void CGOpenMPTaskOutlinedRegionInfo::EmitBody(CodeGenFunction &CGF,
- const Stmt *S) {
- if (PartIDVar) {
- // TODO: emit code for untied tasks.
- }
- CGCapturedStmtInfo::EmitBody(CGF, S);
-}
-
CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
: CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) {
IdentTy = llvm::StructType::create(
@@ -216,13 +274,14 @@
}
llvm::Value *
-CGOpenMPRuntime::emitOutlinedFunction(const OMPExecutableDirective &D,
- const VarDecl *ThreadIDVar) {
+CGOpenMPRuntime::emitParallelOutlinedFunction(const OMPExecutableDirective &D,
+ const VarDecl *ThreadIDVar,
+ const RegionCodeGenTy &CodeGen) {
assert(ThreadIDVar->getType()->isPointerType() &&
"thread id variable must be of type kmp_int32 *");
const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
CodeGenFunction CGF(CGM, true);
- CGOpenMPOutlinedRegionInfo CGInfo(D, *CS, ThreadIDVar);
+ CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen);
CGF.CapturedStmtInfo = &CGInfo;
return CGF.GenerateCapturedStmtFunction(*CS);
}
@@ -230,12 +289,12 @@
llvm::Value *
CGOpenMPRuntime::emitTaskOutlinedFunction(const OMPExecutableDirective &D,
const VarDecl *ThreadIDVar,
- const VarDecl *PartIDVar) {
+ const RegionCodeGenTy &CodeGen) {
assert(!ThreadIDVar->getType()->isPointerType() &&
"thread id variable must be of type kmp_int32 for tasks");
auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
CodeGenFunction CGF(CGM, true);
- CGOpenMPTaskOutlinedRegionInfo CGInfo(D, *CS, ThreadIDVar, PartIDVar);
+ CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen);
CGF.CapturedStmtInfo = &CGInfo;
return CGF.GenerateCapturedStmtFunction(*CS);
}
@@ -303,8 +362,8 @@
}
// char **psource = &.kmpc_loc_<flags>.addr.psource;
- auto *PSource =
- CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource);
+ auto *PSource = CGF.Builder.CreateConstInBoundsGEP2_32(IdentTy, LocValue, 0,
+ IdentField_PSource);
auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
if (OMPDebugLoc == nullptr) {
@@ -595,6 +654,62 @@
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
break;
}
+ case OMPRTL__kmpc_reduce: {
+ // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
+ // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
+ // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
+ llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
+ auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
+ /*isVarArg=*/false);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
+ CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
+ llvm::PointerType::getUnqual(KmpCriticalNameTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
+ break;
+ }
+ case OMPRTL__kmpc_reduce_nowait: {
+ // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
+ // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
+ // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
+ // *lck);
+ llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
+ auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
+ /*isVarArg=*/false);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
+ CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
+ llvm::PointerType::getUnqual(KmpCriticalNameTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
+ break;
+ }
+ case OMPRTL__kmpc_end_reduce: {
+ // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *lck);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty,
+ llvm::PointerType::getUnqual(KmpCriticalNameTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
+ break;
+ }
+ case OMPRTL__kmpc_end_reduce_nowait: {
+ // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *lck);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty,
+ llvm::PointerType::getUnqual(KmpCriticalNameTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn =
+ CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
+ break;
+ }
}
return RTLFn;
}
@@ -906,24 +1021,46 @@
return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
}
-void CGOpenMPRuntime::emitCriticalRegion(
- CodeGenFunction &CGF, StringRef CriticalName,
- const std::function<void()> &CriticalOpGen, SourceLocation Loc) {
- auto RegionLock = getCriticalRegionLock(CriticalName);
+namespace {
+class CallEndCleanup : public EHScopeStack::Cleanup {
+public:
+ typedef ArrayRef<llvm::Value *> CleanupValuesTy;
+private:
+ llvm::Value *Callee;
+ llvm::SmallVector<llvm::Value *, 8> Args;
+
+public:
+ CallEndCleanup(llvm::Value *Callee, CleanupValuesTy Args)
+ : Callee(Callee), Args(Args.begin(), Args.end()) {}
+ void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
+ CGF.EmitRuntimeCall(Callee, Args);
+ }
+};
+} // namespace
+
+void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
+ StringRef CriticalName,
+ const RegionCodeGenTy &CriticalOpGen,
+ SourceLocation Loc) {
// __kmpc_critical(ident_t *, gtid, Lock);
// CriticalOpGen();
// __kmpc_end_critical(ident_t *, gtid, Lock);
// Prepare arguments and build a call to __kmpc_critical
- llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
- RegionLock};
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
- CriticalOpGen();
- // Build a call to __kmpc_end_critical
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ getCriticalRegionLock(CriticalName)};
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
+ // Build a call to __kmpc_end_critical
+ CGF.EHStack.pushCleanup<CallEndCleanup>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
+ llvm::makeArrayRef(Args));
+ emitInlinedDirective(CGF, CriticalOpGen);
+ }
}
static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
- const std::function<void()> &BodyOpGen) {
+ const RegionCodeGenTy &BodyOpGen) {
llvm::Value *CallBool = CGF.EmitScalarConversion(
IfCond,
CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
@@ -934,14 +1071,14 @@
// Generate the branch (If-stmt)
CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
CGF.EmitBlock(ThenBlock);
- BodyOpGen();
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, BodyOpGen);
// Emit the rest of bblocks/branches
CGF.EmitBranch(ContBlock);
CGF.EmitBlock(ContBlock, true);
}
void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
- const std::function<void()> &MasterOpGen,
+ const RegionCodeGenTy &MasterOpGen,
SourceLocation Loc) {
// if(__kmpc_master(ident_t *, gtid)) {
// MasterOpGen();
@@ -951,23 +1088,12 @@
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
auto *IsMaster =
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
- emitIfStmt(CGF, IsMaster, [&]() -> void {
- MasterOpGen();
- // Build a call to __kmpc_end_master.
- // OpenMP [1.2.2 OpenMP Language Terminology]
- // For C/C++, an executable statement, possibly compound, with a single
- // entry at the top and a single exit at the bottom, or an OpenMP construct.
- // * Access to the structured block must not be the result of a branch.
- // * The point of exit cannot be a branch out of the structured block.
- // * The point of entry must not be a call to setjmp().
- // * longjmp() and throw() must not violate the entry/exit criteria.
- // * An expression statement, iteration statement, selection statement, or
- // try block is considered to be a structured block if the corresponding
- // compound statement obtained by enclosing it in { and } would be a
- // structured block.
- // It is analyzed in Sema, so we can just call __kmpc_end_master() on
- // fallthrough rather than pushing a normal cleanup for it.
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_master), Args);
+ emitIfStmt(CGF, IsMaster, [&](CodeGenFunction &CGF) -> void {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CGF.EHStack.pushCleanup<CallEndCleanup>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
+ llvm::makeArrayRef(Args));
+ MasterOpGen(CGF);
});
}
@@ -981,8 +1107,9 @@
}
static llvm::Value *emitCopyprivateCopyFunction(
- CodeGenModule &CGM, llvm::Type *ArgsType, ArrayRef<const Expr *> SrcExprs,
- ArrayRef<const Expr *> DstExprs, ArrayRef<const Expr *> AssignmentOps) {
+ CodeGenModule &CGM, llvm::Type *ArgsType,
+ ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
+ ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
auto &C = CGM.getContext();
// void copy_func(void *LHSArg, void *RHSArg);
FunctionArgList Args;
@@ -1001,7 +1128,7 @@
CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
CodeGenFunction CGF(CGM);
CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
- // Dst = (void*[n])(LHSArg);
+ // Dest = (void*[n])(LHSArg);
// Src = (void*[n])(RHSArg);
auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
@@ -1015,36 +1142,28 @@
// *(Type1*)Dst[1] = *(Type1*)Src[1];
// ...
// *(Typen*)Dst[n] = *(Typen*)Src[n];
- CodeGenFunction::OMPPrivateScope Scope(CGF);
for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
- Scope.addPrivate(
- cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
- [&]() -> llvm::Value *{
- return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(CGF.Builder.CreateStructGEP(RHS, I),
- CGM.PointerAlignInBytes),
- CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
- });
- Scope.addPrivate(
- cast<VarDecl>(cast<DeclRefExpr>(DstExprs[I])->getDecl()),
- [&]() -> llvm::Value *{
- return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(CGF.Builder.CreateStructGEP(LHS, I),
- CGM.PointerAlignInBytes),
- CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
- });
+ auto *DestAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(
+ CGF.Builder.CreateStructGEP(nullptr, LHS, I),
+ CGM.PointerAlignInBytes),
+ CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
+ auto *SrcAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(
+ CGF.Builder.CreateStructGEP(nullptr, RHS, I),
+ CGM.PointerAlignInBytes),
+ CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
+ CGF.EmitOMPCopy(CGF, CopyprivateVars[I]->getType(), DestAddr, SrcAddr,
+ cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()),
+ cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
+ AssignmentOps[I]);
}
- Scope.Privatize();
- for (auto *E : AssignmentOps) {
- CGF.EmitIgnoredExpr(E);
- }
- Scope.ForceCleanup();
CGF.FinishFunction();
return Fn;
}
void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
- const std::function<void()> &SingleOpGen,
+ const RegionCodeGenTy &SingleOpGen,
SourceLocation Loc,
ArrayRef<const Expr *> CopyprivateVars,
ArrayRef<const Expr *> SrcExprs,
@@ -1074,28 +1193,17 @@
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
auto *IsSingle =
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
- emitIfStmt(CGF, IsSingle, [&]() -> void {
- SingleOpGen();
+ emitIfStmt(CGF, IsSingle, [&](CodeGenFunction &CGF) -> void {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CGF.EHStack.pushCleanup<CallEndCleanup>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
+ llvm::makeArrayRef(Args));
+ SingleOpGen(CGF);
if (DidIt) {
// did_it = 1;
CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(1), DidIt,
DidIt->getAlignment());
}
- // Build a call to __kmpc_end_single.
- // OpenMP [1.2.2 OpenMP Language Terminology]
- // For C/C++, an executable statement, possibly compound, with a single
- // entry at the top and a single exit at the bottom, or an OpenMP construct.
- // * Access to the structured block must not be the result of a branch.
- // * The point of exit cannot be a branch out of the structured block.
- // * The point of entry must not be a call to setjmp().
- // * longjmp() and throw() must not violate the entry/exit criteria.
- // * An expression statement, iteration statement, selection statement, or
- // try block is considered to be a structured block if the corresponding
- // compound statement obtained by enclosing it in { and } would be a
- // structured block.
- // It is analyzed in Sema, so we can just call __kmpc_end_single() on
- // fallthrough rather than pushing a normal cleanup for it.
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_single), Args);
});
// call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
// <copy_func>, did_it);
@@ -1108,7 +1216,8 @@
auto *CopyprivateList =
CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
- auto *Elem = CGF.Builder.CreateStructGEP(CopyprivateList, I);
+ auto *Elem = CGF.Builder.CreateStructGEP(
+ CopyprivateList->getAllocatedType(), CopyprivateList, I);
CGF.Builder.CreateAlignedStore(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
CGF.EmitLValue(CopyprivateVars[I]).getAddress(), CGF.VoidPtrTy),
@@ -1118,7 +1227,7 @@
// threads in the corresponding parallel region.
auto *CpyFn = emitCopyprivateCopyFunction(
CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
- SrcExprs, DstExprs, AssignmentOps);
+ CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
auto *BufSize = CGF.Builder.getInt32(
C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity());
auto *CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
@@ -1138,11 +1247,23 @@
}
void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
- bool IsExplicit) {
+ OpenMPDirectiveKind Kind) {
// Build call __kmpc_cancel_barrier(loc, thread_id);
- auto Flags = static_cast<OpenMPLocationFlags>(
- OMP_IDENT_KMPC |
- (IsExplicit ? OMP_IDENT_BARRIER_EXPL : OMP_IDENT_BARRIER_IMPL));
+ OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
+ if (Kind == OMPD_for) {
+ Flags =
+ static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR);
+ } else if (Kind == OMPD_sections) {
+ Flags = static_cast<OpenMPLocationFlags>(Flags |
+ OMP_IDENT_BARRIER_IMPL_SECTIONS);
+ } else if (Kind == OMPD_single) {
+ Flags =
+ static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE);
+ } else if (Kind == OMPD_barrier) {
+ Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL);
+ } else {
+ Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL);
+ }
// Build call __kmpc_cancel_barrier(loc, thread_id);
// Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this
// one provides the same functionality and adds initial support for
@@ -1262,6 +1383,7 @@
assert((ScheduleKind == OMPC_SCHEDULE_static ||
ScheduleKind == OMPC_SCHEDULE_unknown) &&
"Non-static schedule kinds are not yet implemented");
+ (void)ScheduleKind;
// Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
getThreadID(CGF, Loc)};
@@ -1379,7 +1501,8 @@
static llvm::Value *
emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
QualType KmpInt32Ty, QualType KmpTaskTPtrQTy,
- QualType SharedsPtrTy, llvm::Value *TaskFunction) {
+ QualType SharedsPtrTy, llvm::Value *TaskFunction,
+ llvm::Type *KmpTaskTTy) {
auto &C = CGM.getContext();
FunctionArgList Args;
ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
@@ -1407,12 +1530,12 @@
auto TaskTypeArgAddr = CGF.EmitLoadOfScalar(
CGF.GetAddrOfLocalVar(&TaskTypeArg), /*Volatile=*/false,
CGM.PointerAlignInBytes, KmpTaskTPtrQTy, Loc);
- auto *PartidPtr = CGF.Builder.CreateStructGEP(TaskTypeArgAddr,
+ auto *PartidPtr = CGF.Builder.CreateStructGEP(KmpTaskTTy, TaskTypeArgAddr,
/*Idx=*/KmpTaskTPartId);
auto *PartidParam = CGF.EmitLoadOfScalar(
PartidPtr, /*Volatile=*/false,
C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
- auto *SharedsPtr = CGF.Builder.CreateStructGEP(TaskTypeArgAddr,
+ auto *SharedsPtr = CGF.Builder.CreateStructGEP(KmpTaskTTy, TaskTypeArgAddr,
/*Idx=*/KmpTaskTShareds);
auto *SharedsParam =
CGF.EmitLoadOfScalar(SharedsPtr, /*Volatile=*/false,
@@ -1441,14 +1564,16 @@
auto KmpTaskQTy =
createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy);
QualType KmpTaskTPtrQTy = C.getPointerType(KmpTaskQTy);
- auto KmpTaskTPtrTy = CGF.ConvertType(KmpTaskQTy)->getPointerTo();
+ auto *KmpTaskTTy = CGF.ConvertType(KmpTaskQTy);
+ auto *KmpTaskTPtrTy = KmpTaskTTy->getPointerTo();
auto KmpTaskTySize = CGM.getSize(C.getTypeSizeInChars(KmpTaskQTy));
QualType SharedsPtrTy = C.getPointerType(SharedsTy);
// Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
// kmp_task_t *tt);
- auto *TaskEntry = emitProxyTaskFunction(CGM, Loc, KmpInt32Ty, KmpTaskTPtrQTy,
- SharedsPtrTy, TaskFunction);
+ auto *TaskEntry =
+ emitProxyTaskFunction(CGM, Loc, KmpInt32Ty, KmpTaskTPtrQTy, SharedsPtrTy,
+ TaskFunction, KmpTaskTTy);
// Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
// kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
@@ -1481,7 +1606,7 @@
if (!SharedsTy->getAsStructureType()->getDecl()->field_empty())
CGF.EmitAggregateCopy(
CGF.EmitLoadOfScalar(
- CGF.Builder.CreateStructGEP(NewTaskNewTaskTTy,
+ CGF.Builder.CreateStructGEP(KmpTaskTTy, NewTaskNewTaskTTy,
/*Idx=*/KmpTaskTShareds),
/*Volatile=*/false, CGM.PointerAlignInBytes, SharedsPtrTy, Loc),
Shareds, SharedsTy);
@@ -1490,7 +1615,7 @@
CGF.Builder.CreateAlignedStore(
llvm::ConstantPointerNull::get(
cast<llvm::PointerType>(KmpRoutineEntryPtrTy)),
- CGF.Builder.CreateStructGEP(NewTaskNewTaskTTy,
+ CGF.Builder.CreateStructGEP(KmpTaskTTy, NewTaskNewTaskTTy,
/*Idx=*/KmpTaskTDestructors),
CGM.PointerAlignInBytes);
@@ -1504,23 +1629,268 @@
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
}
-InlinedOpenMPRegionRAII::InlinedOpenMPRegionRAII(
- CodeGenFunction &CGF, const OMPExecutableDirective &D)
- : CGF(CGF) {
- CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(D, CGF.CapturedStmtInfo);
- // 1.2.2 OpenMP Language Terminology
- // Structured block - An executable statement with a single entry at the
- // top and a single exit at the bottom.
- // The point of exit cannot be a branch out of the structured block.
- // longjmp() and throw() must not violate the entry/exit criteria.
- CGF.EHStack.pushTerminate();
+static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
+ llvm::Type *ArgsType,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps) {
+ auto &C = CGM.getContext();
+
+ // void reduction_func(void *LHSArg, void *RHSArg);
+ FunctionArgList Args;
+ ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
+ C.VoidPtrTy);
+ ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
+ C.VoidPtrTy);
+ Args.push_back(&LHSArg);
+ Args.push_back(&RHSArg);
+ FunctionType::ExtInfo EI;
+ auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ C.VoidTy, Args, EI, /*isVariadic=*/false);
+ auto *Fn = llvm::Function::Create(
+ CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
+ ".omp.reduction.reduction_func", &CGM.getModule());
+ CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
+ CodeGenFunction CGF(CGM);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+
+ // Dst = (void*[n])(LHSArg);
+ // Src = (void*[n])(RHSArg);
+ auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
+ CGF.PointerAlignInBytes),
+ ArgsType);
+ auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
+ CGF.PointerAlignInBytes),
+ ArgsType);
+
+ // ...
+ // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
+ // ...
+ CodeGenFunction::OMPPrivateScope Scope(CGF);
+ for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I) {
+ Scope.addPrivate(
+ cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()),
+ [&]() -> llvm::Value *{
+ return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(
+ CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, RHS, I),
+ CGM.PointerAlignInBytes),
+ CGF.ConvertTypeForMem(C.getPointerType(RHSExprs[I]->getType())));
+ });
+ Scope.addPrivate(
+ cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()),
+ [&]() -> llvm::Value *{
+ return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(
+ CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, LHS, I),
+ CGM.PointerAlignInBytes),
+ CGF.ConvertTypeForMem(C.getPointerType(LHSExprs[I]->getType())));
+ });
+ }
+ Scope.Privatize();
+ for (auto *E : ReductionOps) {
+ CGF.EmitIgnoredExpr(E);
+ }
+ Scope.ForceCleanup();
+ CGF.FinishFunction();
+ return Fn;
}
-InlinedOpenMPRegionRAII::~InlinedOpenMPRegionRAII() {
- CGF.EHStack.popTerminate();
- auto *OldCSI =
- cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
- delete CGF.CapturedStmtInfo;
- CGF.CapturedStmtInfo = OldCSI;
+void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps,
+ bool WithNowait) {
+ // Next code should be emitted for reduction:
+ //
+ // static kmp_critical_name lock = { 0 };
+ //
+ // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
+ // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
+ // ...
+ // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
+ // *(Type<n>-1*)rhs[<n>-1]);
+ // }
+ //
+ // ...
+ // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
+ // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
+ // RedList, reduce_func, &<lock>)) {
+ // case 1:
+ // ...
+ // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ // ...
+ // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ // break;
+ // case 2:
+ // ...
+ // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
+ // ...
+ // break;
+ // default:;
+ // }
+
+ auto &C = CGM.getContext();
+
+ // 1. Build a list of reduction variables.
+ // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
+ llvm::APInt ArraySize(/*unsigned int numBits=*/32, RHSExprs.size());
+ QualType ReductionArrayTy =
+ C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ auto *ReductionList =
+ CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
+ for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I) {
+ auto *Elem = CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, ReductionList, I);
+ CGF.Builder.CreateAlignedStore(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.EmitLValue(RHSExprs[I]).getAddress(), CGF.VoidPtrTy),
+ Elem, CGM.PointerAlignInBytes);
+ }
+
+ // 2. Emit reduce_func().
+ auto *ReductionFn = emitReductionFunction(
+ CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), LHSExprs,
+ RHSExprs, ReductionOps);
+
+ // 3. Create static kmp_critical_name lock = { 0 };
+ auto *Lock = getCriticalRegionLock(".reduction");
+
+ // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
+ // RedList, reduce_func, &<lock>);
+ auto *IdentTLoc = emitUpdateLocation(
+ CGF, Loc,
+ static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
+ auto *ThreadId = getThreadID(CGF, Loc);
+ auto *ReductionArrayTySize = llvm::ConstantInt::get(
+ CGM.SizeTy, C.getTypeSizeInChars(ReductionArrayTy).getQuantity());
+ auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList,
+ CGF.VoidPtrTy);
+ llvm::Value *Args[] = {
+ IdentTLoc, // ident_t *<loc>
+ ThreadId, // i32 <gtid>
+ CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
+ ReductionArrayTySize, // size_type sizeof(RedList)
+ RL, // void *RedList
+ ReductionFn, // void (*) (void *, void *) <reduce_func>
+ Lock // kmp_critical_name *&<lock>
+ };
+ auto Res = CGF.EmitRuntimeCall(
+ createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
+ : OMPRTL__kmpc_reduce),
+ Args);
+
+ // 5. Build switch(res)
+ auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
+ auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
+
+ // 6. Build case 1:
+ // ...
+ // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ // ...
+ // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ // break;
+ auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
+ SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
+ CGF.EmitBlock(Case1BB);
+
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ llvm::Value *EndArgs[] = {
+ IdentTLoc, // ident_t *<loc>
+ ThreadId, // i32 <gtid>
+ Lock // kmp_critical_name *&<lock>
+ };
+ CGF.EHStack.pushCleanup<CallEndCleanup>(
+ NormalAndEHCleanup,
+ createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
+ : OMPRTL__kmpc_end_reduce),
+ llvm::makeArrayRef(EndArgs));
+ for (auto *E : ReductionOps) {
+ CGF.EmitIgnoredExpr(E);
+ }
+ }
+
+ CGF.EmitBranch(DefaultBB);
+
+ // 7. Build case 2:
+ // ...
+ // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
+ // ...
+ // break;
+ auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
+ SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
+ CGF.EmitBlock(Case2BB);
+
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ auto I = LHSExprs.begin();
+ for (auto *E : ReductionOps) {
+ const Expr *XExpr = nullptr;
+ const Expr *EExpr = nullptr;
+ const Expr *UpExpr = nullptr;
+ BinaryOperatorKind BO = BO_Comma;
+ // Try to emit update expression as a simple atomic.
+ if (auto *ACO = dyn_cast<AbstractConditionalOperator>(E)) {
+ // If this is a conditional operator, analyze it's condition for
+ // min/max reduction operator.
+ E = ACO->getCond();
+ }
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Assign) {
+ XExpr = BO->getLHS();
+ UpExpr = BO->getRHS();
+ }
+ }
+ // Analyze RHS part of the whole expression.
+ if (UpExpr) {
+ if (auto *BORHS =
+ dyn_cast<BinaryOperator>(UpExpr->IgnoreParenImpCasts())) {
+ EExpr = BORHS->getRHS();
+ BO = BORHS->getOpcode();
+ }
+ }
+ if (XExpr) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
+ LValue X = CGF.EmitLValue(XExpr);
+ RValue E;
+ if (EExpr)
+ E = CGF.EmitAnyExpr(EExpr);
+ CGF.EmitOMPAtomicSimpleUpdateExpr(
+ X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
+ [&CGF, UpExpr, VD](RValue XRValue) {
+ CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
+ PrivateScope.addPrivate(
+ VD, [&CGF, VD, XRValue]() -> llvm::Value *{
+ auto *LHSTemp = CGF.CreateMemTemp(VD->getType());
+ CGF.EmitStoreThroughLValue(
+ XRValue,
+ CGF.MakeNaturalAlignAddrLValue(LHSTemp, VD->getType()));
+ return LHSTemp;
+ });
+ (void)PrivateScope.Privatize();
+ return CGF.EmitAnyExpr(UpExpr);
+ });
+ } else {
+ // Emit as a critical region.
+ emitCriticalRegion(CGF, ".atomic_reduction", [E](CodeGenFunction &CGF) {
+ CGF.EmitIgnoredExpr(E);
+ }, Loc);
+ }
+ ++I;
+ }
+ }
+
+ CGF.EmitBranch(DefaultBB);
+ CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
+}
+
+void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
+ const RegionCodeGenTy &CodeGen) {
+ InlinedOpenMPRegionRAII Region(CGF, CodeGen);
+ CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
}
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index f8849e6..fa59930 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -43,7 +43,10 @@
class CodeGenFunction;
class CodeGenModule;
+typedef llvm::function_ref<void(CodeGenFunction &)> RegionCodeGenTy;
+
class CGOpenMPRuntime {
+private:
enum OpenMPRTLFunction {
/// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
/// kmpc_micro microtask, ...);
@@ -100,6 +103,21 @@
// kmp_int32 cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
// kmp_int32 didit);
OMPRTL__kmpc_copyprivate,
+ // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
+ // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
+ // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
+ OMPRTL__kmpc_reduce,
+ // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
+ // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
+ // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
+ // *lck);
+ OMPRTL__kmpc_reduce_nowait,
+ // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *lck);
+ OMPRTL__kmpc_end_reduce,
+ // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *lck);
+ OMPRTL__kmpc_end_reduce_nowait,
};
/// \brief Values for bit flags used in the ident_t to describe the fields.
@@ -284,25 +302,27 @@
virtual ~CGOpenMPRuntime() {}
virtual void clear();
- /// \brief Emits outlined function for the specified OpenMP directive \a D.
- /// This outlined function has type void(*)(kmp_int32 *ThreadID, kmp_int32
- /// BoundID, struct context_vars*).
+ /// \brief Emits outlined function for the specified OpenMP parallel directive
+ /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
+ /// kmp_int32 BoundID, struct context_vars*).
/// \param D OpenMP directive.
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
- ///
- virtual llvm::Value *emitOutlinedFunction(const OMPExecutableDirective &D,
- const VarDecl *ThreadIDVar);
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ virtual llvm::Value *
+ emitParallelOutlinedFunction(const OMPExecutableDirective &D,
+ const VarDecl *ThreadIDVar,
+ const RegionCodeGenTy &CodeGen);
/// \brief Emits outlined function for the OpenMP task directive \a D. This
/// outlined function has type void(*)(kmp_int32 ThreadID, kmp_int32
/// PartID, struct context_vars*).
/// \param D OpenMP directive.
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
- /// \param PartIDVar If not nullptr - variable used for part id in tasks.
+ /// \param CodeGen Code generation sequence for the \a D directive.
///
virtual llvm::Value *emitTaskOutlinedFunction(const OMPExecutableDirective &D,
const VarDecl *ThreadIDVar,
- const VarDecl *PartIDVar);
+ const RegionCodeGenTy &CodeGen);
/// \brief Cleans up references to the objects in finished function.
///
@@ -334,14 +354,14 @@
/// \param CriticalOpGen Generator for the statement associated with the given
/// critical region.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
- const std::function<void()> &CriticalOpGen,
+ const RegionCodeGenTy &CriticalOpGen,
SourceLocation Loc);
/// \brief Emits a master region.
/// \param MasterOpGen Generator for the statement associated with the given
/// master region.
virtual void emitMasterRegion(CodeGenFunction &CGF,
- const std::function<void()> &MasterOpGen,
+ const RegionCodeGenTy &MasterOpGen,
SourceLocation Loc);
/// \brief Emits code for a taskyield directive.
@@ -351,18 +371,19 @@
/// \param SingleOpGen Generator for the statement associated with the given
/// single region.
virtual void emitSingleRegion(CodeGenFunction &CGF,
- const std::function<void()> &SingleOpGen,
+ const RegionCodeGenTy &SingleOpGen,
SourceLocation Loc,
ArrayRef<const Expr *> CopyprivateVars,
+ ArrayRef<const Expr *> DestExprs,
ArrayRef<const Expr *> SrcExprs,
- ArrayRef<const Expr *> DstExprs,
ArrayRef<const Expr *> AssignmentOps);
- /// \brief Emits explicit barrier for OpenMP threads.
- /// \param IsExplicit true, if it is explicitly specified barrier.
+ /// \brief Emit an implicit/explicit barrier for OpenMP threads.
+ /// \param Kind Directive for which this implicit barrier call must be
+ /// generated. Must be OMPD_barrier for explicit barrier generation.
///
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
- bool IsExplicit = true);
+ OpenMPDirectiveKind Kind);
/// \brief Check if the specified \a ScheduleKind is static non-chunked.
/// This kind of worksharing directive is emitted without outer loop.
@@ -505,17 +526,56 @@
llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
llvm::Value *TaskFunction, QualType SharedsTy,
llvm::Value *Shareds);
+
+ /// \brief Emit code for the directive that does not require outlining.
+ ///
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ virtual void emitInlinedDirective(CodeGenFunction &CGF,
+ const RegionCodeGenTy &CodeGen);
+ /// \brief Emit a code for reduction clause. Next code should be emitted for
+ /// reduction:
+ /// \code
+ ///
+ /// static kmp_critical_name lock = { 0 };
+ ///
+ /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
+ /// ...
+ /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
+ /// ...
+ /// }
+ ///
+ /// ...
+ /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
+ /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
+ /// RedList, reduce_func, &<lock>)) {
+ /// case 1:
+ /// ...
+ /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ /// ...
+ /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ /// break;
+ /// case 2:
+ /// ...
+ /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
+ /// ...
+ /// break;
+ /// default:;
+ /// }
+ /// \endcode
+ ///
+ /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
+ /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
+ /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
+ /// or 'operator binop(LHS, RHS)'.
+ /// \param WithNowait true if parent directive has also nowait clause, false
+ /// otherwise.
+ virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps,
+ bool WithNowait);
};
-/// \brief RAII for emitting code of CapturedStmt without function outlining.
-class InlinedOpenMPRegionRAII {
- CodeGenFunction &CGF;
-
-public:
- InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
- const OMPExecutableDirective &D);
- ~InlinedOpenMPRegionRAII();
-};
} // namespace CodeGen
} // namespace clang
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index e433984..481fdbe 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -1021,6 +1021,12 @@
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
+ // Returning from an outlined SEH helper is UB, and we already warn on it.
+ if (IsOutlinedSEHHelper) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+ }
+
// Emit the result value, even if unused, to evalute the side effects.
const Expr *RV = S.getRetValue();
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 9af7474..aa53756 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -23,21 +23,6 @@
//===----------------------------------------------------------------------===//
// OpenMP Directive Emission
//===----------------------------------------------------------------------===//
-namespace {
-/// \brief RAII for inlined OpenMP regions (like 'omp for', 'omp simd', 'omp
-/// critical' etc.). Helps to generate proper debug info and provides correct
-/// code generation for such constructs.
-class InlinedOpenMPRegionScopeRAII {
- InlinedOpenMPRegionRAII Region;
- CodeGenFunction::LexicalScope DirectiveScope;
-
-public:
- InlinedOpenMPRegionScopeRAII(CodeGenFunction &CGF,
- const OMPExecutableDirective &D)
- : Region(CGF, D), DirectiveScope(CGF, D.getSourceRange()) {}
-};
-} // namespace
-
/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
/// function. Here is the logic:
/// if (Cond) {
@@ -84,117 +69,171 @@
CGF.EmitBlock(ContBlock, /*IsFinished*/ true);
}
-void CodeGenFunction::EmitOMPAggregateAssign(LValue OriginalAddr,
- llvm::Value *PrivateAddr,
- const Expr *AssignExpr,
- QualType OriginalType,
- const VarDecl *VDInit) {
- EmitBlock(createBasicBlock(".omp.assign.begin."));
- if (!isa<CXXConstructExpr>(AssignExpr) || isTrivialInitializer(AssignExpr)) {
- // Perform simple memcpy.
- EmitAggregateAssign(PrivateAddr, OriginalAddr.getAddress(),
- AssignExpr->getType());
- } else {
- // Perform element-by-element initialization.
- QualType ElementTy;
- auto SrcBegin = OriginalAddr.getAddress();
- auto DestBegin = PrivateAddr;
- auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
- auto SrcNumElements = emitArrayLength(ArrayTy, ElementTy, SrcBegin);
- auto DestNumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
- auto SrcEnd = Builder.CreateGEP(SrcBegin, SrcNumElements);
- auto DestEnd = Builder.CreateGEP(DestBegin, DestNumElements);
- // The basic structure here is a do-while loop, because we don't
- // need to check for the zero-element case.
- auto BodyBB = createBasicBlock("omp.arraycpy.body");
- auto DoneBB = createBasicBlock("omp.arraycpy.done");
- auto IsEmpty =
- Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
- Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
+void CodeGenFunction::EmitOMPAggregateAssign(
+ llvm::Value *DestAddr, llvm::Value *SrcAddr, QualType OriginalType,
+ const llvm::function_ref<void(llvm::Value *, llvm::Value *)> &CopyGen) {
+ // Perform element-by-element initialization.
+ QualType ElementTy;
+ auto SrcBegin = SrcAddr;
+ auto DestBegin = DestAddr;
+ auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
+ auto NumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
+ // Cast from pointer to array type to pointer to single element.
+ SrcBegin = Builder.CreatePointerBitCastOrAddrSpaceCast(SrcBegin,
+ DestBegin->getType());
+ auto DestEnd = Builder.CreateGEP(DestBegin, NumElements);
+ // The basic structure here is a while-do loop.
+ auto BodyBB = createBasicBlock("omp.arraycpy.body");
+ auto DoneBB = createBasicBlock("omp.arraycpy.done");
+ auto IsEmpty =
+ Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
+ Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
- // Enter the loop body, making that address the current address.
- auto EntryBB = Builder.GetInsertBlock();
- EmitBlock(BodyBB);
- auto SrcElementPast = Builder.CreatePHI(SrcBegin->getType(), 2,
- "omp.arraycpy.srcElementPast");
- SrcElementPast->addIncoming(SrcEnd, EntryBB);
- auto DestElementPast = Builder.CreatePHI(DestBegin->getType(), 2,
- "omp.arraycpy.destElementPast");
- DestElementPast->addIncoming(DestEnd, EntryBB);
+ // Enter the loop body, making that address the current address.
+ auto EntryBB = Builder.GetInsertBlock();
+ EmitBlock(BodyBB);
+ auto SrcElementCurrent =
+ Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast");
+ SrcElementCurrent->addIncoming(SrcBegin, EntryBB);
+ auto DestElementCurrent = Builder.CreatePHI(DestBegin->getType(), 2,
+ "omp.arraycpy.destElementPast");
+ DestElementCurrent->addIncoming(DestBegin, EntryBB);
- // Shift the address back by one element.
- auto NegativeOne = llvm::ConstantInt::get(SizeTy, -1, true);
- auto DestElement = Builder.CreateGEP(DestElementPast, NegativeOne,
- "omp.arraycpy.dest.element");
- auto SrcElement = Builder.CreateGEP(SrcElementPast, NegativeOne,
- "omp.arraycpy.src.element");
- {
- // Create RunCleanScope to cleanup possible temps.
- CodeGenFunction::RunCleanupsScope Init(*this);
- // Emit initialization for single element.
- LocalDeclMap[VDInit] = SrcElement;
- EmitAnyExprToMem(AssignExpr, DestElement,
- AssignExpr->getType().getQualifiers(),
- /*IsInitializer*/ false);
- LocalDeclMap.erase(VDInit);
- }
+ // Emit copy.
+ CopyGen(DestElementCurrent, SrcElementCurrent);
- // Check whether we've reached the end.
- auto Done =
- Builder.CreateICmpEQ(DestElement, DestBegin, "omp.arraycpy.done");
- Builder.CreateCondBr(Done, DoneBB, BodyBB);
- DestElementPast->addIncoming(DestElement, Builder.GetInsertBlock());
- SrcElementPast->addIncoming(SrcElement, Builder.GetInsertBlock());
+ // Shift the address forward by one element.
+ auto DestElementNext = Builder.CreateConstGEP1_32(
+ DestElementCurrent, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ auto SrcElementNext = Builder.CreateConstGEP1_32(
+ SrcElementCurrent, /*Idx0=*/1, "omp.arraycpy.src.element");
+ // Check whether we've reached the end.
+ auto Done =
+ Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
+ Builder.CreateCondBr(Done, DoneBB, BodyBB);
+ DestElementCurrent->addIncoming(DestElementNext, Builder.GetInsertBlock());
+ SrcElementCurrent->addIncoming(SrcElementNext, Builder.GetInsertBlock());
- // Done.
- EmitBlock(DoneBB, true);
- }
- EmitBlock(createBasicBlock(".omp.assign.end."));
+ // Done.
+ EmitBlock(DoneBB, /*IsFinished=*/true);
}
-void CodeGenFunction::EmitOMPFirstprivateClause(
- const OMPExecutableDirective &D,
- CodeGenFunction::OMPPrivateScope &PrivateScope) {
- auto PrivateFilter = [](const OMPClause *C) -> bool {
+void CodeGenFunction::EmitOMPCopy(CodeGenFunction &CGF,
+ QualType OriginalType, llvm::Value *DestAddr,
+ llvm::Value *SrcAddr, const VarDecl *DestVD,
+ const VarDecl *SrcVD, const Expr *Copy) {
+ if (OriginalType->isArrayType()) {
+ auto *BO = dyn_cast<BinaryOperator>(Copy);
+ if (BO && BO->getOpcode() == BO_Assign) {
+ // Perform simple memcpy for simple copying.
+ CGF.EmitAggregateAssign(DestAddr, SrcAddr, OriginalType);
+ } else {
+ // For arrays with complex element types perform element by element
+ // copying.
+ CGF.EmitOMPAggregateAssign(
+ DestAddr, SrcAddr, OriginalType,
+ [&CGF, Copy, SrcVD, DestVD](llvm::Value *DestElement,
+ llvm::Value *SrcElement) {
+ // Working with the single array element, so have to remap
+ // destination and source variables to corresponding array
+ // elements.
+ CodeGenFunction::OMPPrivateScope Remap(CGF);
+ Remap.addPrivate(DestVD, [DestElement]() -> llvm::Value *{
+ return DestElement;
+ });
+ Remap.addPrivate(
+ SrcVD, [SrcElement]() -> llvm::Value *{ return SrcElement; });
+ (void)Remap.Privatize();
+ CGF.EmitIgnoredExpr(Copy);
+ });
+ }
+ } else {
+ // Remap pseudo source variable to private copy.
+ CodeGenFunction::OMPPrivateScope Remap(CGF);
+ Remap.addPrivate(SrcVD, [SrcAddr]() -> llvm::Value *{ return SrcAddr; });
+ Remap.addPrivate(DestVD, [DestAddr]() -> llvm::Value *{ return DestAddr; });
+ (void)Remap.Privatize();
+ // Emit copying of the whole variable.
+ CGF.EmitIgnoredExpr(Copy);
+ }
+}
+
+bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
+ OMPPrivateScope &PrivateScope) {
+ auto FirstprivateFilter = [](const OMPClause *C) -> bool {
return C->getClauseKind() == OMPC_firstprivate;
};
- for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
- I(D.clauses(), PrivateFilter); I; ++I) {
+ llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
+ for (OMPExecutableDirective::filtered_clause_iterator<decltype(
+ FirstprivateFilter)> I(D.clauses(), FirstprivateFilter);
+ I; ++I) {
auto *C = cast<OMPFirstprivateClause>(*I);
auto IRef = C->varlist_begin();
auto InitsRef = C->inits().begin();
for (auto IInit : C->private_copies()) {
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
- bool IsRegistered;
- if (*InitsRef != nullptr) {
- // Emit VarDecl with copy init for arrays.
- auto *FD = CapturedStmtInfo->lookup(OrigVD);
- LValue Base = MakeNaturalAlignAddrLValue(
- CapturedStmtInfo->getContextValue(),
- getContext().getTagDeclType(FD->getParent()));
- auto OriginalAddr = EmitLValueForField(Base, FD);
- auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
- IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
- auto Emission = EmitAutoVarAlloca(*VD);
- // Emit initialization of aggregate firstprivate vars.
- EmitOMPAggregateAssign(OriginalAddr, Emission.getAllocatedAddress(),
- VD->getInit(), (*IRef)->getType(), VDInit);
- EmitAutoVarCleanups(Emission);
- return Emission.getAllocatedAddress();
- });
- } else
- IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
- // Emit private VarDecl with copy init.
- EmitDecl(*VD);
- return GetAddrOfLocalVar(VD);
- });
- assert(IsRegistered && "firstprivate var already registered as private");
- // Silence the warning about unused variable.
- (void)IsRegistered;
+ if (EmittedAsFirstprivate.count(OrigVD) == 0) {
+ EmittedAsFirstprivate.insert(OrigVD);
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
+ bool IsRegistered;
+ DeclRefExpr DRE(
+ const_cast<VarDecl *>(OrigVD),
+ /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
+ OrigVD) != nullptr,
+ (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
+ auto *OriginalAddr = EmitLValue(&DRE).getAddress();
+ if (OrigVD->getType()->isArrayType()) {
+ // Emit VarDecl with copy init for arrays.
+ // Get the address of the original variable captured in current
+ // captured region.
+ IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ auto Emission = EmitAutoVarAlloca(*VD);
+ auto *Init = VD->getInit();
+ if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
+ // Perform simple memcpy.
+ EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr,
+ (*IRef)->getType());
+ } else {
+ EmitOMPAggregateAssign(
+ Emission.getAllocatedAddress(), OriginalAddr,
+ (*IRef)->getType(),
+ [this, VDInit, Init](llvm::Value *DestElement,
+ llvm::Value *SrcElement) {
+ // Clean up any temporaries needed by the initialization.
+ RunCleanupsScope InitScope(*this);
+ // Emit initialization for single element.
+ LocalDeclMap[VDInit] = SrcElement;
+ EmitAnyExprToMem(Init, DestElement,
+ Init->getType().getQualifiers(),
+ /*IsInitializer*/ false);
+ LocalDeclMap.erase(VDInit);
+ });
+ }
+ EmitAutoVarCleanups(Emission);
+ return Emission.getAllocatedAddress();
+ });
+ } else {
+ IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ // Emit private VarDecl with copy init.
+ // Remap temp VDInit variable to the address of the original
+ // variable
+ // (for proper handling of captured global variables).
+ LocalDeclMap[VDInit] = OriginalAddr;
+ EmitDecl(*VD);
+ LocalDeclMap.erase(VDInit);
+ return GetAddrOfLocalVar(VD);
+ });
+ }
+ assert(IsRegistered &&
+ "firstprivate var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+ }
++IRef, ++InitsRef;
}
}
+ return !EmittedAsFirstprivate.empty();
}
void CodeGenFunction::EmitOMPPrivateClause(
@@ -224,9 +263,225 @@
}
}
+bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
+ // threadprivate_var1 = master_threadprivate_var1;
+ // operator=(threadprivate_var2, master_threadprivate_var2);
+ // ...
+ // __kmpc_barrier(&loc, global_tid);
+ auto CopyinFilter = [](const OMPClause *C) -> bool {
+ return C->getClauseKind() == OMPC_copyin;
+ };
+ llvm::DenseSet<const VarDecl *> CopiedVars;
+ llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr;
+ for (OMPExecutableDirective::filtered_clause_iterator<decltype(CopyinFilter)>
+ I(D.clauses(), CopyinFilter);
+ I; ++I) {
+ auto *C = cast<OMPCopyinClause>(*I);
+ auto IRef = C->varlist_begin();
+ auto ISrcRef = C->source_exprs().begin();
+ auto IDestRef = C->destination_exprs().begin();
+ for (auto *AssignOp : C->assignment_ops()) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
+ // Get the address of the master variable.
+ auto *MasterAddr = VD->isStaticLocal()
+ ? CGM.getStaticLocalDeclAddress(VD)
+ : CGM.GetAddrOfGlobal(VD);
+ // Get the address of the threadprivate variable.
+ auto *PrivateAddr = EmitLValue(*IRef).getAddress();
+ if (CopiedVars.size() == 1) {
+ // At first check if current thread is a master thread. If it is, no
+ // need to copy data.
+ CopyBegin = createBasicBlock("copyin.not.master");
+ CopyEnd = createBasicBlock("copyin.not.master.end");
+ Builder.CreateCondBr(
+ Builder.CreateICmpNE(
+ Builder.CreatePtrToInt(MasterAddr, CGM.IntPtrTy),
+ Builder.CreatePtrToInt(PrivateAddr, CGM.IntPtrTy)),
+ CopyBegin, CopyEnd);
+ EmitBlock(CopyBegin);
+ }
+ auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
+ auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ EmitOMPCopy(*this, (*IRef)->getType(), PrivateAddr, MasterAddr, DestVD,
+ SrcVD, AssignOp);
+ }
+ ++IRef;
+ ++ISrcRef;
+ ++IDestRef;
+ }
+ }
+ if (CopyEnd) {
+ // Exit out of copying procedure for non-master thread.
+ EmitBlock(CopyEnd, /*IsFinished=*/true);
+ return true;
+ }
+ return false;
+}
+
+bool CodeGenFunction::EmitOMPLastprivateClauseInit(
+ const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) {
+ auto LastprivateFilter = [](const OMPClause *C) -> bool {
+ return C->getClauseKind() == OMPC_lastprivate;
+ };
+ bool HasAtLeastOneLastprivate = false;
+ llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
+ for (OMPExecutableDirective::filtered_clause_iterator<decltype(
+ LastprivateFilter)> I(D.clauses(), LastprivateFilter);
+ I; ++I) {
+ auto *C = cast<OMPLastprivateClause>(*I);
+ auto IRef = C->varlist_begin();
+ auto IDestRef = C->destination_exprs().begin();
+ for (auto *IInit : C->private_copies()) {
+ // Keep the address of the original variable for future update at the end
+ // of the loop.
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
+ auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() -> llvm::Value *{
+ DeclRefExpr DRE(
+ const_cast<VarDecl *>(OrigVD),
+ /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
+ OrigVD) != nullptr,
+ (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
+ return EmitLValue(&DRE).getAddress();
+ });
+ // Check if the variable is also a firstprivate: in this case IInit is
+ // not generated. Initialization of this variable will happen in codegen
+ // for 'firstprivate' clause.
+ if (!IInit)
+ continue;
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ bool IsRegistered =
+ PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ // Emit private VarDecl with copy init.
+ EmitDecl(*VD);
+ return GetAddrOfLocalVar(VD);
+ });
+ assert(IsRegistered && "lastprivate var already registered as private");
+ HasAtLeastOneLastprivate = HasAtLeastOneLastprivate || IsRegistered;
+ }
+ ++IRef, ++IDestRef;
+ }
+ }
+ return HasAtLeastOneLastprivate;
+}
+
+void CodeGenFunction::EmitOMPLastprivateClauseFinal(
+ const OMPExecutableDirective &D, llvm::Value *IsLastIterCond) {
+ // Emit following code:
+ // if (<IsLastIterCond>) {
+ // orig_var1 = private_orig_var1;
+ // ...
+ // orig_varn = private_orig_varn;
+ // }
+ auto *ThenBB = createBasicBlock(".omp.lastprivate.then");
+ auto *DoneBB = createBasicBlock(".omp.lastprivate.done");
+ Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
+ EmitBlock(ThenBB);
+ {
+ auto LastprivateFilter = [](const OMPClause *C) -> bool {
+ return C->getClauseKind() == OMPC_lastprivate;
+ };
+ llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
+ for (OMPExecutableDirective::filtered_clause_iterator<decltype(
+ LastprivateFilter)> I(D.clauses(), LastprivateFilter);
+ I; ++I) {
+ auto *C = cast<OMPLastprivateClause>(*I);
+ auto IRef = C->varlist_begin();
+ auto ISrcRef = C->source_exprs().begin();
+ auto IDestRef = C->destination_exprs().begin();
+ for (auto *AssignOp : C->assignment_ops()) {
+ auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ if (AlreadyEmittedVars.insert(PrivateVD->getCanonicalDecl()).second) {
+ auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
+ auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ // Get the address of the original variable.
+ auto *OriginalAddr = GetAddrOfLocalVar(DestVD);
+ // Get the address of the private variable.
+ auto *PrivateAddr = GetAddrOfLocalVar(PrivateVD);
+ EmitOMPCopy(*this, (*IRef)->getType(), OriginalAddr, PrivateAddr,
+ DestVD, SrcVD, AssignOp);
+ }
+ ++IRef;
+ ++ISrcRef;
+ ++IDestRef;
+ }
+ }
+ }
+ EmitBlock(DoneBB, /*IsFinished=*/true);
+}
+
+void CodeGenFunction::EmitOMPReductionClauseInit(
+ const OMPExecutableDirective &D,
+ CodeGenFunction::OMPPrivateScope &PrivateScope) {
+ auto ReductionFilter = [](const OMPClause *C) -> bool {
+ return C->getClauseKind() == OMPC_reduction;
+ };
+ for (OMPExecutableDirective::filtered_clause_iterator<decltype(
+ ReductionFilter)> I(D.clauses(), ReductionFilter);
+ I; ++I) {
+ auto *C = cast<OMPReductionClause>(*I);
+ auto ILHS = C->lhs_exprs().begin();
+ auto IRHS = C->rhs_exprs().begin();
+ for (auto IRef : C->varlists()) {
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
+ auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ // Store the address of the original variable associated with the LHS
+ // implicit variable.
+ PrivateScope.addPrivate(LHSVD, [this, OrigVD, IRef]() -> llvm::Value *{
+ DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ CapturedStmtInfo->lookup(OrigVD) != nullptr,
+ IRef->getType(), VK_LValue, IRef->getExprLoc());
+ return EmitLValue(&DRE).getAddress();
+ });
+ // Emit reduction copy.
+ bool IsRegistered =
+ PrivateScope.addPrivate(OrigVD, [this, PrivateVD]() -> llvm::Value *{
+ // Emit private VarDecl with reduction init.
+ EmitDecl(*PrivateVD);
+ return GetAddrOfLocalVar(PrivateVD);
+ });
+ assert(IsRegistered && "private var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+ ++ILHS, ++IRHS;
+ }
+ }
+}
+
+void CodeGenFunction::EmitOMPReductionClauseFinal(
+ const OMPExecutableDirective &D) {
+ llvm::SmallVector<const Expr *, 8> LHSExprs;
+ llvm::SmallVector<const Expr *, 8> RHSExprs;
+ llvm::SmallVector<const Expr *, 8> ReductionOps;
+ auto ReductionFilter = [](const OMPClause *C) -> bool {
+ return C->getClauseKind() == OMPC_reduction;
+ };
+ bool HasAtLeastOneReduction = false;
+ for (OMPExecutableDirective::filtered_clause_iterator<decltype(
+ ReductionFilter)> I(D.clauses(), ReductionFilter);
+ I; ++I) {
+ HasAtLeastOneReduction = true;
+ auto *C = cast<OMPReductionClause>(*I);
+ LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
+ RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
+ ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
+ }
+ if (HasAtLeastOneReduction) {
+ // Emit nowait reduction if nowait clause is present or directive is a
+ // parallel directive (it always has implicit barrier).
+ CGM.getOpenMPRuntime().emitReduction(
+ *this, D.getLocEnd(), LHSExprs, RHSExprs, ReductionOps,
+ D.getSingleClause(OMPC_nowait) ||
+ isOpenMPParallelDirective(D.getDirectiveKind()));
+ }
+}
+
/// \brief Emits code for OpenMP parallel directive in the parallel region.
-static void EmitOMPParallelCall(CodeGenFunction &CGF,
- const OMPParallelDirective &S,
+static void emitOMPParallelCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S,
llvm::Value *OutlinedFn,
llvm::Value *CapturedStruct) {
if (auto C = S.getSingleClause(/*K*/ OMPC_num_threads)) {
@@ -241,22 +496,51 @@
CapturedStruct);
}
-void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
+static void emitCommonOMPParallelDirective(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S,
+ const RegionCodeGenTy &CodeGen) {
auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
- auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
- auto OutlinedFn = CGM.getOpenMPRuntime().emitOutlinedFunction(
- S, *CS->getCapturedDecl()->param_begin());
+ auto CapturedStruct = CGF.GenerateCapturedStmtArgument(*CS);
+ auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
+ S, *CS->getCapturedDecl()->param_begin(), CodeGen);
if (auto C = S.getSingleClause(/*K*/ OMPC_if)) {
auto Cond = cast<OMPIfClause>(C)->getCondition();
- EmitOMPIfClause(*this, Cond, [&](bool ThenBlock) {
+ EmitOMPIfClause(CGF, Cond, [&](bool ThenBlock) {
if (ThenBlock)
- EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
+ emitOMPParallelCall(CGF, S, OutlinedFn, CapturedStruct);
else
- CGM.getOpenMPRuntime().emitSerialCall(*this, S.getLocStart(),
- OutlinedFn, CapturedStruct);
+ CGF.CGM.getOpenMPRuntime().emitSerialCall(CGF, S.getLocStart(),
+ OutlinedFn, CapturedStruct);
});
} else
- EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
+ emitOMPParallelCall(CGF, S, OutlinedFn, CapturedStruct);
+}
+
+void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ // Emit parallel region as a standalone region.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ OMPPrivateScope PrivateScope(CGF);
+ bool Copyins = CGF.EmitOMPCopyinClause(S);
+ bool Firstprivates = CGF.EmitOMPFirstprivateClause(S, PrivateScope);
+ if (Copyins || Firstprivates) {
+ // Emit implicit barrier to synchronize threads and avoid data races on
+ // initialization of firstprivate variables or propagation master's thread
+ // values of threadprivate variables to local instances of that variables
+ // of all other implicit threads.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_unknown);
+ }
+ CGF.EmitOMPPrivateClause(S, PrivateScope);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitOMPReductionClauseFinal(S);
+ // Emit implicit barrier at the end of the 'parallel' directive.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_unknown);
+ };
+ emitCommonOMPParallelDirective(*this, S, CodeGen);
}
void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S,
@@ -289,10 +573,10 @@
}
}
-void CodeGenFunction::EmitOMPInnerLoop(const Stmt &S, bool RequiresCleanup,
- const Expr *LoopCond,
- const Expr *IncExpr,
- const std::function<void()> &BodyGen) {
+void CodeGenFunction::EmitOMPInnerLoop(
+ const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
+ const Expr *IncExpr,
+ const llvm::function_ref<void(CodeGenFunction &)> &BodyGen) {
auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
auto Cnt = getPGORegionCounter(&S);
@@ -323,7 +607,7 @@
auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
- BodyGen();
+ BodyGen(*this);
// Emit "IV = IV + 1" and a back-edge to the condition block.
EmitBlock(Continue.getBlock());
@@ -414,129 +698,132 @@
}
void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
- // Pragma 'simd' code depends on presence of 'lastprivate'.
- // If present, we have to separate last iteration of the loop:
- //
- // if (LastIteration != 0) {
- // for (IV in 0..LastIteration-1) BODY;
- // BODY with updates of lastprivate vars;
- // <Final counter/linear vars updates>;
- // }
- //
- // otherwise (when there's no lastprivate):
- //
- // for (IV in 0..LastIteration) BODY;
- // <Final counter/linear vars updates>;
- //
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ // Pragma 'simd' code depends on presence of 'lastprivate'.
+ // If present, we have to separate last iteration of the loop:
+ //
+ // if (LastIteration != 0) {
+ // for (IV in 0..LastIteration-1) BODY;
+ // BODY with updates of lastprivate vars;
+ // <Final counter/linear vars updates>;
+ // }
+ //
+ // otherwise (when there's no lastprivate):
+ //
+ // for (IV in 0..LastIteration) BODY;
+ // <Final counter/linear vars updates>;
+ //
- // Walk clauses and process safelen/lastprivate.
- bool SeparateIter = false;
- LoopStack.setParallel();
- LoopStack.setVectorizerEnable(true);
- for (auto C : S.clauses()) {
- switch (C->getClauseKind()) {
- case OMPC_safelen: {
- RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
- AggValueSlot::ignored(), true);
- llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
- LoopStack.setVectorizerWidth(Val->getZExtValue());
- // In presence of finite 'safelen', it may be unsafe to mark all
- // the memory instructions parallel, because loop-carried
- // dependences of 'safelen' iterations are possible.
- LoopStack.setParallel(false);
- break;
- }
- case OMPC_aligned:
- EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
- break;
- case OMPC_lastprivate:
- SeparateIter = true;
- break;
- default:
- // Not handled yet
- ;
- }
- }
-
- InlinedOpenMPRegionScopeRAII Region(*this, S);
-
- // Emit inits for the linear variables.
- for (auto C : OMPExecutableDirective::linear_filter(S.clauses())) {
- for (auto Init : C->inits()) {
- auto *D = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
- EmitVarDecl(*D);
- }
- }
-
- // Emit the loop iteration variable.
- const Expr *IVExpr = S.getIterationVariable();
- const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
- EmitVarDecl(*IVDecl);
- EmitIgnoredExpr(S.getInit());
-
- // Emit the iterations count variable.
- // If it is not a variable, Sema decided to calculate iterations count on each
- // iteration (e.g., it is foldable into a constant).
- if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
- EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
- // Emit calculation of the iterations count.
- EmitIgnoredExpr(S.getCalcLastIteration());
- }
-
- // Emit the linear steps for the linear clauses.
- // If a step is not constant, it is pre-calculated before the loop.
- for (auto C : OMPExecutableDirective::linear_filter(S.clauses())) {
- if (auto CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
- if (auto SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
- EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
- // Emit calculation of the linear step.
- EmitIgnoredExpr(CS);
+ // Walk clauses and process safelen/lastprivate.
+ bool SeparateIter = false;
+ CGF.LoopStack.setParallel();
+ CGF.LoopStack.setVectorizerEnable(true);
+ for (auto C : S.clauses()) {
+ switch (C->getClauseKind()) {
+ case OMPC_safelen: {
+ RValue Len = CGF.EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
+ AggValueSlot::ignored(), true);
+ llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
+ CGF.LoopStack.setVectorizerWidth(Val->getZExtValue());
+ // In presence of finite 'safelen', it may be unsafe to mark all
+ // the memory instructions parallel, because loop-carried
+ // dependences of 'safelen' iterations are possible.
+ CGF.LoopStack.setParallel(false);
+ break;
}
- }
+ case OMPC_aligned:
+ EmitOMPAlignedClause(CGF, CGF.CGM, cast<OMPAlignedClause>(*C));
+ break;
+ case OMPC_lastprivate:
+ SeparateIter = true;
+ break;
+ default:
+ // Not handled yet
+ ;
+ }
+ }
- if (SeparateIter) {
- // Emit: if (LastIteration > 0) - begin.
- RegionCounter Cnt = getPGORegionCounter(&S);
- auto ThenBlock = createBasicBlock("simd.if.then");
- auto ContBlock = createBasicBlock("simd.if.end");
- EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
- EmitBlock(ThenBlock);
- Cnt.beginRegion(Builder);
- // Emit 'then' code.
- {
- OMPPrivateScope LoopScope(*this);
- EmitPrivateLoopCounters(*this, LoopScope, S.counters());
- EmitPrivateLinearVars(*this, S, LoopScope);
- EmitOMPPrivateClause(S, LoopScope);
- (void)LoopScope.Privatize();
- EmitOMPInnerLoop(S, LoopScope.requiresCleanups(),
- S.getCond(/*SeparateIter=*/true), S.getInc(),
- [&S, this]() {
- EmitOMPLoopBody(S);
- EmitStopPoint(&S);
- });
- EmitOMPLoopBody(S, /* SeparateIter */ true);
+ // Emit inits for the linear variables.
+ for (auto C : OMPExecutableDirective::linear_filter(S.clauses())) {
+ for (auto Init : C->inits()) {
+ auto *D = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
+ CGF.EmitVarDecl(*D);
+ }
}
- EmitOMPSimdFinal(S);
- // Emit: if (LastIteration != 0) - end.
- EmitBranch(ContBlock);
- EmitBlock(ContBlock, true);
- } else {
- {
- OMPPrivateScope LoopScope(*this);
- EmitPrivateLoopCounters(*this, LoopScope, S.counters());
- EmitPrivateLinearVars(*this, S, LoopScope);
- EmitOMPPrivateClause(S, LoopScope);
- (void)LoopScope.Privatize();
- EmitOMPInnerLoop(S, LoopScope.requiresCleanups(),
- S.getCond(/*SeparateIter=*/false), S.getInc(),
- [&S, this]() {
- EmitOMPLoopBody(S);
- EmitStopPoint(&S);
- });
+
+ // Emit the loop iteration variable.
+ const Expr *IVExpr = S.getIterationVariable();
+ const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
+ CGF.EmitVarDecl(*IVDecl);
+ CGF.EmitIgnoredExpr(S.getInit());
+
+ // Emit the iterations count variable.
+ // If it is not a variable, Sema decided to calculate iterations count on
+ // each
+ // iteration (e.g., it is foldable into a constant).
+ if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
+ CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
+ // Emit calculation of the iterations count.
+ CGF.EmitIgnoredExpr(S.getCalcLastIteration());
}
- EmitOMPSimdFinal(S);
- }
+
+ // Emit the linear steps for the linear clauses.
+ // If a step is not constant, it is pre-calculated before the loop.
+ for (auto C : OMPExecutableDirective::linear_filter(S.clauses())) {
+ if (auto CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
+ if (auto SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
+ CGF.EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
+ // Emit calculation of the linear step.
+ CGF.EmitIgnoredExpr(CS);
+ }
+ }
+
+ if (SeparateIter) {
+ // Emit: if (LastIteration > 0) - begin.
+ RegionCounter Cnt = CGF.getPGORegionCounter(&S);
+ auto ThenBlock = CGF.createBasicBlock("simd.if.then");
+ auto ContBlock = CGF.createBasicBlock("simd.if.end");
+ CGF.EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock,
+ Cnt.getCount());
+ CGF.EmitBlock(ThenBlock);
+ Cnt.beginRegion(CGF.Builder);
+ // Emit 'then' code.
+ {
+ OMPPrivateScope LoopScope(CGF);
+ EmitPrivateLoopCounters(CGF, LoopScope, S.counters());
+ EmitPrivateLinearVars(CGF, S, LoopScope);
+ CGF.EmitOMPPrivateClause(S, LoopScope);
+ (void)LoopScope.Privatize();
+ CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(),
+ S.getCond(/*SeparateIter=*/true), S.getInc(),
+ [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S);
+ CGF.EmitStopPoint(&S);
+ });
+ CGF.EmitOMPLoopBody(S, /* SeparateIter */ true);
+ }
+ CGF.EmitOMPSimdFinal(S);
+ // Emit: if (LastIteration != 0) - end.
+ CGF.EmitBranch(ContBlock);
+ CGF.EmitBlock(ContBlock, true);
+ } else {
+ {
+ OMPPrivateScope LoopScope(CGF);
+ EmitPrivateLoopCounters(CGF, LoopScope, S.counters());
+ EmitPrivateLinearVars(CGF, S, LoopScope);
+ CGF.EmitOMPPrivateClause(S, LoopScope);
+ (void)LoopScope.Privatize();
+ CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(),
+ S.getCond(/*SeparateIter=*/false), S.getInc(),
+ [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S);
+ CGF.EmitStopPoint(&S);
+ });
+ }
+ CGF.EmitOMPSimdFinal(S);
+ }
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
}
void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
@@ -654,9 +941,10 @@
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
EmitOMPInnerLoop(S, LoopScope.requiresCleanups(),
- S.getCond(/*SeparateIter=*/false), S.getInc(), [&S, this]() {
- EmitOMPLoopBody(S);
- EmitStopPoint(&S);
+ S.getCond(/*SeparateIter=*/false), S.getInc(),
+ [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S);
+ CGF.EmitStopPoint(&S);
});
EmitBlock(Continue.getBlock());
@@ -686,7 +974,7 @@
return CGF.EmitLValue(Helper);
}
-void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
+bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
// Emit the loop iteration variable.
auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
auto IVDecl = cast<VarDecl>(IVExpr->getDecl());
@@ -703,6 +991,7 @@
auto &RT = CGM.getOpenMPRuntime();
+ bool HasLastprivateClause;
// Check pre-condition.
{
// Skip the entire loop if we don't meet the precondition.
@@ -725,6 +1014,13 @@
EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
OMPPrivateScope LoopScope(*this);
+ if (EmitOMPFirstprivateClause(S, LoopScope)) {
+ // Emit implicit barrier to synchronize threads and avoid data races on
+ // initialization of firstprivate variables.
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
+ OMPD_unknown);
+ }
+ HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
EmitPrivateLoopCounters(*this, LoopScope, S.counters());
(void)LoopScope.Privatize();
@@ -759,9 +1055,9 @@
// while (idx <= UB) { BODY; ++idx; }
EmitOMPInnerLoop(S, LoopScope.requiresCleanups(),
S.getCond(/*SeparateIter=*/false), S.getInc(),
- [&S, this]() {
- EmitOMPLoopBody(S);
- EmitStopPoint(&S);
+ [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S);
+ CGF.EmitStopPoint(&S);
});
// Tell the runtime we are done.
RT.emitForFinish(*this, S.getLocStart(), ScheduleKind);
@@ -772,21 +1068,30 @@
UB.getAddress(), ST.getAddress(), IL.getAddress(),
Chunk);
}
+ // Emit final copy of the lastprivate variables if IsLastIter != 0.
+ if (HasLastprivateClause)
+ EmitOMPLastprivateClauseFinal(
+ S, Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getLocStart())));
}
// We're now done with the loop, so jump to the continuation block.
EmitBranch(ContBlock);
EmitBlock(ContBlock, true);
}
+ return HasLastprivateClause;
}
void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
- InlinedOpenMPRegionScopeRAII Region(*this, S);
-
- EmitOMPWorksharingLoop(S);
+ LexicalScope Scope(*this, S.getSourceRange());
+ bool HasLastprivates = false;
+ auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
+ HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
// Emit an implicit barrier at the end.
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
- /*IsExplicit*/ false);
+ if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
+ }
}
void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) {
@@ -802,107 +1107,122 @@
return LVal;
}
-void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
- InlinedOpenMPRegionScopeRAII Region(*this, S);
-
+static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S) {
auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
auto *CS = dyn_cast<CompoundStmt>(Stmt);
if (CS && CS->size() > 1) {
- auto &C = CGM.getContext();
- auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
- // Emit helper vars inits.
- LValue LB = createSectionLVal(*this, KmpInt32Ty, ".omp.sections.lb.",
- Builder.getInt32(0));
- auto *GlobalUBVal = Builder.getInt32(CS->size() - 1);
- LValue UB =
- createSectionLVal(*this, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
- LValue ST = createSectionLVal(*this, KmpInt32Ty, ".omp.sections.st.",
- Builder.getInt32(1));
- LValue IL = createSectionLVal(*this, KmpInt32Ty, ".omp.sections.il.",
- Builder.getInt32(0));
- // Loop counter.
- LValue IV = createSectionLVal(*this, KmpInt32Ty, ".omp.sections.iv.");
- OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
- OpaqueValueMapping OpaqueIV(*this, &IVRefExpr, IV);
- OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
- OpaqueValueMapping OpaqueUB(*this, &UBRefExpr, UB);
- // Generate condition for loop.
- BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
- OK_Ordinary, S.getLocStart(), /*fpContractable=*/false);
- // Increment for loop counter.
- UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
- S.getLocStart());
- auto BodyGen = [this, CS, &S, &IV]() {
- // Iterate through all sections and emit a switch construct:
- // switch (IV) {
- // case 0:
- // <SectionStmt[0]>;
- // break;
- // ...
- // case <NumSection> - 1:
- // <SectionStmt[<NumSection> - 1]>;
- // break;
- // }
- // .omp.sections.exit:
- auto *ExitBB = createBasicBlock(".omp.sections.exit");
- auto *SwitchStmt = Builder.CreateSwitch(
- EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB,
- CS->size());
- unsigned CaseNumber = 0;
- for (auto C = CS->children(); C; ++C, ++CaseNumber) {
- auto CaseBB = createBasicBlock(".omp.sections.case");
- EmitBlock(CaseBB);
- SwitchStmt->addCase(Builder.getInt32(CaseNumber), CaseBB);
- EmitStmt(*C);
- EmitBranch(ExitBB);
- }
- EmitBlock(ExitBB, /*IsFinished=*/true);
+ auto &&CodeGen = [&S, CS](CodeGenFunction &CGF) {
+ auto &C = CGF.CGM.getContext();
+ auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ // Emit helper vars inits.
+ LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
+ CGF.Builder.getInt32(0));
+ auto *GlobalUBVal = CGF.Builder.getInt32(CS->size() - 1);
+ LValue UB =
+ createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
+ LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
+ CGF.Builder.getInt32(1));
+ LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
+ CGF.Builder.getInt32(0));
+ // Loop counter.
+ LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
+ OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
+ CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
+ OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
+ CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
+ // Generate condition for loop.
+ BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
+ OK_Ordinary, S.getLocStart(),
+ /*fpContractable=*/false);
+ // Increment for loop counter.
+ UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue,
+ OK_Ordinary, S.getLocStart());
+ auto BodyGen = [CS, &S, &IV](CodeGenFunction &CGF) {
+ // Iterate through all sections and emit a switch construct:
+ // switch (IV) {
+ // case 0:
+ // <SectionStmt[0]>;
+ // break;
+ // ...
+ // case <NumSection> - 1:
+ // <SectionStmt[<NumSection> - 1]>;
+ // break;
+ // }
+ // .omp.sections.exit:
+ auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
+ auto *SwitchStmt = CGF.Builder.CreateSwitch(
+ CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB,
+ CS->size());
+ unsigned CaseNumber = 0;
+ for (auto C = CS->children(); C; ++C, ++CaseNumber) {
+ auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
+ CGF.EmitBlock(CaseBB);
+ SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
+ CGF.EmitStmt(*C);
+ CGF.EmitBranch(ExitBB);
+ }
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
+ };
+ // Emit static non-chunked loop.
+ CGF.CGM.getOpenMPRuntime().emitForInit(
+ CGF, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32,
+ /*IVSigned=*/true, IL.getAddress(), LB.getAddress(), UB.getAddress(),
+ ST.getAddress());
+ // UB = min(UB, GlobalUB);
+ auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
+ auto *MinUBGlobalUB = CGF.Builder.CreateSelect(
+ CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
+ CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
+ // IV = LB;
+ CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV);
+ // while (idx <= UB) { BODY; ++idx; }
+ CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen);
+ // Tell the runtime we are done.
+ CGF.CGM.getOpenMPRuntime().emitForFinish(CGF, S.getLocStart(),
+ OMPC_SCHEDULE_static);
};
- // Emit static non-chunked loop.
- CGM.getOpenMPRuntime().emitForInit(
- *this, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32,
- /*IVSigned=*/true, IL.getAddress(), LB.getAddress(), UB.getAddress(),
- ST.getAddress());
- // UB = min(UB, GlobalUB);
- auto *UBVal = EmitLoadOfScalar(UB, S.getLocStart());
- auto *MinUBGlobalUB = Builder.CreateSelect(
- Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
- EmitStoreOfScalar(MinUBGlobalUB, UB);
- // IV = LB;
- EmitStoreOfScalar(EmitLoadOfScalar(LB, S.getLocStart()), IV);
- // while (idx <= UB) { BODY; ++idx; }
- EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen);
- // Tell the runtime we are done.
- CGM.getOpenMPRuntime().emitForFinish(*this, S.getLocStart(),
- OMPC_SCHEDULE_static);
- } else {
- // If only one section is found - no need to generate loop, emit as a single
- // region.
- CGM.getOpenMPRuntime().emitSingleRegion(*this, [&]() -> void {
- InlinedOpenMPRegionScopeRAII Region(*this, S);
- EmitStmt(Stmt);
- EnsureInsertPoint();
- }, S.getLocStart(), llvm::None, llvm::None, llvm::None, llvm::None);
- }
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, CodeGen);
+ return OMPD_sections;
+ }
+ // If only one section is found - no need to generate loop, emit as a single
+ // region.
+ auto &&CodeGen = [Stmt](CodeGenFunction &CGF) {
+ CGF.EmitStmt(Stmt);
+ CGF.EnsureInsertPoint();
+ };
+ CGF.CGM.getOpenMPRuntime().emitSingleRegion(CGF, CodeGen, S.getLocStart(),
+ llvm::None, llvm::None,
+ llvm::None, llvm::None);
+ return OMPD_single;
+}
+
+void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ OpenMPDirectiveKind EmittedAs = emitSections(*this, S);
// Emit an implicit barrier at the end.
- if (!S.getSingleClause(OMPC_nowait))
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
- /*IsExplicit=*/false);
+ if (!S.getSingleClause(OMPC_nowait)) {
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), EmittedAs);
+ }
}
void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
- InlinedOpenMPRegionScopeRAII Region(*this, S);
- EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- EnsureInsertPoint();
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
}
void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
llvm::SmallVector<const Expr *, 8> CopyprivateVars;
+ llvm::SmallVector<const Expr *, 8> DestExprs;
llvm::SmallVector<const Expr *, 8> SrcExprs;
- llvm::SmallVector<const Expr *, 8> DstExprs;
llvm::SmallVector<const Expr *, 8> AssignmentOps;
- // Check if there are any 'copyprivate' clauses associated with this 'single'
+ // Check if there are any 'copyprivate' clauses associated with this
+ // 'single'
// construct.
auto CopyprivateFilter = [](const OMPClause *C) -> bool {
return C->getClauseKind() == OMPC_copyprivate;
@@ -914,44 +1234,60 @@
for (CopyprivateIter I(S.clauses(), CopyprivateFilter); I; ++I) {
auto *C = cast<OMPCopyprivateClause>(*I);
CopyprivateVars.append(C->varlists().begin(), C->varlists().end());
+ DestExprs.append(C->destination_exprs().begin(),
+ C->destination_exprs().end());
SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
- DstExprs.append(C->destination_exprs().begin(),
- C->destination_exprs().end());
AssignmentOps.append(C->assignment_ops().begin(),
C->assignment_ops().end());
}
+ LexicalScope Scope(*this, S.getSourceRange());
// Emit code for 'single' region along with 'copyprivate' clauses
- CGM.getOpenMPRuntime().emitSingleRegion(*this, [&]() -> void {
- InlinedOpenMPRegionScopeRAII Region(*this, S);
- EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- EnsureInsertPoint();
- }, S.getLocStart(), CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
+ CopyprivateVars, DestExprs, SrcExprs,
+ AssignmentOps);
// Emit an implicit barrier at the end.
- if (!S.getSingleClause(OMPC_nowait))
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
- /*IsExplicit=*/false);
+ if (!S.getSingleClause(OMPC_nowait)) {
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_single);
+ }
}
void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
- CGM.getOpenMPRuntime().emitMasterRegion(*this, [&]() -> void {
- InlinedOpenMPRegionScopeRAII Region(*this, S);
- EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- EnsureInsertPoint();
- }, S.getLocStart());
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getLocStart());
}
void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
CGM.getOpenMPRuntime().emitCriticalRegion(
- *this, S.getDirectiveName().getAsString(), [&]() -> void {
- InlinedOpenMPRegionScopeRAII Region(*this, S);
- EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- EnsureInsertPoint();
- }, S.getLocStart());
+ *this, S.getDirectiveName().getAsString(), CodeGen, S.getLocStart());
}
-void
-CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
- llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
+void CodeGenFunction::EmitOMPParallelForDirective(
+ const OMPParallelForDirective &S) {
+ // Emit directive as a combined directive that consists of two implicit
+ // directives: 'parallel' with 'for' directive.
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPWorksharingLoop(S);
+ // Emit implicit barrier at the end of parallel region, but this barrier
+ // is at the end of 'for' directive, so emit it as the implicit barrier for
+ // this 'for' directive.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_parallel);
+ };
+ emitCommonOMPParallelDirective(*this, S, CodeGen);
}
void CodeGenFunction::EmitOMPParallelForSimdDirective(
@@ -960,19 +1296,36 @@
}
void CodeGenFunction::EmitOMPParallelSectionsDirective(
- const OMPParallelSectionsDirective &) {
- llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
+ const OMPParallelSectionsDirective &S) {
+ // Emit directive as a combined directive that consists of two implicit
+ // directives: 'parallel' with 'sections' directive.
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ (void)emitSections(CGF, S);
+ // Emit implicit barrier at the end of parallel region.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_parallel);
+ };
+ emitCommonOMPParallelDirective(*this, S, CodeGen);
}
void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
// Emit outlined function for task construct.
+ LexicalScope Scope(*this, S.getSourceRange());
auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
auto *I = CS->getCapturedDecl()->param_begin();
+ auto *PartId = std::next(I);
// The first function argument for tasks is a thread id, the second one is a
// part id (0 for tied tasks, >=0 for untied task).
+ auto &&CodeGen = [PartId, &S](CodeGenFunction &CGF) {
+ if (*PartId) {
+ // TODO: emit code for untied tasks.
+ }
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ };
auto OutlinedFn =
- CGM.getOpenMPRuntime().emitTaskOutlinedFunction(S, *I, *std::next(I));
+ CGM.getOpenMPRuntime().emitTaskOutlinedFunction(S, *I, CodeGen);
// Check if we should emit tied or untied task.
bool Tied = !S.getSingleClause(OMPC_untied);
// Check if the task is final
@@ -1001,7 +1354,7 @@
}
void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart());
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_barrier);
}
void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
@@ -1116,9 +1469,156 @@
CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
}
+bool emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update,
+ BinaryOperatorKind BO, llvm::AtomicOrdering AO,
+ bool IsXLHSInRHSPart) {
+ auto &Context = CGF.CGM.getContext();
+ // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
+ // expression is simple and atomic is allowed for the given type for the
+ // target platform.
+ if (BO == BO_Comma || !Update.isScalar() ||
+ !Update.getScalarVal()->getType()->isIntegerTy() || !X.isSimple() ||
+ (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
+ (Update.getScalarVal()->getType() !=
+ X.getAddress()->getType()->getPointerElementType())) ||
+ !Context.getTargetInfo().hasBuiltinAtomic(
+ Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
+ return false;
+
+ llvm::AtomicRMWInst::BinOp RMWOp;
+ switch (BO) {
+ case BO_Add:
+ RMWOp = llvm::AtomicRMWInst::Add;
+ break;
+ case BO_Sub:
+ if (!IsXLHSInRHSPart)
+ return false;
+ RMWOp = llvm::AtomicRMWInst::Sub;
+ break;
+ case BO_And:
+ RMWOp = llvm::AtomicRMWInst::And;
+ break;
+ case BO_Or:
+ RMWOp = llvm::AtomicRMWInst::Or;
+ break;
+ case BO_Xor:
+ RMWOp = llvm::AtomicRMWInst::Xor;
+ break;
+ case BO_LT:
+ RMWOp = X.getType()->hasSignedIntegerRepresentation()
+ ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
+ : llvm::AtomicRMWInst::Max)
+ : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
+ : llvm::AtomicRMWInst::UMax);
+ break;
+ case BO_GT:
+ RMWOp = X.getType()->hasSignedIntegerRepresentation()
+ ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
+ : llvm::AtomicRMWInst::Min)
+ : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
+ : llvm::AtomicRMWInst::UMin);
+ break;
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LAnd:
+ case BO_LOr:
+ return false;
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_Assign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_Comma:
+ llvm_unreachable("Unsupported atomic update operation");
+ }
+ auto *UpdateVal = Update.getScalarVal();
+ if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
+ UpdateVal = CGF.Builder.CreateIntCast(
+ IC, X.getAddress()->getType()->getPointerElementType(),
+ X.getType()->hasSignedIntegerRepresentation());
+ }
+ CGF.Builder.CreateAtomicRMW(RMWOp, X.getAddress(), UpdateVal, AO);
+ return true;
+}
+
+void CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr(
+ LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
+ llvm::AtomicOrdering AO, SourceLocation Loc,
+ const llvm::function_ref<RValue(RValue)> &CommonGen) {
+ // Update expressions are allowed to have the following forms:
+ // x binop= expr; -> xrval + expr;
+ // x++, ++x -> xrval + 1;
+ // x--, --x -> xrval - 1;
+ // x = x binop expr; -> xrval binop expr
+ // x = expr Op x; - > expr binop xrval;
+ if (!emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart)) {
+ if (X.isGlobalReg()) {
+ // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop
+ // 'xrval'.
+ EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X);
+ } else {
+ // Perform compare-and-swap procedure.
+ EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified());
+ }
+ }
+}
+
+static void EmitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst,
+ const Expr *X, const Expr *E,
+ const Expr *UE, bool IsXLHSInRHSPart,
+ SourceLocation Loc) {
+ assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
+ "Update expr in 'atomic update' must be a binary operator.");
+ auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
+ // Update expressions are allowed to have the following forms:
+ // x binop= expr; -> xrval + expr;
+ // x++, ++x -> xrval + 1;
+ // x--, --x -> xrval - 1;
+ // x = x binop expr; -> xrval binop expr
+ // x = expr Op x; - > expr binop xrval;
+ assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
+ LValue XLValue = CGF.EmitLValue(X);
+ RValue ExprRValue = CGF.EmitAnyExpr(E);
+ auto AO = IsSeqCst ? llvm::SequentiallyConsistent : llvm::Monotonic;
+ auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
+ auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
+ auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
+ auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
+ auto Gen =
+ [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) -> RValue {
+ CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
+ CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
+ return CGF.EmitAnyExpr(UE);
+ };
+ CGF.EmitOMPAtomicSimpleUpdateExpr(XLValue, ExprRValue, BOUE->getOpcode(),
+ IsXLHSInRHSPart, AO, Loc, Gen);
+ // OpenMP, 2.12.6, atomic Construct
+ // Any atomic construct with a seq_cst clause forces the atomically
+ // performed operation to include an implicit flush operation without a
+ // list.
+ if (IsSeqCst)
+ CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
+}
+
static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
bool IsSeqCst, const Expr *X, const Expr *V,
- const Expr *E, SourceLocation Loc) {
+ const Expr *E, const Expr *UE,
+ bool IsXLHSInRHSPart, SourceLocation Loc) {
switch (Kind) {
case OMPC_read:
EmitOMPAtomicReadExpr(CGF, IsSeqCst, X, V, Loc);
@@ -1126,7 +1626,10 @@
case OMPC_write:
EmitOMPAtomicWriteExpr(CGF, IsSeqCst, X, E, Loc);
break;
+ case OMPC_unknown:
case OMPC_update:
+ EmitOMPAtomicUpdateExpr(CGF, IsSeqCst, X, E, UE, IsXLHSInRHSPart, Loc);
+ break;
case OMPC_capture:
llvm_unreachable("CodeGen for 'omp atomic clause' is not supported yet.");
case OMPC_if:
@@ -1153,7 +1656,6 @@
case OMPC_untied:
case OMPC_threadprivate:
case OMPC_mergeable:
- case OMPC_unknown:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}
@@ -1173,10 +1675,13 @@
S.getAssociatedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS))
enterFullExpression(EWC);
- InlinedOpenMPRegionScopeRAII Region(*this, S);
- EmitOMPAtomicExpr(*this, Kind, IsSeqCst, S.getX(), S.getV(), S.getExpr(),
- S.getLocStart());
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S, Kind, IsSeqCst](CodeGenFunction &CGF) {
+ EmitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.getX(), S.getV(), S.getExpr(),
+ S.getUpdateExpr(), S.isXLHSInRHSPart(), S.getLocStart());
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
}
void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index 81bd651..895afd7 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -18,7 +18,7 @@
using namespace clang;
using namespace CodeGen;
-static llvm::Constant *
+static llvm::GlobalVariable *
GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM,
const CXXRecordDecl *MostDerivedClass,
const VTTVTable &VTable,
@@ -47,8 +47,8 @@
llvm::Type *Int8PtrTy = CGM.Int8PtrTy, *Int64Ty = CGM.Int64Ty;
llvm::ArrayType *ArrayType =
llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
-
- SmallVector<llvm::Constant *, 8> VTables;
+
+ SmallVector<llvm::GlobalVariable *, 8> VTables;
SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints;
for (const VTTVTable *i = Builder.getVTTVTables().begin(),
*e = Builder.getVTTVTables().end(); i != e; ++i) {
@@ -61,7 +61,7 @@
for (const VTTComponent *i = Builder.getVTTComponents().begin(),
*e = Builder.getVTTComponents().end(); i != e; ++i) {
const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex];
- llvm::Constant *VTable = VTables[i->VTableIndex];
+ llvm::GlobalVariable *VTable = VTables[i->VTableIndex];
uint64_t AddressPoint;
if (VTTVT.getBase() == RD) {
// Just get the address point for the regular vtable.
@@ -79,8 +79,8 @@
llvm::ConstantInt::get(Int64Ty, AddressPoint)
};
- llvm::Constant *Init =
- llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs);
+ llvm::Constant *Init = llvm::ConstantExpr::getInBoundsGetElementPtr(
+ VTable->getValueType(), VTable, Idxs);
Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 372db7a..57370a6 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -842,7 +842,10 @@
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
const VTableLayout &VTLayout) {
- if (!LangOpts.Sanitize.has(SanitizerKind::CFIVptr))
+ if (!LangOpts.Sanitize.has(SanitizerKind::CFIVCall) &&
+ !LangOpts.Sanitize.has(SanitizerKind::CFINVCall) &&
+ !LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) &&
+ !LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast))
return;
llvm::Metadata *VTableMD = llvm::ConstantAsMetadata::get(VTable);
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 82cd949..9205591 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -19,6 +19,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/IR/Value.h"
+#include "llvm/IR/Type.h"
namespace llvm {
class Constant;
@@ -299,6 +300,7 @@
LValue R;
R.LVType = Simple;
+ assert(address->getType()->isPointerTy());
R.V = address;
R.Initialize(type, qs, alignment, TBAAInfo);
return R;
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index b5ed12a..60aac07 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -46,7 +46,7 @@
const CodeGenOptions &CodeGenOpts;
const TargetOptions &TargetOpts;
const LangOptions &LangOpts;
- raw_ostream *AsmOutStream;
+ raw_pwrite_stream *AsmOutStream;
ASTContext *Context;
Timer LLVMIRGeneration;
@@ -61,7 +61,7 @@
const TargetOptions &targetopts,
const LangOptions &langopts, bool TimePasses,
const std::string &infile, llvm::Module *LinkModule,
- raw_ostream *OS, LLVMContext &C,
+ raw_pwrite_stream *OS, LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr)
: Diags(_Diags), Action(action), CodeGenOpts(compopts),
TargetOpts(targetopts), LangOpts(langopts), AsmOutStream(OS),
@@ -601,9 +601,8 @@
return VMContext;
}
-static raw_ostream *GetOutputStream(CompilerInstance &CI,
- StringRef InFile,
- BackendAction Action) {
+static raw_pwrite_stream *
+GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
switch (Action) {
case Backend_EmitAssembly:
return CI.createDefaultOutputFile(false, InFile, "s");
@@ -625,7 +624,7 @@
std::unique_ptr<ASTConsumer>
CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
BackendAction BA = static_cast<BackendAction>(Act);
- std::unique_ptr<raw_ostream> OS(GetOutputStream(CI, InFile, BA));
+ std::unique_ptr<raw_pwrite_stream> OS(GetOutputStream(CI, InFile, BA));
if (BA != Backend_EmitNothing && !OS)
return nullptr;
@@ -678,7 +677,7 @@
if (getCurrentFileKind() == IK_LLVM_IR) {
BackendAction BA = static_cast<BackendAction>(Act);
CompilerInstance &CI = getCompilerInstance();
- raw_ostream *OS = GetOutputStream(CI, getCurrentFile(), BA);
+ raw_pwrite_stream *OS = GetOutputStream(CI, getCurrentFile(), BA);
if (BA != Backend_EmitNothing && !OS)
return;
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 9e80f0a..42c3a42 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -40,7 +40,7 @@
CurFn(nullptr), CapturedStmtInfo(nullptr),
SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false),
CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false),
- BlockInfo(nullptr), BlockPointer(nullptr),
+ IsOutlinedSEHHelper(false), BlockInfo(nullptr), BlockPointer(nullptr),
LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
ExceptionSlot(nullptr), EHSelectorSlot(nullptr),
@@ -70,6 +70,9 @@
if (CGM.getCodeGenOpts().NoSignedZeros) {
FMF.setNoSignedZeros();
}
+ if (CGM.getCodeGenOpts().ReciprocalMath) {
+ FMF.setAllowReciprocal();
+ }
Builder.SetFastMathFlags(FMF);
}
@@ -279,6 +282,20 @@
Builder.ClearInsertionPoint();
}
+ // If some of our locals escaped, insert a call to llvm.frameescape in the
+ // entry block.
+ if (!EscapedLocals.empty()) {
+ // Invert the map from local to index into a simple vector. There should be
+ // no holes.
+ SmallVector<llvm::Value *, 4> EscapeArgs;
+ EscapeArgs.resize(EscapedLocals.size());
+ for (auto &Pair : EscapedLocals)
+ EscapeArgs[Pair.second] = Pair.first;
+ llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration(
+ &CGM.getModule(), llvm::Intrinsic::frameescape);
+ CGBuilderTy(AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
+ }
+
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
llvm::Instruction *Ptr = AllocaInsertPt;
AllocaInsertPt = nullptr;
@@ -680,7 +697,7 @@
unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex();
llvm::Function::arg_iterator EI = CurFn->arg_end();
--EI;
- llvm::Value *Addr = Builder.CreateStructGEP(EI, Idx);
+ llvm::Value *Addr = Builder.CreateStructGEP(nullptr, EI, Idx);
ReturnValue = Builder.CreateLoad(Addr, "agg.result");
} else {
ReturnValue = CreateIRTemp(RetTy, "retval");
@@ -1229,7 +1246,8 @@
/*volatile*/ false);
// Go to the next element.
- llvm::Value *next = Builder.CreateConstInBoundsGEP1_32(cur, 1, "vla.next");
+ llvm::Value *next = Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(),
+ cur, 1, "vla.next");
// Leave if that's the end of the VLA.
llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone");
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 151eb7e..4e7a7e2 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -192,7 +192,7 @@
CapturedRegionKind getKind() const { return Kind; }
- void setContextValue(llvm::Value *V) { ThisValue = V; }
+ virtual void setContextValue(llvm::Value *V) { ThisValue = V; }
// \brief Retrieve the value of the context parameter.
virtual llvm::Value *getContextValue() const { return ThisValue; }
@@ -263,6 +263,10 @@
/// potentially set the return value.
bool SawAsmBlock;
+ /// True if the current function is an outlined SEH helper. This can be a
+ /// finally block or filter expression.
+ bool IsOutlinedSEHHelper;
+
const CodeGen::CGBlockInfo *BlockInfo;
llvm::Value *BlockPointer;
@@ -351,17 +355,6 @@
void exit(CodeGenFunction &CGF);
};
- /// Cleanups can be emitted for two reasons: normal control leaving a region
- /// exceptional control flow leaving a region.
- struct SEHFinallyInfo {
- SEHFinallyInfo()
- : FinallyBB(nullptr), ContBB(nullptr), ResumeBB(nullptr) {}
-
- llvm::BasicBlock *FinallyBB;
- llvm::BasicBlock *ContBB;
- llvm::BasicBlock *ResumeBB;
- };
-
/// Returns true inside SEH __try blocks.
bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); }
@@ -851,7 +844,8 @@
/// getByrefValueFieldNumber - Given a declaration, returns the LLVM field
/// number that holds the value.
- unsigned getByRefValueLLVMField(const ValueDecl *VD) const;
+ std::pair<llvm::Type *, unsigned>
+ getByRefValueLLVMField(const ValueDecl *VD) const;
/// BuildBlockByrefAddress - Computes address location of the
/// variable which is declared as __block.
@@ -876,6 +870,10 @@
typedef llvm::DenseMap<const Decl*, llvm::Value*> DeclMapTy;
DeclMapTy LocalDeclMap;
+ /// Track escaped local variables with auto storage. Used during SEH
+ /// outlining to produce a call to llvm.frameescape.
+ llvm::DenseMap<llvm::AllocaInst *, int> EscapedLocals;
+
/// LabelMap - This keeps track of the LLVM basic block for each C label.
llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap;
@@ -1047,10 +1045,6 @@
llvm::Value *getExceptionSlot();
llvm::Value *getEHSelectorSlot();
- /// Stack slot that contains whether a __finally block is being executed as an
- /// EH cleanup or as a normal cleanup.
- llvm::Value *getAbnormalTerminationSlot();
-
/// Returns the contents of the function's exception object and selector
/// slots.
llvm::Value *getExceptionFromSlot();
@@ -1729,7 +1723,8 @@
llvm::Value *This);
void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType,
- llvm::Value *NewPtr, llvm::Value *NumElements,
+ llvm::Type *ElementTy, llvm::Value *NewPtr,
+ llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie);
void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
@@ -1895,8 +1890,8 @@
llvm::Value *getObjectAddress(CodeGenFunction &CGF) const {
if (!IsByRef) return Address;
- return CGF.Builder.CreateStructGEP(Address,
- CGF.getByRefValueLLVMField(Variable),
+ auto F = CGF.getByRefValueLLVMField(Variable);
+ return CGF.Builder.CreateStructGEP(F.first, Address, F.second,
Variable->getNameAsString());
}
};
@@ -1994,17 +1989,30 @@
void EmitCXXTryStmt(const CXXTryStmt &S);
void EmitSEHTryStmt(const SEHTryStmt &S);
void EmitSEHLeaveStmt(const SEHLeaveStmt &S);
- void EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI);
- void ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI);
+ void EnterSEHTryStmt(const SEHTryStmt &S);
+ void ExitSEHTryStmt(const SEHTryStmt &S);
+
+ void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name,
+ QualType RetTy, FunctionArgList &Args,
+ const Stmt *OutlinedStmt);
llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
const SEHExceptStmt &Except);
+ llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
+ const SEHFinallyStmt &Finally);
+
void EmitSEHExceptionCodeSave();
llvm::Value *EmitSEHExceptionCode();
llvm::Value *EmitSEHExceptionInfo();
llvm::Value *EmitSEHAbnormalTermination();
+ /// Scan the outlined statement for captures from the parent function. For
+ /// each capture, mark the capture as escaped and emit a call to
+ /// llvm.framerecover. Insert the framerecover result into the LocalDeclMap.
+ void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt,
+ llvm::Value *ParentFP);
+
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = None);
@@ -2014,13 +2022,100 @@
llvm::Function *GenerateCapturedStmtFunctionEpilog(const CapturedStmt &S);
llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S);
llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S);
- void EmitOMPAggregateAssign(LValue OriginalAddr, llvm::Value *PrivateAddr,
- const Expr *AssignExpr, QualType Type,
- const VarDecl *VDInit);
- void EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
+ /// \brief Perform element by element copying of arrays with type \a
+ /// OriginalType from \a SrcAddr to \a DestAddr using copying procedure
+ /// generated by \a CopyGen.
+ ///
+ /// \param DestAddr Address of the destination array.
+ /// \param SrcAddr Address of the source array.
+ /// \param OriginalType Type of destination and source arrays.
+ /// \param CopyGen Copying procedure that copies value of single array element
+ /// to another single array element.
+ void EmitOMPAggregateAssign(
+ llvm::Value *DestAddr, llvm::Value *SrcAddr, QualType OriginalType,
+ const llvm::function_ref<void(llvm::Value *, llvm::Value *)> &CopyGen);
+ /// \brief Emit proper copying of data from one variable to another.
+ ///
+ /// \param OriginalType Original type of the copied variables.
+ /// \param DestAddr Destination address.
+ /// \param SrcAddr Source address.
+ /// \param DestVD Destination variable used in \a CopyExpr (for arrays, has
+ /// type of the base array element).
+ /// \param SrcVD Source variable used in \a CopyExpr (for arrays, has type of
+ /// the base array element).
+ /// \param Copy Actual copygin expression for copying data from \a SrcVD to \a
+ /// DestVD.
+ void EmitOMPCopy(CodeGenFunction &CGF, QualType OriginalType,
+ llvm::Value *DestAddr, llvm::Value *SrcAddr,
+ const VarDecl *DestVD, const VarDecl *SrcVD,
+ const Expr *Copy);
+ /// \brief Emit atomic update code for constructs: \a X = \a X \a BO \a E or
+ /// \a X = \a E \a BO \a E.
+ ///
+ /// \param X Value to be updated.
+ /// \param E Update value.
+ /// \param BO Binary operation for update operation.
+ /// \param IsXLHSInRHSPart true if \a X is LHS in RHS part of the update
+ /// expression, false otherwise.
+ /// \param AO Atomic ordering of the generated atomic instructions.
+ /// \param CommonGen Code generator for complex expressions that cannot be
+ /// expressed through atomicrmw instruction.
+ void EmitOMPAtomicSimpleUpdateExpr(
+ LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
+ llvm::AtomicOrdering AO, SourceLocation Loc,
+ const llvm::function_ref<RValue(RValue)> &CommonGen);
+ bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope);
void EmitOMPPrivateClause(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope);
+ /// \brief Emit code for copyin clause in \a D directive. The next code is
+ /// generated at the start of outlined functions for directives:
+ /// \code
+ /// threadprivate_var1 = master_threadprivate_var1;
+ /// operator=(threadprivate_var2, master_threadprivate_var2);
+ /// ...
+ /// __kmpc_barrier(&loc, global_tid);
+ /// \endcode
+ ///
+ /// \param D OpenMP directive possibly with 'copyin' clause(s).
+ /// \returns true if at least one copyin variable is found, false otherwise.
+ bool EmitOMPCopyinClause(const OMPExecutableDirective &D);
+ /// \brief Emit initial code for lastprivate variables. If some variable is
+ /// not also firstprivate, then the default initialization is used. Otherwise
+ /// initialization of this variable is performed by EmitOMPFirstprivateClause
+ /// method.
+ ///
+ /// \param D Directive that may have 'lastprivate' directives.
+ /// \param PrivateScope Private scope for capturing lastprivate variables for
+ /// proper codegen in internal captured statement.
+ ///
+ /// \returns true if there is at least one lastprivate variable, false
+ /// otherwise.
+ bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D,
+ OMPPrivateScope &PrivateScope);
+ /// \brief Emit final copying of lastprivate values to original variables at
+ /// the end of the worksharing or simd directive.
+ ///
+ /// \param D Directive that has at least one 'lastprivate' directives.
+ /// \param IsLastIterCond Boolean condition that must be set to 'i1 true' if
+ /// it is the last iteration of the loop code in associated directive, or to
+ /// 'i1 false' otherwise.
+ void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D,
+ llvm::Value *IsLastIterCond);
+ /// \brief Emit initial code for reduction variables. Creates reduction copies
+ /// and initializes them with the values according to OpenMP standard.
+ ///
+ /// \param D Directive (possibly) with the 'reduction' clause.
+ /// \param PrivateScope Private scope for capturing reduction variables for
+ /// proper codegen in internal captured statement.
+ ///
+ void EmitOMPReductionClauseInit(const OMPExecutableDirective &D,
+ OMPPrivateScope &PrivateScope);
+ /// \brief Emit final update of reduction values to original variables at
+ /// the end of the directive.
+ ///
+ /// \param D Directive that has at least one 'reduction' directives.
+ void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D);
void EmitOMPParallelDirective(const OMPParallelDirective &S);
void EmitOMPSimdDirective(const OMPSimdDirective &S);
@@ -2044,16 +2139,21 @@
void EmitOMPTargetDirective(const OMPTargetDirective &S);
void EmitOMPTeamsDirective(const OMPTeamsDirective &S);
+ void
+ EmitOMPInnerLoop(const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
+ const Expr *IncExpr,
+ const llvm::function_ref<void(CodeGenFunction &)> &BodyGen);
+
private:
/// Helpers for the OpenMP loop directives.
void EmitOMPLoopBody(const OMPLoopDirective &Directive,
bool SeparateIter = false);
- void EmitOMPInnerLoop(const Stmt &S, bool RequiresCleanup,
- const Expr *LoopCond, const Expr *IncExpr,
- const std::function<void()> &BodyGen);
void EmitOMPSimdFinal(const OMPLoopDirective &S);
- void EmitOMPWorksharingLoop(const OMPLoopDirective &S);
+ /// \brief Emit code for the worksharing loop-based directive.
+ /// \return true, if this construct has any lastprivate clause, false -
+ /// otherwise.
+ bool EmitOMPWorksharingLoop(const OMPLoopDirective &S);
void EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
const OMPLoopDirective &S,
OMPPrivateScope &LoopScope, llvm::Value *LB,
@@ -2123,12 +2223,16 @@
void EmitAtomicStore(RValue rvalue, LValue lvalue, llvm::AtomicOrdering AO,
bool IsVolatile, bool isInit);
- std::pair<RValue, RValue> EmitAtomicCompareExchange(
+ std::pair<RValue, llvm::Value *> EmitAtomicCompareExchange(
LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc,
llvm::AtomicOrdering Success = llvm::SequentiallyConsistent,
llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent,
bool IsWeak = false, AggValueSlot Slot = AggValueSlot::ignored());
+ void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO,
+ const std::function<RValue(RValue)> &UpdateOp,
+ bool IsVolatile);
+
/// EmitToMemory - Change a scalar value from its value
/// representation to its in-memory representation.
llvm::Value *EmitToMemory(llvm::Value *Value, QualType Ty);
@@ -2430,6 +2534,7 @@
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitR600BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index f4ae684..17b7ddc 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -147,8 +147,8 @@
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"Could not read profile: %0");
getDiags().Report(DiagID) << EC.message();
- }
- PGOReader = std::move(ReaderOrErr.get());
+ } else
+ PGOReader = std::move(ReaderOrErr.get());
}
// If coverage mapping generation is enabled, create the
@@ -2134,7 +2134,8 @@
}
static bool isVarDeclStrongDefinition(const ASTContext &Context,
- const VarDecl *D, bool NoCommon) {
+ CodeGenModule &CGM, const VarDecl *D,
+ bool NoCommon) {
// Don't give variables common linkage if -fno-common was specified unless it
// was overridden by a NoCommon attribute.
if ((NoCommon || D->hasAttr<NoCommonAttr>()) && !D->hasAttr<CommonAttr>())
@@ -2159,6 +2160,10 @@
if (D->hasAttr<WeakImportAttr>())
return true;
+ // A variable cannot be both common and exist in a comdat.
+ if (shouldBeInCOMDAT(CGM, *D))
+ return true;
+
// Declarations with a required alignment do not have common linakge in MSVC
// mode.
if (Context.getLangOpts().MSVCCompat) {
@@ -2227,7 +2232,7 @@
// C++ doesn't have tentative definitions and thus cannot have common
// linkage.
if (!getLangOpts().CPlusPlus && isa<VarDecl>(D) &&
- !isVarDeclStrongDefinition(Context, cast<VarDecl>(D),
+ !isVarDeclStrongDefinition(Context, *this, cast<VarDecl>(D),
CodeGenOpts.NoCommon))
return llvm::GlobalVariable::CommonLinkage;
@@ -2350,7 +2355,7 @@
callSite->replaceAllUsesWith(newCall.getInstruction());
// Copy debug location attached to CI.
- if (!callSite->getDebugLoc().isUnknown())
+ if (callSite->getDebugLoc())
newCall->setDebugLoc(callSite->getDebugLoc());
callSite->eraseFromParent();
}
@@ -2564,12 +2569,10 @@
Tys);
}
-static llvm::StringMapEntry<llvm::Constant*> &
-GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map,
- const StringLiteral *Literal,
- bool TargetIsLSB,
- bool &IsUTF16,
- unsigned &StringLength) {
+static llvm::StringMapEntry<llvm::GlobalVariable *> &
+GetConstantCFStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
+ const StringLiteral *Literal, bool TargetIsLSB,
+ bool &IsUTF16, unsigned &StringLength) {
StringRef String = Literal->getString();
unsigned NumBytes = String.size();
@@ -2601,10 +2604,9 @@
nullptr)).first;
}
-static llvm::StringMapEntry<llvm::Constant*> &
-GetConstantStringEntry(llvm::StringMap<llvm::Constant*> &Map,
- const StringLiteral *Literal,
- unsigned &StringLength) {
+static llvm::StringMapEntry<llvm::GlobalVariable *> &
+GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
+ const StringLiteral *Literal, unsigned &StringLength) {
StringRef String = Literal->getString();
StringLength = String.size();
return *Map.insert(std::make_pair(String, nullptr)).first;
@@ -2614,10 +2616,10 @@
CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
unsigned StringLength = 0;
bool isUTF16 = false;
- llvm::StringMapEntry<llvm::Constant*> &Entry =
- GetConstantCFStringEntry(CFConstantStringMap, Literal,
- getDataLayout().isLittleEndian(),
- isUTF16, StringLength);
+ llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
+ GetConstantCFStringEntry(CFConstantStringMap, Literal,
+ getDataLayout().isLittleEndian(), isUTF16,
+ StringLength);
if (auto *C = Entry.second)
return C;
@@ -2633,7 +2635,7 @@
llvm::Constant *GV = CreateRuntimeVariable(Ty,
"__CFConstantStringClassReference");
// Decay array -> ptr
- V = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
+ V = llvm::ConstantExpr::getGetElementPtr(Ty, GV, Zeros);
CFConstantStringClassRef = V;
}
else
@@ -2686,7 +2688,7 @@
}
// String.
- Fields[2] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
+ Fields[2] = llvm::ConstantExpr::getGetElementPtr(GV->getType(), GV, Zeros);
if (isUTF16)
// Cast the UTF16 string to the correct type.
@@ -2707,11 +2709,11 @@
return GV;
}
-llvm::Constant *
+llvm::GlobalVariable *
CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
unsigned StringLength = 0;
- llvm::StringMapEntry<llvm::Constant*> &Entry =
- GetConstantStringEntry(CFConstantStringMap, Literal, StringLength);
+ llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
+ GetConstantStringEntry(CFConstantStringMap, Literal, StringLength);
if (auto *C = Entry.second)
return C;
@@ -2740,11 +2742,10 @@
llvm::Type *PTy = llvm::ArrayType::get(Ty, 0);
GV = CreateRuntimeVariable(PTy, str);
// Decay array -> ptr
- V = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
+ V = llvm::ConstantExpr::getGetElementPtr(PTy, GV, Zeros);
ConstantStringClassRef = V;
}
- }
- else
+ } else
V = ConstantStringClassRef;
if (!NSConstantStringType) {
@@ -2800,8 +2801,9 @@
// of the string is via this class initializer.
CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy);
GV->setAlignment(Align.getQuantity());
- Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
-
+ Fields[1] =
+ llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
+
// String length.
llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
Fields[2] = llvm::ConstantInt::get(Ty, StringLength);
@@ -3433,7 +3435,7 @@
void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
std::vector<const Decl *> DeferredDecls;
- for (const auto I : DeferredEmptyCoverageMappingDecls) {
+ for (const auto &I : DeferredEmptyCoverageMappingDecls) {
if (!I.second)
continue;
DeferredDecls.push_back(I.first);
@@ -3638,9 +3640,9 @@
}
llvm::Constant *
-CodeGenModule::getAddrOfCXXHandlerMapEntry(QualType Ty,
- QualType CatchHandlerType) {
- return getCXXABI().getAddrOfCXXHandlerMapEntry(Ty, CatchHandlerType);
+CodeGenModule::getAddrOfCXXCatchHandlerType(QualType Ty,
+ QualType CatchHandlerType) {
+ return getCXXABI().getAddrOfCXXCatchHandlerType(Ty, CatchHandlerType);
}
llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index ce540e9..feef6c2 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -366,7 +366,7 @@
/// Map used to get unique annotation strings.
llvm::StringMap<llvm::Constant*> AnnotationStrings;
- llvm::StringMap<llvm::Constant*> CFConstantStringMap;
+ llvm::StringMap<llvm::GlobalVariable *> CFConstantStringMap;
llvm::DenseMap<llvm::Constant *, llvm::GlobalVariable *> ConstantStringMap;
llvm::DenseMap<const Decl*, llvm::Constant *> StaticLocalDeclMap;
@@ -400,7 +400,8 @@
/// When a C++ decl with an initializer is deferred, null is
/// appended to CXXGlobalInits, and the index of that null is placed
/// here so that the initializer will be performed in the correct
- /// order.
+ /// order. Once the decl is emitted, the index is replaced with ~0U to ensure
+ /// that we don't re-emit the initializer.
llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
typedef std::pair<OrderGlobalInits, llvm::Function*> GlobalInitData;
@@ -719,8 +720,8 @@
/// Get the address of the RTTI descriptor for the given type.
llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
- llvm::Constant *getAddrOfCXXHandlerMapEntry(QualType Ty,
- QualType CatchHandlerType);
+ llvm::Constant *getAddrOfCXXCatchHandlerType(QualType Ty,
+ QualType CatchHandlerType);
/// Get the address of a uuid descriptor .
llvm::Constant *GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);
@@ -786,7 +787,7 @@
/// Return a pointer to a constant NSString object for the given string. Or a
/// user defined String object as defined via
/// -fconstant-string-class=class_name option.
- llvm::Constant *GetAddrOfConstantString(const StringLiteral *Literal);
+ llvm::GlobalVariable *GetAddrOfConstantString(const StringLiteral *Literal);
/// Return a constant array for the given string.
llvm::Constant *GetConstantArrayFromStringLiteral(const StringLiteral *E);
diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp
index 557828d..cc6ac20 100644
--- a/lib/CodeGen/CodeGenPGO.cpp
+++ b/lib/CodeGen/CodeGenPGO.cpp
@@ -880,12 +880,10 @@
if (!haveRegionCounts())
return nullptr;
uint64_t LoopCount = Cnt.getCount();
- uint64_t CondCount = 0;
- bool Found = getStmtCount(Cond, CondCount);
- assert(Found && "missing expected loop condition count");
- (void)Found;
- if (CondCount == 0)
+ Optional<uint64_t> CondCount = getStmtCount(Cond);
+ assert(CondCount.hasValue() && "missing expected loop condition count");
+ if (*CondCount == 0)
return nullptr;
return createBranchWeights(LoopCount,
- std::max(CondCount, LoopCount) - LoopCount);
+ std::max(*CondCount, LoopCount) - LoopCount);
}
diff --git a/lib/CodeGen/CodeGenPGO.h b/lib/CodeGen/CodeGenPGO.h
index 431c850..c92a057 100644
--- a/lib/CodeGen/CodeGenPGO.h
+++ b/lib/CodeGen/CodeGenPGO.h
@@ -69,23 +69,20 @@
/// Check if an execution count is known for a given statement. If so, return
/// true and put the value in Count; else return false.
- bool getStmtCount(const Stmt *S, uint64_t &Count) {
+ Optional<uint64_t> getStmtCount(const Stmt *S) {
if (!StmtCountMap)
- return false;
- llvm::DenseMap<const Stmt*, uint64_t>::const_iterator
- I = StmtCountMap->find(S);
+ return None;
+ auto I = StmtCountMap->find(S);
if (I == StmtCountMap->end())
- return false;
- Count = I->second;
- return true;
+ return None;
+ return I->second;
}
/// If the execution count for the current statement is known, record that
/// as the current count.
void setCurrentStmt(const Stmt *S) {
- uint64_t Count;
- if (getStmtCount(S, Count))
- setCurrentRegionCount(Count);
+ if (auto Count = getStmtCount(S))
+ setCurrentRegionCount(*Count);
}
/// Calculate branch weights appropriate for PGO data
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 07db6c7..d26eced 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -748,7 +748,7 @@
size_t Index =
pushRegion(Counter::getZero(), getStart(CS->body_front()),
getEnd(CS->body_back()));
- for (const auto &Child : CS->children())
+ for (const auto *Child : CS->children())
Visit(Child);
popRegions(Index);
}
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index f23cd9f..eb7ab1d 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -127,7 +127,8 @@
void EmitFundamentalRTTIDescriptors();
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
llvm::Constant *
- getAddrOfCXXHandlerMapEntry(QualType Ty, QualType CatchHandlerType) override {
+ getAddrOfCXXCatchHandlerType(QualType Ty,
+ QualType CatchHandlerType) override {
return getAddrOfRTTIDescriptor(Ty);
}
@@ -1387,7 +1388,7 @@
llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
BaseSubobject Base, const CXXRecordDecl *VTableClass) {
- llvm::Constant *VTable = getAddrOfVTable(VTableClass, CharUnits());
+ auto *VTable = getAddrOfVTable(VTableClass, CharUnits());
// Find the appropriate vtable within the vtable group.
uint64_t AddressPoint = CGM.getItaniumVTableContext()
@@ -1398,7 +1399,8 @@
llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint)
};
- return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices);
+ return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable->getValueType(),
+ VTable, Indices);
}
llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
@@ -1442,7 +1444,8 @@
Ty = Ty->getPointerTo()->getPointerTo();
llvm::Value *VTable = CGF.GetVTablePtr(This, Ty);
- CGF.EmitVTablePtrCheckForCall(cast<CXXMethodDecl>(GD.getDecl()), VTable);
+ if (CGF.SanOpts.has(SanitizerKind::CFIVCall))
+ CGF.EmitVTablePtrCheckForCall(cast<CXXMethodDecl>(GD.getDecl()), VTable);
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
llvm::Value *VFuncPtr =
@@ -1666,7 +1669,7 @@
CGF.Builder.CreateStore(elementSize, cookie);
// The second element is the element count.
- cookie = CGF.Builder.CreateConstInBoundsGEP1_32(cookie, 1);
+ cookie = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.SizeTy, cookie, 1);
CGF.Builder.CreateStore(numElements, cookie);
// Finally, compute a pointer to the actual data buffer by skipping
@@ -2604,7 +2607,8 @@
// The vtable address point is 2.
llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
- VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two);
+ VTable =
+ llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable, Two);
VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
Fields.push_back(VTable);
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index f8f7845..f00cd9c 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -45,7 +45,7 @@
: CGCXXABI(CGM), BaseClassDescriptorType(nullptr),
ClassHierarchyDescriptorType(nullptr),
CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr),
- ThrowInfoType(nullptr), HandlerMapEntryType(nullptr) {}
+ ThrowInfoType(nullptr), CatchHandlerTypeType(nullptr) {}
bool HasThisReturn(GlobalDecl GD) const override;
bool hasMostDerivedReturn(GlobalDecl GD) const override;
@@ -85,7 +85,7 @@
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
llvm::Constant *
- getAddrOfCXXHandlerMapEntry(QualType Ty, QualType CatchHandlerType) override;
+ getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) override;
bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
void EmitBadTypeidCall(CodeGenFunction &CGF) override;
@@ -573,16 +573,16 @@
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
- llvm::StructType *getHandlerMapEntryType() {
- if (!HandlerMapEntryType) {
+ llvm::StructType *getCatchHandlerTypeType() {
+ if (!CatchHandlerTypeType) {
llvm::Type *FieldTypes[] = {
- CGM.IntTy, // Flags
- getImageRelativeType(CGM.Int8PtrTy), // TypeDescriptor
+ CGM.IntTy, // Flags
+ CGM.Int8PtrTy, // TypeDescriptor
};
- HandlerMapEntryType = llvm::StructType::create(
- CGM.getLLVMContext(), FieldTypes, "eh.HandlerMapEntry");
+ CatchHandlerTypeType = llvm::StructType::create(
+ CGM.getLLVMContext(), FieldTypes, "eh.CatchHandlerType");
}
- return HandlerMapEntryType;
+ return CatchHandlerTypeType;
}
llvm::StructType *getCatchableTypeType() {
@@ -698,7 +698,7 @@
llvm::StructType *CatchableTypeType;
llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
llvm::StructType *ThrowInfoType;
- llvm::StructType *HandlerMapEntryType;
+ llvm::StructType *CatchHandlerTypeType;
};
}
@@ -809,7 +809,9 @@
llvm::Function *BeginCatch =
CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_begincatch);
- if (!CatchParam) {
+ // If this is a catch-all or the catch parameter is unnamed, we don't need to
+ // emit an alloca to the object.
+ if (!CatchParam || !CatchParam->getDeclName()) {
llvm::Value *Args[2] = {Exn, llvm::Constant::getNullValue(CGF.Int8PtrTy)};
CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalAndEHCleanup);
@@ -1121,7 +1123,8 @@
Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr());
llvm::Value *VBPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(ThisInt8Ptr, Offs.getQuantity());
- llvm::Value *GVPtr = CGF.Builder.CreateConstInBoundsGEP2_32(GV, 0, 0);
+ llvm::Value *GVPtr =
+ CGF.Builder.CreateConstInBoundsGEP2_32(GV->getValueType(), GV, 0, 0);
VBPtr = CGF.Builder.CreateBitCast(VBPtr, GVPtr->getType()->getPointerTo(0),
"vbptr." + VBT->ReusingBase->getName());
CGF.Builder.CreateStore(GVPtr, VBPtr);
@@ -1255,7 +1258,7 @@
// FIXME: Update the code that emits this adjustment in thunks prologues.
This = CGF.Builder.CreateConstGEP1_32(This, StaticOffset.getQuantity());
} else {
- This = CGF.Builder.CreateConstInBoundsGEP1_32(This,
+ This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This,
StaticOffset.getQuantity());
}
}
@@ -1310,8 +1313,8 @@
This = CGF.Builder.CreateBitCast(This, charPtrTy);
assert(Adjustment.isPositive());
- This =
- CGF.Builder.CreateConstInBoundsGEP1_32(This, -Adjustment.getQuantity());
+ This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This,
+ -Adjustment.getQuantity());
return CGF.Builder.CreateBitCast(This, thisTy);
}
@@ -1550,8 +1553,8 @@
llvm::ConstantInt::get(CGM.IntTy, 1)};
// Create a GEP which points just after the first entry in the VFTable,
// this should be the location of the first virtual method.
- llvm::Constant *VTableGEP =
- llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, GEPIndices);
+ llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(
+ VTable->getValueType(), VTable, GEPIndices);
if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) {
VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
if (C)
@@ -1871,7 +1874,7 @@
}
if (RA.NonVirtual)
- V = CGF.Builder.CreateConstInBoundsGEP1_32(V, RA.NonVirtual);
+ V = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, V, RA.NonVirtual);
// Cast back to the original type.
return CGF.Builder.CreateBitCast(V, Ret->getType());
@@ -3020,13 +3023,15 @@
if (CHD->isWeakForLinker())
CHD->setComdat(CGM.getModule().getOrInsertComdat(CHD->getName()));
+ auto *Bases = getBaseClassArray(Classes);
+
// Initialize the base class ClassHierarchyDescriptor.
llvm::Constant *Fields[] = {
llvm::ConstantInt::get(CGM.IntTy, 0), // Unknown
llvm::ConstantInt::get(CGM.IntTy, Flags),
llvm::ConstantInt::get(CGM.IntTy, Classes.size()),
ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
- getBaseClassArray(Classes),
+ Bases->getValueType(), Bases,
llvm::ArrayRef<llvm::Value *>(GEPIndices))),
};
CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
@@ -3193,8 +3198,8 @@
}
llvm::Constant *
-MicrosoftCXXABI::getAddrOfCXXHandlerMapEntry(QualType Type,
- QualType CatchHandlerType) {
+MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type,
+ QualType CatchHandlerType) {
// TypeDescriptors for exceptions never have qualified pointer types,
// qualifiers are stored seperately in order to support qualification
// conversions.
@@ -3203,16 +3208,6 @@
bool IsReference = CatchHandlerType->isReferenceType();
- SmallString<256> MangledName;
- {
- llvm::raw_svector_ostream Out(MangledName);
- getMangleContext().mangleCXXHandlerMapEntry(Type, IsConst, IsVolatile,
- IsReference, Out);
- }
-
- if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
-
uint32_t Flags = 0;
if (IsConst)
Flags |= 1;
@@ -3221,15 +3216,24 @@
if (IsReference)
Flags |= 8;
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ getMangleContext().mangleCXXCatchHandlerType(Type, Flags, Out);
+ }
+
+ if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
+ return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
+
llvm::Constant *Fields[] = {
- llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags
- getImageRelativeConstant(getAddrOfRTTIDescriptor(Type)), // TypeDescriptor
+ llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags
+ getAddrOfRTTIDescriptor(Type), // TypeDescriptor
};
- llvm::StructType *HandlerMapEntryType = getHandlerMapEntryType();
+ llvm::StructType *CatchHandlerTypeType = getCatchHandlerTypeType();
auto *Var = new llvm::GlobalVariable(
- CGM.getModule(), HandlerMapEntryType, /*Constant=*/true,
+ CGM.getModule(), CatchHandlerTypeType, /*Constant=*/true,
llvm::GlobalValue::PrivateLinkage,
- llvm::ConstantStruct::get(HandlerMapEntryType, Fields),
+ llvm::ConstantStruct::get(CatchHandlerTypeType, Fields),
StringRef(MangledName));
Var->setUnnamedAddr(true);
Var->setSection("llvm.metadata");
@@ -3596,9 +3600,10 @@
// - a standard pointer conversion (4.10) not involving conversions to
// pointers to private or protected or ambiguous classes
//
- // All pointers are convertible to pointer-to-void so ensure that it is in the
- // CatchableTypeArray.
- if (IsPointer)
+ // C++14 [conv.ptr]p2:
+ // A prvalue of type "pointer to cv T," where T is an object type, can be
+ // converted to a prvalue of type "pointer to cv void".
+ if (IsPointer && T->getPointeeType()->isObjectType())
CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
// C++14 [except.handle]p3:
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index 03771e1..25e5740 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -63,7 +63,7 @@
CoverageInfo(CoverageInfo),
M(new llvm::Module(ModuleName, C)) {}
- virtual ~CodeGeneratorImpl() {
+ ~CodeGeneratorImpl() override {
// There should normally not be any leftover inline method definitions.
assert(DeferredInlineMethodDefinitions.empty() ||
Diags.hasErrorOccurred());
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 43cf791..48c85e6 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -37,7 +37,8 @@
unsigned LastIndex) {
// Alternatively, we could emit this as a loop in the source.
for (unsigned I = FirstIndex; I <= LastIndex; ++I) {
- llvm::Value *Cell = Builder.CreateConstInBoundsGEP1_32(Array, I);
+ llvm::Value *Cell =
+ Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(), Array, I);
Builder.CreateStore(Value, Cell);
}
}
@@ -339,9 +340,15 @@
//
// FIXME: This needs to be generalized to handle classes as well.
const RecordDecl *RD = RT->getDecl();
- if (!RD->isStruct() || isa<CXXRecordDecl>(RD))
+ if (!RD->isStruct())
return false;
+ // We try to expand CLike CXXRecordDecl.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (!CXXRD->isCLike())
+ return false;
+ }
+
uint64_t Size = 0;
for (const auto *FD : RD->fields()) {
@@ -1352,7 +1359,8 @@
} else {
// 9 is %eflags, which doesn't get a size on Darwin for some
// reason.
- Builder.CreateStore(Four8, Builder.CreateConstInBoundsGEP1_32(Address, 9));
+ Builder.CreateStore(
+ Four8, Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, Address, 9));
// 11-16 are st(0..5). Not sure why we stop at 5.
// These have size 12, which is sizeof(long double) on
@@ -1617,7 +1625,7 @@
: X86_64TargetCodeGenInfo(CGT, HasAVX) {}
void getDependentLibraryOption(llvm::StringRef Lib,
- llvm::SmallString<24> &Opt) const {
+ llvm::SmallString<24> &Opt) const override {
Opt = "\01";
Opt += Lib;
}
@@ -2766,8 +2774,8 @@
static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr,
QualType Ty,
CodeGenFunction &CGF) {
- llvm::Value *overflow_arg_area_p =
- CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_p");
+ llvm::Value *overflow_arg_area_p = CGF.Builder.CreateStructGEP(
+ nullptr, VAListAddr, 2, "overflow_arg_area_p");
llvm::Value *overflow_arg_area =
CGF.Builder.CreateLoad(overflow_arg_area_p, "overflow_arg_area");
@@ -2847,14 +2855,16 @@
llvm::Value *gp_offset_p = nullptr, *gp_offset = nullptr;
llvm::Value *fp_offset_p = nullptr, *fp_offset = nullptr;
if (neededInt) {
- gp_offset_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "gp_offset_p");
+ gp_offset_p =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 0, "gp_offset_p");
gp_offset = CGF.Builder.CreateLoad(gp_offset_p, "gp_offset");
InRegs = llvm::ConstantInt::get(CGF.Int32Ty, 48 - neededInt * 8);
InRegs = CGF.Builder.CreateICmpULE(gp_offset, InRegs, "fits_in_gp");
}
if (neededSSE) {
- fp_offset_p = CGF.Builder.CreateStructGEP(VAListAddr, 1, "fp_offset_p");
+ fp_offset_p =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 1, "fp_offset_p");
fp_offset = CGF.Builder.CreateLoad(fp_offset_p, "fp_offset");
llvm::Value *FitsInFP =
llvm::ConstantInt::get(CGF.Int32Ty, 176 - neededSSE * 16);
@@ -2882,9 +2892,8 @@
// simple assembling of a structure from scattered addresses has many more
// loads than necessary. Can we clean this up?
llvm::Type *LTy = CGF.ConvertTypeForMem(Ty);
- llvm::Value *RegAddr =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(VAListAddr, 3),
- "reg_save_area");
+ llvm::Value *RegAddr = CGF.Builder.CreateLoad(
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3), "reg_save_area");
if (neededInt && neededSSE) {
// FIXME: Cleanup.
assert(AI.isDirect() && "Unexpected ABI info for mixed regs");
@@ -2904,9 +2913,9 @@
llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
llvm::Value *V =
CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegLoAddr, PTyLo));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 0));
V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegHiAddr, PTyHi));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 1));
RegAddr = CGF.Builder.CreateBitCast(Tmp,
llvm::PointerType::getUnqual(LTy));
@@ -2943,10 +2952,10 @@
Tmp = CGF.Builder.CreateBitCast(Tmp, ST->getPointerTo());
V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo,
DblPtrTy));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 0));
V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrHi,
DblPtrTy));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 1));
RegAddr = CGF.Builder.CreateBitCast(Tmp,
llvm::PointerType::getUnqual(LTy));
}
@@ -3781,10 +3790,12 @@
ImagAddr = Builder.CreateIntToPtr(ImagAddr, PBaseTy);
llvm::Value *Real = Builder.CreateLoad(RealAddr, false, ".vareal");
llvm::Value *Imag = Builder.CreateLoad(ImagAddr, false, ".vaimag");
- llvm::Value *Ptr = CGF.CreateTempAlloca(CGT.ConvertTypeForMem(Ty),
- "vacplx");
- llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, ".real");
- llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, ".imag");
+ llvm::AllocaInst *Ptr =
+ CGF.CreateTempAlloca(CGT.ConvertTypeForMem(Ty), "vacplx");
+ llvm::Value *RealPtr =
+ Builder.CreateStructGEP(Ptr->getAllocatedType(), Ptr, 0, ".real");
+ llvm::Value *ImagPtr =
+ Builder.CreateStructGEP(Ptr->getAllocatedType(), Ptr, 1, ".imag");
Builder.CreateStore(Real, RealPtr, false);
Builder.CreateStore(Imag, ImagPtr, false);
return Ptr;
@@ -3904,8 +3915,8 @@
llvm::Value *EmitAAPCSVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const;
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override {
+ llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const override {
return isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF)
: EmitAAPCSVAArg(VAListAddr, Ty, CGF);
}
@@ -3916,13 +3927,15 @@
AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind Kind)
: TargetCodeGenInfo(new AArch64ABIInfo(CGT, Kind)) {}
- StringRef getARCRetainAutoreleasedReturnValueMarker() const {
+ StringRef getARCRetainAutoreleasedReturnValueMarker() const override {
return "mov\tfp, fp\t\t; marker for objc_retainAutoreleaseReturnValue";
}
- int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { return 31; }
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
+ return 31;
+ }
- virtual bool doesReturnSlotInterfereWithArgs() const { return false; }
+ bool doesReturnSlotInterfereWithArgs() const override { return false; }
};
}
@@ -4119,13 +4132,15 @@
int RegSize = IsIndirect ? 8 : getContext().getTypeSize(Ty) / 8;
if (!IsFPR) {
// 3 is the field number of __gr_offs
- reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 3, "gr_offs_p");
+ reg_offs_p =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3, "gr_offs_p");
reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "gr_offs");
reg_top_index = 1; // field number for __gr_top
RegSize = llvm::RoundUpToAlignment(RegSize, 8);
} else {
// 4 is the field number of __vr_offs.
- reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 4, "vr_offs_p");
+ reg_offs_p =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 4, "vr_offs_p");
reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "vr_offs");
reg_top_index = 2; // field number for __vr_top
RegSize = 16 * NumRegs;
@@ -4186,8 +4201,8 @@
CGF.EmitBlock(InRegBlock);
llvm::Value *reg_top_p = nullptr, *reg_top = nullptr;
- reg_top_p =
- CGF.Builder.CreateStructGEP(VAListAddr, reg_top_index, "reg_top_p");
+ reg_top_p = CGF.Builder.CreateStructGEP(nullptr, VAListAddr, reg_top_index,
+ "reg_top_p");
reg_top = CGF.Builder.CreateLoad(reg_top_p, "reg_top");
llvm::Value *BaseAddr = CGF.Builder.CreateGEP(reg_top, reg_offs);
llvm::Value *RegAddr = nullptr;
@@ -4210,7 +4225,7 @@
assert(!IsIndirect && "Homogeneous aggregates should be passed directly");
llvm::Type *BaseTy = CGF.ConvertType(QualType(Base, 0));
llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers);
- llvm::Value *Tmp = CGF.CreateTempAlloca(HFATy);
+ llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(HFATy);
int Offset = 0;
if (CGF.CGM.getDataLayout().isBigEndian() && Ctx.getTypeSize(Base) < 128)
@@ -4221,7 +4236,8 @@
llvm::Value *LoadAddr = CGF.Builder.CreateGEP(BaseAddr, BaseOffset);
LoadAddr = CGF.Builder.CreateBitCast(
LoadAddr, llvm::PointerType::getUnqual(BaseTy));
- llvm::Value *StoreAddr = CGF.Builder.CreateStructGEP(Tmp, i);
+ llvm::Value *StoreAddr =
+ CGF.Builder.CreateStructGEP(Tmp->getAllocatedType(), Tmp, i);
llvm::Value *Elem = CGF.Builder.CreateLoad(LoadAddr);
CGF.Builder.CreateStore(Elem, StoreAddr);
@@ -4254,7 +4270,7 @@
CGF.EmitBlock(OnStackBlock);
llvm::Value *stack_p = nullptr, *OnStackAddr = nullptr;
- stack_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "stack_p");
+ stack_p = CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 0, "stack_p");
OnStackAddr = CGF.Builder.CreateLoad(stack_p, "stack");
// Again, stack arguments may need realigmnent. In this case both integer and
@@ -5171,7 +5187,9 @@
}
bool SystemZABIInfo::isCompoundType(QualType Ty) const {
- return Ty->isAnyComplexType() || isAggregateTypeForABI(Ty);
+ return (Ty->isAnyComplexType() ||
+ Ty->isVectorType() ||
+ isAggregateTypeForABI(Ty));
}
bool SystemZABIInfo::isFPArgumentType(QualType Ty) const {
@@ -5206,11 +5224,12 @@
// Check the fields.
for (const auto *FD : RD->fields()) {
- // Empty bitfields don't affect things either way.
+ // For compatibility with GCC, ignore empty bitfields in C++ mode.
// Unlike isSingleElementStruct(), empty structure and array fields
// do count. So do anonymous bitfields that aren't zero-sized.
- if (FD->isBitField() && FD->getBitWidthValue(getContext()) == 0)
- return true;
+ if (getContext().getLangOpts().CPlusPlus &&
+ FD->isBitField() && FD->getBitWidthValue(getContext()) == 0)
+ continue;
// Unlike isSingleElementStruct(), arrays do not count.
// Nested isFPArgumentType structures still do though.
@@ -5242,17 +5261,21 @@
// Every argument occupies 8 bytes and is passed by preference in either
// GPRs or FPRs.
Ty = CGF.getContext().getCanonicalType(Ty);
+ llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty);
+ llvm::Type *APTy = llvm::PointerType::getUnqual(ArgTy);
ABIArgInfo AI = classifyArgumentType(Ty);
- bool InFPRs = isFPArgumentType(Ty);
-
- llvm::Type *APTy = llvm::PointerType::getUnqual(CGF.ConvertTypeForMem(Ty));
bool IsIndirect = AI.isIndirect();
+ bool InFPRs = false;
unsigned UnpaddedBitSize;
if (IsIndirect) {
APTy = llvm::PointerType::getUnqual(APTy);
UnpaddedBitSize = 64;
- } else
+ } else {
+ if (AI.getCoerceToType())
+ ArgTy = AI.getCoerceToType();
+ InFPRs = ArgTy->isFloatTy() || ArgTy->isDoubleTy();
UnpaddedBitSize = getContext().getTypeSize(Ty);
+ }
unsigned PaddedBitSize = 64;
assert((UnpaddedBitSize <= PaddedBitSize) && "Invalid argument size.");
@@ -5272,8 +5295,8 @@
RegPadding = Padding; // values are passed in the low bits of a GPR
}
- llvm::Value *RegCountPtr =
- CGF.Builder.CreateStructGEP(VAListAddr, RegCountField, "reg_count_ptr");
+ llvm::Value *RegCountPtr = CGF.Builder.CreateStructGEP(
+ nullptr, VAListAddr, RegCountField, "reg_count_ptr");
llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count");
llvm::Type *IndexTy = RegCount->getType();
llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs);
@@ -5297,7 +5320,7 @@
llvm::Value *RegOffset =
CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset");
llvm::Value *RegSaveAreaPtr =
- CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr");
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3, "reg_save_area_ptr");
llvm::Value *RegSaveArea =
CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area");
llvm::Value *RawRegAddr =
@@ -5316,8 +5339,8 @@
CGF.EmitBlock(InMemBlock);
// Work out the address of a stack argument.
- llvm::Value *OverflowArgAreaPtr =
- CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr");
+ llvm::Value *OverflowArgAreaPtr = CGF.Builder.CreateStructGEP(
+ nullptr, VAListAddr, 2, "overflow_arg_area_ptr");
llvm::Value *OverflowArgArea =
CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area");
llvm::Value *PaddingV = llvm::ConstantInt::get(IndexTy, Padding);
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 0e99c58..07a5e42 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -2062,6 +2062,9 @@
else
TC = new toolchains::Linux(*this, Target, Args);
break;
+ case llvm::Triple::NaCl:
+ TC = new toolchains::NaCl_TC(*this, Target, Args);
+ break;
case llvm::Triple::Solaris:
TC = new toolchains::Solaris(*this, Target, Args);
break;
@@ -2149,7 +2152,7 @@
Major = Minor = Micro = 0;
if (*Str == '\0')
- return true;
+ return false;
char *End;
Major = (unsigned) strtol(Str, &End, 10);
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index fb907a7..cd3785c 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -48,7 +48,7 @@
RecoverableByDefault = Undefined | Integer,
Unrecoverable = Address | Unreachable | Return,
LegacyFsanitizeRecoverMask = Undefined | Integer,
- NeedsLTO = CFIDerivedCast | CFIUnrelatedCast | CFIVptr,
+ NeedsLTO = CFI,
};
}
@@ -159,7 +159,8 @@
}
bool SanitizerArgs::needsUbsanRt() const {
- return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt);
+ return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt) &&
+ !Sanitizers.has(SanitizerKind::Address);
}
bool SanitizerArgs::requiresPIE() const {
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 9606df6..434dc4d 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -135,7 +135,7 @@
.Cases("sc000", "cortex-m0", "cortex-m0plus", "cortex-m1", "armv6m")
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "armv7")
.Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "armv7")
- .Cases("cortex-r4", "cortex-r5", "cortex-r7", "armv7r")
+ .Cases("cortex-r4", "cortex-r4f", "cortex-r5", "cortex-r7", "armv7r")
.Cases("sc300", "cortex-m3", "armv7m")
.Cases("cortex-m4", "cortex-m7", "armv7em")
.Case("swift", "armv7s")
@@ -338,6 +338,12 @@
OS + "_dynamic.dylib").str(),
/*AlwaysLink*/ true, /*IsEmbedded*/ false,
/*AddRPath*/ true);
+
+ if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
+ // Add explicit dependcy on -lc++abi, as -lc++ doesn't re-export
+ // all RTTI-related symbols that UBSan uses.
+ CmdArgs.push_back("-lc++abi");
+ }
}
void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
@@ -401,9 +407,6 @@
<< "-fsanitize=undefined";
} else {
AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
- // Add explicit dependcy on -lc++abi, as -lc++ doesn't re-export
- // all RTTI-related symbols that UBSan uses.
- CmdArgs.push_back("-lc++abi");
}
}
@@ -2084,7 +2087,8 @@
getTriple().getArch() == llvm::Triple::aarch64_be ||
(getTriple().getOS() == llvm::Triple::Linux &&
(!V.isOlderThan(4, 7, 0) ||
- getTriple().getEnvironment() == llvm::Triple::Android));
+ getTriple().getEnvironment() == llvm::Triple::Android)) ||
+ getTriple().getOS() == llvm::Triple::NaCl;
if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
options::OPT_fno_use_init_array,
@@ -2307,6 +2311,159 @@
}
// End Hexagon
+/// NaCl Toolchain
+NaCl_TC::NaCl_TC(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+
+ // Remove paths added by Generic_GCC. NaCl Toolchain cannot use the
+ // default paths, and must instead only use the paths provided
+ // with this toolchain based on architecture.
+ path_list& file_paths = getFilePaths();
+ path_list& prog_paths = getProgramPaths();
+
+ file_paths.clear();
+ prog_paths.clear();
+
+ // Path for library files (libc.a, ...)
+ std::string FilePath(getDriver().Dir + "/../");
+
+ // Path for tools (clang, ld, etc..)
+ std::string ProgPath(getDriver().Dir + "/../");
+
+ // Path for toolchain libraries (libgcc.a, ...)
+ std::string ToolPath(getDriver().ResourceDir + "/lib/");
+
+ switch(Triple.getArch()) {
+ case llvm::Triple::x86: {
+ file_paths.push_back(FilePath + "x86_64-nacl/lib32");
+ file_paths.push_back(FilePath + "x86_64-nacl/usr/lib32");
+ prog_paths.push_back(ProgPath + "x86_64-nacl/bin");
+ file_paths.push_back(ToolPath + "i686-nacl");
+ break;
+ }
+ case llvm::Triple::x86_64: {
+ file_paths.push_back(FilePath + "x86_64-nacl/lib");
+ file_paths.push_back(FilePath + "x86_64-nacl/usr/lib");
+ prog_paths.push_back(ProgPath + "x86_64-nacl/bin");
+ file_paths.push_back(ToolPath + "x86_64-nacl");
+ break;
+ }
+ case llvm::Triple::arm: {
+ file_paths.push_back(FilePath + "arm-nacl/lib");
+ file_paths.push_back(FilePath + "arm-nacl/usr/lib");
+ prog_paths.push_back(ProgPath + "arm-nacl/bin");
+ file_paths.push_back(ToolPath + "arm-nacl");
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Use provided linker, not system linker
+ Linker = GetProgramPath("ld");
+ NaClArmMacrosPath = GetFilePath("nacl-arm-macros.s");
+}
+
+void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ SmallString<128> P(D.Dir + "/../");
+ if (getTriple().getArch() == llvm::Triple::arm) {
+ llvm::sys::path::append(P, "arm-nacl/usr/include");
+ } else if (getTriple().getArch() == llvm::Triple::x86) {
+ llvm::sys::path::append(P, "x86_64-nacl/usr/include");
+ } else if (getTriple().getArch() == llvm::Triple::x86_64) {
+ llvm::sys::path::append(P, "x86_64-nacl/usr/include");
+ } else {
+ return;
+ }
+
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+}
+
+void NaCl_TC::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Check for -stdlib= flags. We only support libc++ but this consumes the arg
+ // if the value is libc++, and emits an error for other values.
+ GetCXXStdlibType(Args);
+ CmdArgs.push_back("-lc++");
+}
+
+void NaCl_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ // Check for -stdlib= flags. We only support libc++ but this consumes the arg
+ // if the value is libc++, and emits an error for other values.
+ GetCXXStdlibType(DriverArgs);
+
+ if (getTriple().getArch() == llvm::Triple::arm) {
+ SmallString<128> P(D.Dir + "/../");
+ llvm::sys::path::append(P, "arm-nacl/include/c++/v1");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ } else if (getTriple().getArch() == llvm::Triple::x86) {
+ SmallString<128> P(D.Dir + "/../");
+ llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ } else if (getTriple().getArch() == llvm::Triple::x86_64) {
+ SmallString<128> P(D.Dir + "/../");
+ llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ }
+}
+
+ToolChain::CXXStdlibType NaCl_TC::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+
+ return ToolChain::CST_Libcxx;
+}
+
+std::string NaCl_TC::ComputeEffectiveClangTriple(
+ const ArgList &Args, types::ID InputType) const {
+ llvm::Triple TheTriple(ComputeLLVMTriple(Args, InputType));
+ if (TheTriple.getArch() == llvm::Triple::arm &&
+ TheTriple.getEnvironment() == llvm::Triple::UnknownEnvironment)
+ TheTriple.setEnvironment(llvm::Triple::GNUEABIHF);
+ return TheTriple.getTriple();
+}
+
+Tool *NaCl_TC::buildLinker() const {
+ return new tools::nacltools::Link(*this);
+}
+
+Tool *NaCl_TC::buildAssembler() const {
+ if (getTriple().getArch() == llvm::Triple::arm)
+ return new tools::nacltools::AssembleARM(*this);
+ return new tools::gnutools::Assemble(*this);
+}
+// End NaCl
+
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
/// Currently does not support anything else but compilation.
@@ -2706,10 +2863,12 @@
DebianSqueeze,
DebianWheezy,
DebianJessie,
+ DebianStretch,
Exherbo,
RHEL4,
RHEL5,
RHEL6,
+ RHEL7,
Fedora,
OpenSUSE,
UbuntuHardy,
@@ -2725,11 +2884,13 @@
UbuntuRaring,
UbuntuSaucy,
UbuntuTrusty,
+ UbuntuUtopic,
+ UbuntuVivid,
UnknownDistro
};
static bool IsRedhat(enum Distro Distro) {
- return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL6);
+ return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL7);
}
static bool IsOpenSUSE(enum Distro Distro) {
@@ -2737,11 +2898,11 @@
}
static bool IsDebian(enum Distro Distro) {
- return Distro >= DebianLenny && Distro <= DebianJessie;
+ return Distro >= DebianLenny && Distro <= DebianStretch;
}
static bool IsUbuntu(enum Distro Distro) {
- return Distro >= UbuntuHardy && Distro <= UbuntuTrusty;
+ return Distro >= UbuntuHardy && Distro <= UbuntuVivid;
}
static Distro DetectDistro(llvm::Triple::ArchType Arch) {
@@ -2768,6 +2929,8 @@
.Case("raring", UbuntuRaring)
.Case("saucy", UbuntuSaucy)
.Case("trusty", UbuntuTrusty)
+ .Case("utopic", UbuntuUtopic)
+ .Case("vivid", UbuntuVivid)
.Default(UnknownDistro);
return Version;
}
@@ -2779,7 +2942,9 @@
return Fedora;
if (Data.startswith("Red Hat Enterprise Linux") ||
Data.startswith("CentOS")) {
- if (Data.find("release 6") != StringRef::npos)
+ if (Data.find("release 7") != StringRef::npos)
+ return RHEL7;
+ else if (Data.find("release 6") != StringRef::npos)
return RHEL6;
else if (Data.find("release 5") != StringRef::npos)
return RHEL5;
@@ -2800,6 +2965,8 @@
return DebianWheezy;
else if (Data.startswith("jessie/sid") || Data[0] == '8')
return DebianJessie;
+ else if (Data.startswith("stretch/sid") || Data[0] == '9')
+ return DebianStretch;
return UnknownDistro;
}
@@ -2996,8 +3163,7 @@
if (IsRedhat(Distro))
ExtraOpts.push_back("--no-add-needed");
- if (Distro == DebianSqueeze || Distro == DebianWheezy ||
- Distro == DebianJessie || IsOpenSUSE(Distro) ||
+ if ((IsDebian(Distro) && Distro >= DebianSqueeze) || IsOpenSUSE(Distro) ||
(IsRedhat(Distro) && Distro != RHEL4 && Distro != RHEL5) ||
(IsUbuntu(Distro) && Distro >= UbuntuKarmic))
ExtraOpts.push_back("--build-id");
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index ebd23d1..456bf77 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -152,7 +152,7 @@
public:
Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~Generic_GCC();
+ ~Generic_GCC() override;
void printVerboseInfo(raw_ostream &OS) const override;
@@ -196,7 +196,7 @@
public:
MachO(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~MachO();
+ ~MachO() override;
/// @name MachO specific toolchain API
/// {
@@ -345,7 +345,7 @@
public:
Darwin(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~Darwin();
+ ~Darwin() override;
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
@@ -487,8 +487,7 @@
AddCCKextLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args)
- const override;
+ void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
void
AddLinkARCArgs(const llvm::opt::ArgList &Args,
@@ -699,7 +698,7 @@
public:
Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~Hexagon_TC();
+ ~Hexagon_TC() override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -717,13 +716,52 @@
static StringRef GetTargetCPU(const llvm::opt::ArgList &Args);
};
+class LLVM_LIBRARY_VISIBILITY NaCl_TC : public Generic_ELF {
+public:
+ NaCl_TC(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ CXXStdlibType
+ GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ void
+ AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ bool
+ IsIntegratedAssemblerDefault() const override { return false; }
+
+ // Get the path to the file containing NaCl's ARM macros. It lives in NaCl_TC
+ // because the AssembleARM tool needs a const char * that it can pass around
+ // and the toolchain outlives all the jobs.
+ const char *GetNaClArmMacrosPath() const { return NaClArmMacrosPath.c_str(); }
+
+ std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
+ types::ID InputType) const override;
+ std::string Linker;
+
+protected:
+ Tool *buildLinker() const override;
+ Tool *buildAssembler() const override;
+
+private:
+ std::string NaClArmMacrosPath;
+};
+
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain {
public:
TCEToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~TCEToolChain();
+ ~TCEToolChain() override;
bool IsMathErrnoDefault() const override;
bool isPICDefault() const override;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index ed1bd3e..3053d9b 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -750,9 +750,8 @@
Features.push_back("-crypto");
}
- // En/disable crc
- if (Arg *A = Args.getLastArg(options::OPT_mcrc,
- options::OPT_mnocrc)) {
+ // En/disable crc code generation.
+ if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
if (A->getOption().matches(options::OPT_mcrc))
Features.push_back("+crc");
else
@@ -862,12 +861,14 @@
}
}
- // Setting -mno-global-merge disables the codegen global merge pass. Setting
- // -mglobal-merge has no effect as the pass is enabled by default.
+ // Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
+ CmdArgs.push_back("-backend-option");
if (A->getOption().matches(options::OPT_mno_global_merge))
- CmdArgs.push_back("-mno-global-merge");
+ CmdArgs.push_back("-arm-global-merge=false");
+ else
+ CmdArgs.push_back("-arm-global-merge=true");
}
if (!Args.hasFlag(options::OPT_mimplicit_float,
@@ -958,12 +959,14 @@
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
}
- // Setting -mno-global-merge disables the codegen global merge pass. Setting
- // -mglobal-merge has no effect as the pass is enabled by default.
+ // Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
+ CmdArgs.push_back("-backend-option");
if (A->getOption().matches(options::OPT_mno_global_merge))
- CmdArgs.push_back("-mno-global-merge");
+ CmdArgs.push_back("-aarch64-global-merge=false");
+ else
+ CmdArgs.push_back("-aarch64-global-merge=true");
}
if (Args.hasArg(options::OPT_ffixed_x18)) {
@@ -1115,11 +1118,21 @@
if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
StringRef Val = StringRef(A->getValue());
- if (Val == "2008")
- Features.push_back("+nan2008");
- else if (Val == "legacy")
- Features.push_back("-nan2008");
- else
+ if (Val == "2008") {
+ if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008)
+ Features.push_back("+nan2008");
+ else {
+ Features.push_back("-nan2008");
+ D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
+ }
+ } else if (Val == "legacy") {
+ if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy)
+ Features.push_back("-nan2008");
+ else {
+ Features.push_back("+nan2008");
+ D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;
+ }
+ } else
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
}
@@ -1418,6 +1431,18 @@
return "z10";
}
+static void getSystemZTargetFeatures(const ArgList &Args,
+ std::vector<const char *> &Features) {
+ // -m(no-)htm overrides use of the transactional-execution facility.
+ if (Arg *A = Args.getLastArg(options::OPT_mhtm,
+ options::OPT_mno_htm)) {
+ if (A->getOption().matches(options::OPT_mhtm))
+ Features.push_back("+transactional-execution");
+ else
+ Features.push_back("-transactional-execution");
+ }
+}
+
static const char *getX86TargetCPU(const ArgList &Args,
const llvm::Triple &Triple) {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
@@ -1566,6 +1591,17 @@
static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<const char *> &Features) {
+ // If -march=native, autodetect the feature list.
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ if (StringRef(A->getValue()) == "native") {
+ llvm::StringMap<bool> HostFeatures;
+ if (llvm::sys::getHostCPUFeatures(HostFeatures))
+ for (auto &F : HostFeatures)
+ Features.push_back(Args.MakeArgString((F.second ? "+" : "-") +
+ F.first()));
+ }
+ }
+
if (Triple.getArchName() == "x86_64h") {
// x86_64h implies quite a few of the more modern subtarget features
// for Haswell class CPUs, but not all of them. Opt-out of a few.
@@ -1766,8 +1802,17 @@
const ArgList &Args,
std::vector<const char *> &Features) {
std::pair<StringRef, StringRef> Split = March.split("+");
- if (Split.first != "armv8-a")
+
+ if (Split.first == "armv8-a" ||
+ Split.first == "armv8a") {
+ // ok, no additional features.
+ } else if (
+ Split.first == "armv8.1-a" ||
+ Split.first == "armv8.1a" ) {
+ Features.push_back("+v8.1a");
+ } else {
return false;
+ }
if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
return false;
@@ -1885,6 +1930,9 @@
case llvm::Triple::sparcv9:
getSparcTargetFeatures(Args, Features);
break;
+ case llvm::Triple::systemz:
+ getSystemZTargetFeatures(Args, Features);
+ break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
getAArch64TargetFeatures(D, Args, Features);
@@ -2281,18 +2329,10 @@
StaticRuntimes.push_back("msan");
if (SanArgs.needsTsanRt())
StaticRuntimes.push_back("tsan");
- // WARNING: UBSan should always go last.
if (SanArgs.needsUbsanRt()) {
- // Check if UBSan is combined with another sanitizers.
- if (StaticRuntimes.empty()) {
- StaticRuntimes.push_back("ubsan_standalone");
- if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("ubsan_standalone_cxx");
- } else {
- StaticRuntimes.push_back("ubsan");
- if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("ubsan_cxx");
- }
+ StaticRuntimes.push_back("ubsan_standalone");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("ubsan_standalone_cxx");
}
}
@@ -2647,6 +2687,13 @@
assert(JA.getType() == types::TY_PP_Asm &&
"Unexpected output type!");
}
+
+ // Preserve use-list order by default when emitting bitcode, so that
+ // loading the bitcode up in 'opt' or 'llc' and running passes gives the
+ // same result as running passes here. For LTO, we don't need to preserve
+ // the use-list order, since serialization to bitcode is part of the flow.
+ if (JA.getType() == types::TY_LLVM_BC)
+ CmdArgs.push_back("-emit-llvm-uselists");
}
// We normally speed up the clang process a bit by skipping destructors at
@@ -3045,6 +3092,9 @@
if (!SignedZeros)
CmdArgs.push_back("-fno-signed-zeros");
+ if (ReciprocalMath)
+ CmdArgs.push_back("-freciprocal-math");
+
// Validate and pass through -fp-contract option.
if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
@@ -3087,8 +3137,10 @@
Args.hasArg(options::OPT_dA))
CmdArgs.push_back("-masm-verbose");
- if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
- IsIntegratedAssemblerDefault))
+ bool UsingIntegratedAssembler =
+ Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
+ IsIntegratedAssemblerDefault);
+ if (!UsingIntegratedAssembler)
CmdArgs.push_back("-no-integrated-as");
if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
@@ -3332,7 +3384,8 @@
}
if (!Args.hasFlag(options::OPT_funique_section_names,
- options::OPT_fno_unique_section_names, true))
+ options::OPT_fno_unique_section_names,
+ !UsingIntegratedAssembler))
CmdArgs.push_back("-fno-unique-section-names");
Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
@@ -5586,7 +5639,7 @@
.Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
.Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "v7")
- .Cases("cortex-r4", "cortex-r5", "cortex-r7", "v7r")
+ .Cases("cortex-r4", "cortex-r4f", "cortex-r5", "cortex-r7", "v7r")
.Cases("sc000", "cortex-m0", "cortex-m0plus", "cortex-m1", "v6m")
.Cases("sc300", "cortex-m3", "v7m")
.Cases("cortex-m4", "cortex-m7", "v7em")
@@ -5610,6 +5663,26 @@
CmdArgs.push_back(LinkFlag);
}
+mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
+ return (NanEncoding)llvm::StringSwitch<int>(CPU)
+ .Case("mips1", NanLegacy)
+ .Case("mips2", NanLegacy)
+ .Case("mips3", NanLegacy)
+ .Case("mips4", NanLegacy)
+ .Case("mips5", NanLegacy)
+ .Case("mips32", NanLegacy)
+ .Case("mips32r2", NanLegacy)
+ .Case("mips32r3", NanLegacy | Nan2008)
+ .Case("mips32r5", NanLegacy | Nan2008)
+ .Case("mips32r6", Nan2008)
+ .Case("mips64", NanLegacy)
+ .Case("mips64r2", NanLegacy)
+ .Case("mips64r3", NanLegacy | Nan2008)
+ .Case("mips64r5", NanLegacy | Nan2008)
+ .Case("mips64r6", Nan2008)
+ .Default(NanLegacy);
+}
+
bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
return A && (A->getValue() == StringRef(Value));
@@ -7391,7 +7464,8 @@
}
StringRef ARMFloatABI = tools::arm::getARMFloatABI(
- getToolChain().getDriver(), Args, Triple);
+ getToolChain().getDriver(), Args,
+ llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
@@ -7911,6 +7985,172 @@
llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
}
+
+// NaCl ARM assembly (inline or standalone) can be written with a set of macros
+// for the various SFI requirements like register masking. The assembly tool
+// inserts the file containing the macros as an input into all the assembly
+// jobs.
+void nacltools::AssembleARM::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::NaCl_TC& ToolChain =
+ static_cast<const toolchains::NaCl_TC&>(getToolChain());
+ InputInfo NaClMacros(ToolChain.GetNaClArmMacrosPath(), types::TY_PP_Asm,
+ "nacl-arm-macros.s");
+ InputInfoList NewInputs;
+ NewInputs.push_back(NaClMacros);
+ NewInputs.append(Inputs.begin(), Inputs.end());
+ gnutools::Assemble::ConstructJob(C, JA, Output, NewInputs, Args,
+ LinkingOutput);
+}
+
+
+// This is quite similar to gnutools::link::ConstructJob with changes that
+// we use static by default, do not yet support sanitizers or LTO, and a few
+// others. Eventually we can support more of that and hopefully migrate back
+// to gnutools::link.
+void nacltools::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ const toolchains::NaCl_TC& ToolChain =
+ static_cast<const toolchains::NaCl_TC&>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const bool IsStatic =
+ !Args.hasArg(options::OPT_dynamic) &&
+ !Args.hasArg(options::OPT_shared);
+
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+
+ if (Args.hasArg(options::OPT_s))
+ CmdArgs.push_back("-s");
+
+ // NaCl_TC doesn't have ExtraOpts like Linux; the only relevant flag from
+ // there is --build-id, which we do want.
+ CmdArgs.push_back("--build-id");
+
+ if (!IsStatic)
+ CmdArgs.push_back("--eh-frame-hdr");
+
+ CmdArgs.push_back("-m");
+ if (ToolChain.getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("elf_i386_nacl");
+ else if (ToolChain.getArch() == llvm::Triple::arm)
+ CmdArgs.push_back("armelf_nacl");
+ else if (ToolChain.getArch() == llvm::Triple::x86_64)
+ CmdArgs.push_back("elf_x86_64_nacl");
+ else
+ D.Diag(diag::err_target_unsupported_arch) << ToolChain.getArchName() <<
+ "Native Client";
+
+
+ if (IsStatic)
+ CmdArgs.push_back("-static");
+ else if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-shared");
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+
+ const char *crtbegin;
+ if (IsStatic)
+ crtbegin = "crtbeginT.o";
+ else if (Args.hasArg(options::OPT_shared))
+ crtbegin = "crtbeginS.o";
+ else
+ crtbegin = "crtbegin.o";
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_u);
+
+ const ToolChain::path_list &Paths = ToolChain.getFilePaths();
+
+ for (const auto &Path : Paths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+
+ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("--no-demangle");
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (D.CCCIsCXX() &&
+ !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
+ !IsStatic;
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bstatic");
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bdynamic");
+ CmdArgs.push_back("-lm");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib)) {
+ if (!Args.hasArg(options::OPT_nodefaultlibs)) {
+ // Always use groups, since it has no effect on dynamic libraries.
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc");
+ // NaCl's libc++ currently requires libpthread, so just always include it
+ // in the group for C++.
+ if (Args.hasArg(options::OPT_pthread) ||
+ Args.hasArg(options::OPT_pthreads) ||
+ D.CCCIsCXX()) {
+ CmdArgs.push_back("-lpthread");
+ }
+
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("--as-needed");
+ if (IsStatic)
+ CmdArgs.push_back("-lgcc_eh");
+ else
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ CmdArgs.push_back("--end-group");
+ }
+
+ if (!Args.hasArg(options::OPT_nostartfiles)) {
+ const char *crtend;
+ if (Args.hasArg(options::OPT_shared))
+ crtend = "crtendS.o";
+ else
+ crtend = "crtend.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+ }
+
+ C.addCommand(llvm::make_unique<Command>(JA, *this,
+ ToolChain.Linker.c_str(), CmdArgs));
+}
+
+
void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 5161557..33fadd1 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -234,6 +234,11 @@
}
namespace mips {
+ typedef enum {
+ NanLegacy = 1,
+ Nan2008 = 2
+ } NanEncoding;
+ NanEncoding getSupportedNanEncoding(StringRef &CPU);
void getMipsCPUAndABI(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple, StringRef &CPUName,
StringRef &ABIName);
@@ -507,6 +512,33 @@
const char *LinkingOutput) const override;
};
}
+
+namespace nacltools {
+ class LLVM_LIBRARY_VISIBILITY AssembleARM : public gnutools::Assemble {
+ public:
+ AssembleARM(const ToolChain &TC) : gnutools::Assemble(TC) {}
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("NaCl::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+}
+
/// minix -- Directly call GNU Binutils assembler and linker
namespace minix {
class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
diff --git a/lib/Edit/EditedSource.cpp b/lib/Edit/EditedSource.cpp
index a5b5875..e557de9 100644
--- a/lib/Edit/EditedSource.cpp
+++ b/lib/Edit/EditedSource.cpp
@@ -295,9 +295,11 @@
}
if (buffer[end] == ' ') {
+ assert((end + 1 != buffer.size() || buffer.data()[end + 1] == 0) &&
+ "buffer not zero-terminated!");
if (canRemoveWhitespace(/*left=*/buffer[begin-1],
/*beforeWSpace=*/buffer[end-1],
- /*right=*/buffer[end+1],
+ /*right=*/buffer.data()[end + 1], // zero-terminated
LangOpts))
++len;
return;
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 83fd6ee..a2a68bd 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -634,7 +634,7 @@
std::min(State.LowestLevelOnLine, Current.NestingLevel);
if (Current.isMemberAccess())
State.Stack.back().StartOfFunctionCall =
- Current.LastOperator ? 0 : State.Column + Current.ColumnWidth;
+ Current.LastOperator ? 0 : State.Column;
if (Current.is(TT_SelectorName))
State.Stack.back().ObjCSelectorNameFound = true;
if (Current.is(TT_CtorInitializerColon)) {
@@ -849,7 +849,8 @@
bool NoLineBreak = State.Stack.back().NoLineBreak ||
(Current.is(TT_TemplateOpener) &&
State.Stack.back().ContainsUnwrappedBuilder);
- unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
+ unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall,
+ State.Stack.back().NestedBlockIndent);
State.Stack.push_back(ParenState(NewIndent, NewIndentLevel,
State.Stack.back().LastSpace,
AvoidBinPacking, NoLineBreak));
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index b44ea5d..ad9398c 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -780,7 +780,15 @@
return false;
FormatToken *EndBacktick = Tokens.back();
- if (!(EndBacktick->is(tok::unknown) && EndBacktick->TokenText == "`"))
+ // Backticks get lexed as tok:unknown tokens. If a template string contains
+ // a comment start, it gets lexed as a tok::comment, or tok::unknown if
+ // unterminated.
+ if (!EndBacktick->isOneOf(tok::comment, tok::unknown))
+ return false;
+ size_t CommentBacktickPos = EndBacktick->TokenText.find('`');
+ // Unknown token that's not actually a backtick, or a comment that doesn't
+ // contain a backtick.
+ if (CommentBacktickPos == StringRef::npos)
return false;
unsigned TokenCount = 0;
@@ -812,7 +820,14 @@
Tokens.resize(Tokens.size() - TokenCount);
Tokens.back()->Type = TT_TemplateString;
- const char *EndOffset = EndBacktick->TokenText.data() + 1;
+ const char *EndOffset =
+ EndBacktick->TokenText.data() + 1 + CommentBacktickPos;
+ if (CommentBacktickPos != 0) {
+ // If the backtick was not the first character (e.g. in a comment),
+ // re-lex after the backtick position.
+ SourceLocation Loc = EndBacktick->Tok.getLocation();
+ resetLexer(SourceMgr.getFileOffset(Loc) + CommentBacktickPos + 1);
+ }
Tokens.back()->TokenText =
StringRef(Tokens.back()->TokenText.data(),
EndOffset - Tokens.back()->TokenText.data());
@@ -1506,8 +1521,7 @@
LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
LangOpts.LineComment = 1;
- bool AlternativeOperators = Style.Language != FormatStyle::LK_JavaScript &&
- Style.Language != FormatStyle::LK_Java;
+ bool AlternativeOperators = Style.Language == FormatStyle::LK_Cpp;
LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
LangOpts.Bool = 1;
LangOpts.ObjC1 = 1;
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index cef7a63..bc14d4c 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -49,6 +49,7 @@
TT_InlineASMColon,
TT_JavaAnnotation,
TT_JsTypeColon,
+ TT_JsTypeOptionalQuestion,
TT_LambdaArrow,
TT_LambdaLSquare,
TT_LeadingJavaAnnotation,
@@ -549,6 +550,10 @@
kw_repeated = &IdentTable.get("repeated");
kw_required = &IdentTable.get("required");
kw_returns = &IdentTable.get("returns");
+
+ kw_signals = &IdentTable.get("signals");
+ kw_slots = &IdentTable.get("slots");
+ kw_qslots = &IdentTable.get("Q_SLOTS");
}
// Context sensitive keywords.
@@ -583,6 +588,11 @@
IdentifierInfo *kw_repeated;
IdentifierInfo *kw_required;
IdentifierInfo *kw_returns;
+
+ // QT keywords.
+ IdentifierInfo *kw_signals;
+ IdentifierInfo *kw_slots;
+ IdentifierInfo *kw_qslots;
};
} // namespace format
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index e0da80c..5b148ea 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -149,6 +149,8 @@
bool MightBeFunctionType = CurrentToken->is(tok::star);
bool HasMultipleLines = false;
bool HasMultipleParametersOnALine = false;
+ bool MightBeObjCForRangeLoop =
+ Left->Previous && Left->Previous->is(tok::kw_for);
while (CurrentToken) {
// LookForDecls is set when "if (" has been seen. Check for
// 'identifier' '*' 'identifier' followed by not '=' -- this
@@ -210,7 +212,8 @@
}
if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
return false;
- else if (CurrentToken->is(tok::l_brace))
+
+ if (CurrentToken->is(tok::l_brace))
Left->Type = TT_Unknown; // Not TT_ObjCBlockLParen
if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
!CurrentToken->Next->HasUnescapedNewline &&
@@ -219,6 +222,11 @@
if (CurrentToken->isOneOf(tok::kw_const, tok::kw_auto) ||
CurrentToken->isSimpleTypeSpecifier())
Contexts.back().IsExpression = false;
+ if (CurrentToken->isOneOf(tok::semi, tok::colon))
+ MightBeObjCForRangeLoop = false;
+ if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in))
+ CurrentToken->Type = TT_ObjCForIn;
+
FormatToken *Tok = CurrentToken;
if (!consumeToken())
return false;
@@ -342,7 +350,8 @@
Style.Language == FormatStyle::LK_Proto) &&
Previous->is(tok::identifier))
Previous->Type = TT_SelectorName;
- if (CurrentToken->is(tok::colon))
+ if (CurrentToken->is(tok::colon) ||
+ Style.Language == FormatStyle::LK_JavaScript)
Left->Type = TT_DictLiteral;
}
if (!consumeToken())
@@ -408,6 +417,16 @@
if (!Tok->Previous)
return false;
// Colons from ?: are handled in parseConditional().
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (Contexts.back().ColonIsForRangeExpr ||
+ (Contexts.size() == 1 &&
+ !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) ||
+ Contexts.back().ContextKind == tok::l_paren ||
+ Contexts.back().ContextKind == tok::l_square) {
+ Tok->Type = TT_JsTypeColon;
+ break;
+ }
+ }
if (Contexts.back().ColonIsDictLiteral) {
Tok->Type = TT_DictLiteral;
} else if (Contexts.back().ColonIsObjCMethodExpr ||
@@ -421,16 +440,12 @@
if (!Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName = Tok->Previous;
} else if (Contexts.back().ColonIsForRangeExpr) {
- Tok->Type = Style.Language == FormatStyle::LK_JavaScript
- ? TT_JsTypeColon
- : TT_RangeBasedForLoopColon;
+ Tok->Type = TT_RangeBasedForLoopColon;
} else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
Tok->Type = TT_BitFieldColon;
} else if (Contexts.size() == 1 &&
!Line.First->isOneOf(tok::kw_enum, tok::kw_case)) {
- if (Style.Language == FormatStyle::LK_JavaScript)
- Tok->Type = TT_JsTypeColon;
- else if (Tok->Previous->is(tok::r_paren))
+ if (Tok->Previous->is(tok::r_paren))
Tok->Type = TT_CtorInitializerColon;
else
Tok->Type = TT_InheritanceColon;
@@ -440,9 +455,7 @@
// the colon are passed as macro arguments.
Tok->Type = TT_ObjCMethodExpr;
} else if (Contexts.back().ContextKind == tok::l_paren) {
- Tok->Type = Style.Language == FormatStyle::LK_JavaScript
- ? TT_JsTypeColon
- : TT_InlineASMColon;
+ Tok->Type = TT_InlineASMColon;
}
break;
case tok::kw_if:
@@ -515,16 +528,20 @@
}
break;
case tok::question:
+ if (Style.Language == FormatStyle::LK_JavaScript && Tok->Next &&
+ Tok->Next->isOneOf(tok::colon, tok::semi, tok::r_paren,
+ tok::r_brace)) {
+ // Question marks before semicolons, colons, commas, etc. indicate
+ // optional types (fields, parameters), e.g.
+ // `function(x?: string, y?) {...}` or `class X {y?;}`
+ Tok->Type = TT_JsTypeOptionalQuestion;
+ break;
+ }
parseConditional();
break;
case tok::kw_template:
parseTemplateDeclaration();
break;
- case tok::identifier:
- if (Line.First->is(tok::kw_for) && Tok->is(Keywords.kw_in) &&
- Tok->Previous->isNot(tok::colon))
- Tok->Type = TT_ObjCForIn;
- break;
case tok::comma:
if (Contexts.back().FirstStartOfName && Contexts.size() == 1) {
Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
@@ -714,27 +731,22 @@
Context(tok::TokenKind ContextKind, unsigned BindingStrength,
bool IsExpression)
: ContextKind(ContextKind), BindingStrength(BindingStrength),
- LongestObjCSelectorName(0), ColonIsForRangeExpr(false),
- ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false),
- FirstObjCSelectorName(nullptr), FirstStartOfName(nullptr),
- IsExpression(IsExpression), CanBeExpression(true),
- InTemplateArgument(false), InCtorInitializer(false),
- CaretFound(false), IsForEachMacro(false) {}
+ IsExpression(IsExpression) {}
tok::TokenKind ContextKind;
unsigned BindingStrength;
- unsigned LongestObjCSelectorName;
- bool ColonIsForRangeExpr;
- bool ColonIsDictLiteral;
- bool ColonIsObjCMethodExpr;
- FormatToken *FirstObjCSelectorName;
- FormatToken *FirstStartOfName;
bool IsExpression;
- bool CanBeExpression;
- bool InTemplateArgument;
- bool InCtorInitializer;
- bool CaretFound;
- bool IsForEachMacro;
+ unsigned LongestObjCSelectorName = 0;
+ bool ColonIsForRangeExpr = false;
+ bool ColonIsDictLiteral = false;
+ bool ColonIsObjCMethodExpr = false;
+ FormatToken *FirstObjCSelectorName = nullptr;
+ FormatToken *FirstStartOfName = nullptr;
+ bool CanBeExpression = true;
+ bool InTemplateArgument = false;
+ bool InCtorInitializer = false;
+ bool CaretFound = false;
+ bool IsForEachMacro = false;
};
/// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime
@@ -1652,7 +1664,7 @@
if (Right.isOneOf(tok::semi, tok::comma))
return false;
if (Right.is(tok::less) &&
- (Left.isOneOf(tok::kw_template, tok::r_paren) ||
+ (Left.is(tok::kw_template) ||
(Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
return true;
if (Left.isOneOf(tok::exclaim, tok::tilde))
@@ -1773,7 +1785,7 @@
} else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Left.is(Keywords.kw_var))
return true;
- if (Right.is(TT_JsTypeColon))
+ if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion))
return false;
if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) &&
Line.First->isOneOf(Keywords.kw_import, tok::kw_export))
diff --git a/lib/Format/UnwrappedLineFormatter.h b/lib/Format/UnwrappedLineFormatter.h
index 9b83b27..7d5b011 100644
--- a/lib/Format/UnwrappedLineFormatter.h
+++ b/lib/Format/UnwrappedLineFormatter.h
@@ -80,7 +80,8 @@
if (Style.Language == FormatStyle::LK_Java ||
Style.Language == FormatStyle::LK_JavaScript)
return 0;
- if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier())
+ if (RootToken.isAccessSpecifier(false) ||
+ RootToken.isObjCAccessSpecifier() || RootToken.is(Keywords.kw_signals))
return Style.AccessModifierOffset;
return 0;
}
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 10ce0e9..905f9c1 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -68,7 +68,7 @@
Line.InPPDirective = true;
}
- ~ScopedMacroState() {
+ ~ScopedMacroState() override {
TokenSource = PreviousTokenSource;
ResetToken = Token;
Line.InPPDirective = false;
@@ -420,7 +420,7 @@
Line->Level = InitialLevel;
}
-static bool IsGoogScope(const UnwrappedLine &Line) {
+static bool isGoogScope(const UnwrappedLine &Line) {
// FIXME: Closure-library specific stuff should not be hard-coded but be
// configurable.
if (Line.Tokens.size() < 4)
@@ -456,12 +456,13 @@
nextToken();
{
bool GoogScope =
- Style.Language == FormatStyle::LK_JavaScript && IsGoogScope(*Line);
+ Style.Language == FormatStyle::LK_JavaScript && isGoogScope(*Line);
ScopedLineState LineState(*this);
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
/*MustBeDeclaration=*/false);
Line->Level += GoogScope ? 0 : 1;
parseLevel(/*HasOpeningBrace=*/true);
+ flushComments(isOnNewLine(*FormatTok));
Line->Level -= GoogScope ? 0 : 1;
}
nextToken();
@@ -752,6 +753,10 @@
parseJavaScriptEs6ImportExport();
return;
}
+ if (FormatTok->is(Keywords.kw_signals)) {
+ parseAccessSpecifier();
+ return;
+ }
// In all other cases, parse the declaration.
break;
default:
@@ -840,9 +845,8 @@
if (Line->Tokens.size() == 1 &&
// JS doesn't have macros, and within classes colons indicate fields,
// not labels.
- (Style.Language != FormatStyle::LK_JavaScript ||
- !Line->MustBeDeclaration)) {
- if (FormatTok->Tok.is(tok::colon)) {
+ Style.Language != FormatStyle::LK_JavaScript) {
+ if (FormatTok->Tok.is(tok::colon) && !Line->MustBeDeclaration) {
parseLabel();
return;
}
@@ -1035,6 +1039,17 @@
FormatTok->BlockKind = BK_BracedInit;
parseBracedList();
break;
+ case tok::r_paren:
+ // JavaScript can just have free standing methods and getters/setters in
+ // object literals. Detect them by a "{" following ")".
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ nextToken();
+ if (FormatTok->is(tok::l_brace))
+ parseChildBlock();
+ break;
+ }
+ nextToken();
+ break;
case tok::r_brace:
nextToken();
return !HasError;
@@ -1399,8 +1414,7 @@
void UnwrappedLineParser::parseAccessSpecifier() {
nextToken();
// Understand Qt's slots.
- if (FormatTok->is(tok::identifier) &&
- (FormatTok->TokenText == "slots" || FormatTok->TokenText == "Q_SLOTS"))
+ if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
nextToken();
// Otherwise, we don't know what it is, and we'd better keep the next token.
if (FormatTok->Tok.is(tok::colon))
@@ -1527,7 +1541,8 @@
// it is often token-pasted.
while (FormatTok->is(tok::identifier) || FormatTok->is(tok::coloncolon) ||
FormatTok->is(tok::hashhash) ||
- (Style.Language == FormatStyle::LK_Java &&
+ ((Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) &&
FormatTok->isOneOf(tok::period, tok::comma)))
nextToken();
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 692edc4..7226344 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -966,9 +966,9 @@
StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = nullptr;
- if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
- OutputFile, OS))
+ raw_ostream *OS = GeneratePCHAction::ComputeASTConsumerArguments(
+ CI, InFile, Sysroot, OutputFile);
+ if (!OS)
return nullptr;
if (!CI.getFrontendOpts().RelocatablePCH)
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index d909d52..7d2a09c 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -183,7 +183,7 @@
typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy;
IDMap IM;
- llvm::raw_fd_ostream& Out;
+ raw_pwrite_stream &Out;
Preprocessor& PP;
uint32_t idcount;
PTHMap PM;
@@ -236,8 +236,8 @@
Offset EmitCachedSpellings();
public:
- PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
- : Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
+ PTHWriter(raw_pwrite_stream &out, Preprocessor &pp)
+ : Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
PTHMap &getPM() { return PM; }
void GeneratePTH(const std::string &MainFile);
@@ -468,6 +468,16 @@
return SpellingsOff;
}
+static uint32_t swap32le(uint32_t X) {
+ return llvm::support::endian::byte_swap<uint32_t, llvm::support::little>(X);
+}
+
+static void pwrite32le(raw_pwrite_stream &OS, uint32_t Val, uint64_t &Off) {
+ uint32_t LEVal = swap32le(Val);
+ OS.pwrite(reinterpret_cast<const char *>(&LEVal), 4, Off);
+ Off += 4;
+}
+
void PTHWriter::GeneratePTH(const std::string &MainFile) {
// Generate the prologue.
Out << "cfe-pth" << '\0';
@@ -520,11 +530,11 @@
Offset FileTableOff = EmitFileTable();
// Finally, write the prologue.
- Out.seek(PrologueOffset);
- Emit32(IdTableOff.first);
- Emit32(IdTableOff.second);
- Emit32(FileTableOff);
- Emit32(SpellingOff);
+ uint64_t Off = PrologueOffset;
+ pwrite32le(Out, IdTableOff.first, Off);
+ pwrite32le(Out, IdTableOff.second, Off);
+ pwrite32le(Out, FileTableOff, Off);
+ pwrite32le(Out, SpellingOff, Off);
}
namespace {
@@ -537,7 +547,7 @@
PTHMap &PM;
public:
StatListener(PTHMap &pm) : PM(pm) {}
- ~StatListener() {}
+ ~StatListener() override {}
LookupResult getStat(const char *Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
@@ -559,8 +569,7 @@
};
} // end anonymous namespace
-
-void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
+void clang::CacheTokens(Preprocessor &PP, raw_pwrite_stream *OS) {
// Get the name of the main file.
const SourceManager &SrcMgr = PP.getSourceManager();
const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID());
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index be99b78..f3677f8 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -27,7 +27,7 @@
namespace {
class ChainedIncludesSource : public ExternalSemaSource {
public:
- virtual ~ChainedIncludesSource();
+ ~ChainedIncludesSource() override;
ExternalSemaSource &getFinalReader() const { return *FinalReader; }
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 1c5b322..fdaf7e2 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -329,7 +329,8 @@
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
- PP->getHeaderSearchInfo().setModuleCachePath(getSpecificModuleCachePath());
+ if (PP->getLangOpts().Modules)
+ PP->getHeaderSearchInfo().setModuleCachePath(getSpecificModuleCachePath());
// Handle generating dependencies, if requested.
const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
@@ -517,42 +518,43 @@
// Output Files
-void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
+void CompilerInstance::addOutputFile(OutputFile &&OutFile) {
assert(OutFile.OS && "Attempt to add empty stream to output list!");
- OutputFiles.push_back(OutFile);
+ OutputFiles.push_back(std::move(OutFile));
}
void CompilerInstance::clearOutputFiles(bool EraseFiles) {
- for (std::list<OutputFile>::iterator
- it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
- delete it->OS;
- if (!it->TempFilename.empty()) {
+ for (OutputFile &OF : OutputFiles) {
+ // Manually close the stream before we rename it.
+ OF.OS.reset();
+
+ if (!OF.TempFilename.empty()) {
if (EraseFiles) {
- llvm::sys::fs::remove(it->TempFilename);
+ llvm::sys::fs::remove(OF.TempFilename);
} else {
- SmallString<128> NewOutFile(it->Filename);
+ SmallString<128> NewOutFile(OF.Filename);
// If '-working-directory' was passed, the output filename should be
// relative to that.
FileMgr->FixupRelativePath(NewOutFile);
if (std::error_code ec =
- llvm::sys::fs::rename(it->TempFilename, NewOutFile)) {
+ llvm::sys::fs::rename(OF.TempFilename, NewOutFile)) {
getDiagnostics().Report(diag::err_unable_to_rename_temp)
- << it->TempFilename << it->Filename << ec.message();
+ << OF.TempFilename << OF.Filename << ec.message();
- llvm::sys::fs::remove(it->TempFilename);
+ llvm::sys::fs::remove(OF.TempFilename);
}
}
- } else if (!it->Filename.empty() && EraseFiles)
- llvm::sys::fs::remove(it->Filename);
+ } else if (!OF.Filename.empty() && EraseFiles)
+ llvm::sys::fs::remove(OF.Filename);
}
OutputFiles.clear();
+ NonSeekStream.reset();
}
-llvm::raw_fd_ostream *
-CompilerInstance::createDefaultOutputFile(bool Binary,
- StringRef InFile,
+raw_pwrite_stream *
+CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile,
StringRef Extension) {
return createOutputFile(getFrontendOpts().OutputFile, Binary,
/*RemoveFileOnSignal=*/true, InFile, Extension,
@@ -560,21 +562,20 @@
}
llvm::raw_null_ostream *CompilerInstance::createNullOutputFile() {
- llvm::raw_null_ostream *OS = new llvm::raw_null_ostream();
- addOutputFile(OutputFile("", "", OS));
- return OS;
+ auto OS = llvm::make_unique<llvm::raw_null_ostream>();
+ llvm::raw_null_ostream *Ret = OS.get();
+ addOutputFile(OutputFile("", "", std::move(OS)));
+ return Ret;
}
-llvm::raw_fd_ostream *
-CompilerInstance::createOutputFile(StringRef OutputPath,
- bool Binary, bool RemoveFileOnSignal,
- StringRef InFile,
- StringRef Extension,
- bool UseTemporary,
+raw_pwrite_stream *
+CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary,
+ bool RemoveFileOnSignal, StringRef InFile,
+ StringRef Extension, bool UseTemporary,
bool CreateMissingDirectories) {
std::string OutputPathName, TempPathName;
std::error_code EC;
- llvm::raw_fd_ostream *OS = createOutputFile(
+ std::unique_ptr<raw_pwrite_stream> OS = createOutputFile(
OutputPath, EC, Binary, RemoveFileOnSignal, InFile, Extension,
UseTemporary, CreateMissingDirectories, &OutputPathName, &TempPathName);
if (!OS) {
@@ -583,15 +584,16 @@
return nullptr;
}
+ raw_pwrite_stream *Ret = OS.get();
// Add the output file -- but don't try to remove "-", since this means we are
// using stdin.
addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
- TempPathName, OS));
+ TempPathName, std::move(OS)));
- return OS;
+ return Ret;
}
-llvm::raw_fd_ostream *CompilerInstance::createOutputFile(
+std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile(
StringRef OutputPath, std::error_code &Error, bool Binary,
bool RemoveFileOnSignal, StringRef InFile, StringRef Extension,
bool UseTemporary, bool CreateMissingDirectories,
@@ -679,7 +681,13 @@
if (TempPathName)
*TempPathName = TempFile;
- return OS.release();
+ if (!Binary || OS->supportsSeeking())
+ return std::move(OS);
+
+ auto B = llvm::make_unique<llvm::buffer_ostream>(*OS);
+ assert(!NonSeekStream);
+ NonSeekStream = std::move(OS);
+ return std::move(B);
}
// Initialization Utilities
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 5d2cdae..da1a088 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -405,6 +405,10 @@
// Default Dwarf version is 4 if we are generating debug information.
Opts.DwarfVersion = 4;
+ if (const Arg *A =
+ Args.getLastArg(OPT_emit_llvm_uselists, OPT_no_emit_llvm_uselists))
+ Opts.EmitLLVMUseLists = A->getOption().getID() == OPT_emit_llvm_uselists;
+
Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
@@ -451,10 +455,10 @@
Args.hasArg(OPT_cl_finite_math_only) ||
Args.hasArg(OPT_cl_fast_relaxed_math));
Opts.NoSignedZeros = Args.hasArg(OPT_fno_signed_zeros);
+ Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option);
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
- Opts.NoGlobalMerge = Args.hasArg(OPT_mno_global_merge);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks);
@@ -1371,6 +1375,9 @@
if (Args.hasArg(OPT_fcuda_allow_host_calls_from_host_device))
Opts.CUDAAllowHostCallsFromHostDevice = 1;
+ if (Args.hasArg(OPT_fcuda_disable_target_call_checks))
+ Opts.CUDADisableTargetCallChecks = 1;
+
if (Opts.ObjC1) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
StringRef value = arg->getValue();
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index fd251ac..8390624 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -44,7 +44,7 @@
explicit DelegatingDeserializationListener(
ASTDeserializationListener *Previous, bool DeletePrevious)
: Previous(Previous), DeletePrevious(DeletePrevious) {}
- virtual ~DelegatingDeserializationListener() {
+ ~DelegatingDeserializationListener() override {
if (DeletePrevious)
delete Previous;
}
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index bc11929..0defe5c 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -79,8 +79,9 @@
GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = nullptr;
- if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
+ raw_ostream *OS =
+ ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile);
+ if (!OS)
return nullptr;
if (!CI.getFrontendOpts().RelocatablePCH)
@@ -89,28 +90,27 @@
nullptr, Sysroot, OS);
}
-bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
- StringRef InFile,
- std::string &Sysroot,
- std::string &OutputFile,
- raw_ostream *&OS) {
+raw_ostream *GeneratePCHAction::ComputeASTConsumerArguments(
+ CompilerInstance &CI, StringRef InFile, std::string &Sysroot,
+ std::string &OutputFile) {
Sysroot = CI.getHeaderSearchOpts().Sysroot;
if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
- return true;
+ return nullptr;
}
// We use createOutputFile here because this is exposed via libclang, and we
// must disable the RemoveFileOnSignal behavior.
// We use a temporary to avoid race conditions.
- OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
- /*RemoveFileOnSignal=*/false, InFile,
- /*Extension=*/"", /*useTemporary=*/true);
+ raw_ostream *OS =
+ CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
+ /*RemoveFileOnSignal=*/false, InFile,
+ /*Extension=*/"", /*useTemporary=*/true);
if (!OS)
- return true;
+ return nullptr;
OutputFile = CI.getFrontendOpts().OutputFile;
- return false;
+ return OS;
}
std::unique_ptr<ASTConsumer>
@@ -118,8 +118,9 @@
StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = nullptr;
- if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
+ raw_ostream *OS =
+ ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile);
+ if (!OS)
return nullptr;
return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile,
@@ -355,11 +356,9 @@
return true;
}
-bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
- StringRef InFile,
- std::string &Sysroot,
- std::string &OutputFile,
- raw_ostream *&OS) {
+raw_ostream *GenerateModuleAction::ComputeASTConsumerArguments(
+ CompilerInstance &CI, StringRef InFile, std::string &Sysroot,
+ std::string &OutputFile) {
// If no output file was provided, figure out where this module would go
// in the module cache.
if (CI.getFrontendOpts().OutputFile.empty()) {
@@ -368,19 +367,20 @@
HS.getModuleFileName(CI.getLangOpts().CurrentModule,
ModuleMapForUniquing->getName());
}
-
+
// We use createOutputFile here because this is exposed via libclang, and we
// must disable the RemoveFileOnSignal behavior.
// We use a temporary to avoid race conditions.
- OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
- /*RemoveFileOnSignal=*/false, InFile,
- /*Extension=*/"", /*useTemporary=*/true,
- /*CreateMissingDirectories=*/true);
+ raw_ostream *OS =
+ CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
+ /*RemoveFileOnSignal=*/false, InFile,
+ /*Extension=*/"", /*useTemporary=*/true,
+ /*CreateMissingDirectories=*/true);
if (!OS)
- return true;
-
+ return nullptr;
+
OutputFile = CI.getFrontendOpts().OutputFile;
- return false;
+ return OS;
}
std::unique_ptr<ASTConsumer>
@@ -480,9 +480,8 @@
return false;
}
- virtual bool
- ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
- bool Complain) override {
+ bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
+ bool Complain) override {
Out.indent(2) << "Diagnostic options:\n";
#define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name);
#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
@@ -600,15 +599,9 @@
void GeneratePTHAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
- if (CI.getFrontendOpts().OutputFile.empty() ||
- CI.getFrontendOpts().OutputFile == "-") {
- // FIXME: Don't fail this way.
- // FIXME: Verify that we can actually seek in the given file.
- llvm::report_fatal_error("PTH requires a seekable file for output!");
- }
- llvm::raw_fd_ostream *OS =
- CI.createDefaultOutputFile(true, getCurrentFile());
- if (!OS) return;
+ raw_pwrite_stream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+ if (!OS)
+ return;
CacheTokens(CI.getPreprocessor(), OS);
}
diff --git a/lib/Frontend/HeaderIncludeGen.cpp b/lib/Frontend/HeaderIncludeGen.cpp
index 2701194..5732e5b 100644
--- a/lib/Frontend/HeaderIncludeGen.cpp
+++ b/lib/Frontend/HeaderIncludeGen.cpp
@@ -35,7 +35,7 @@
OwnsOutputFile(OwnsOutputFile_), ShowAllHeaders(ShowAllHeaders_),
ShowDepth(ShowDepth_), MSStyle(MSStyle_) {}
- ~HeaderIncludesCallback() {
+ ~HeaderIncludesCallback() override {
if (OwnsOutputFile)
delete OutputFile;
}
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 9b4f7e5..2bd999e 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -232,6 +232,7 @@
case llvm::Triple::NetBSD:
case llvm::Triple::OpenBSD:
case llvm::Triple::Bitrig:
+ case llvm::Triple::NaCl:
break;
default:
// FIXME: temporary hack: hard-coded paths.
@@ -352,6 +353,7 @@
switch (os) {
case llvm::Triple::CloudABI:
case llvm::Triple::RTEMS:
+ case llvm::Triple::NaCl:
break;
default:
AddPath("/usr/include", ExternCSystem, false);
diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 12c57cd..e13cdb3 100644
--- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -243,8 +243,8 @@
RewriteModernObjC(std::string inFile, raw_ostream *OS,
DiagnosticsEngine &D, const LangOptions &LOpts,
bool silenceMacroWarn, bool LineInfo);
-
- ~RewriteModernObjC() {}
+
+ ~RewriteModernObjC() override {}
void HandleTranslationUnit(ASTContext &C) override;
@@ -886,15 +886,15 @@
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get(D->getNameAsString()),
- IvarT, nullptr,
- /*BitWidth=*/nullptr, /*Mutable=*/true,
- ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
- IvarT = Context->getDecltypeType(ME, ME->getType());
- }
- }
+ IvarT, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
+ ICIS_NoInit);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
+ IvarT = Context->getDecltypeType(ME, ME->getType());
+ }
+ }
convertObjCTypeToCStyleType(IvarT);
QualType castT = Context->getPointerType(IvarT);
std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));
@@ -2689,7 +2689,7 @@
MsgExprs.push_back(subExpr);
SmallVector<QualType, 4> ArgTypes;
- ArgTypes.push_back(Context->getObjCIdType());
+ ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
for (const auto PI : BoxingMethod->parameters())
ArgTypes.push_back(PI->getType());
@@ -2764,15 +2764,15 @@
FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("arr"),
- Context->getPointerType(Context->VoidPtrTy),
- nullptr, /*BitWidth=*/nullptr,
- /*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ArrayLiteralME = new (Context)
- MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD,
- SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
- QualType ConstIdT = Context->getObjCIdType().withConst();
- CStyleCastExpr * ArrayLiteralObjects =
- NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(Context->VoidPtrTy),
+ nullptr, /*BitWidth=*/nullptr,
+ /*Mutable=*/true, ICIS_NoInit);
+ MemberExpr *ArrayLiteralME = new (Context)
+ MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
+ QualType ConstIdT = Context->getObjCIdType().withConst();
+ CStyleCastExpr * ArrayLiteralObjects =
+ NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(ConstIdT),
CK_BitCast,
ArrayLiteralME);
@@ -2816,7 +2816,7 @@
SmallVector<QualType, 4> ArgTypes;
- ArgTypes.push_back(Context->getObjCIdType());
+ ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
for (const auto *PI : ArrayMethod->params())
ArgTypes.push_back(PI->getType());
@@ -2899,30 +2899,30 @@
FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("arr"),
- Context->getPointerType(Context->VoidPtrTy),
- nullptr, /*BitWidth=*/nullptr,
- /*Mutable=*/true, ICIS_NoInit);
- MemberExpr *DictLiteralValueME = new (Context)
- MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD,
- SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
- QualType ConstIdT = Context->getObjCIdType().withConst();
- CStyleCastExpr * DictValueObjects =
- NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(Context->VoidPtrTy),
+ nullptr, /*BitWidth=*/nullptr,
+ /*Mutable=*/true, ICIS_NoInit);
+ MemberExpr *DictLiteralValueME = new (Context)
+ MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
+ QualType ConstIdT = Context->getObjCIdType().withConst();
+ CStyleCastExpr * DictValueObjects =
+ NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(ConstIdT),
CK_BitCast,
DictLiteralValueME);
// (const id <NSCopying> [])keys
- Expr *NSKeyCallExpr =
- new (Context) CallExpr(*Context, NSDictDRE, KeyExprs,
- NSDictFType, VK_LValue, SourceLocation());
-
- MemberExpr *DictLiteralKeyME = new (Context)
- MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD,
- SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
-
- CStyleCastExpr * DictKeyObjects =
- NoTypeInfoCStyleCastExpr(Context,
- Context->getPointerType(ConstIdT),
+ Expr *NSKeyCallExpr =
+ new (Context) CallExpr(*Context, NSDictDRE, KeyExprs,
+ NSDictFType, VK_LValue, SourceLocation());
+
+ MemberExpr *DictLiteralKeyME = new (Context)
+ MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
+
+ CStyleCastExpr * DictKeyObjects =
+ NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(ConstIdT),
CK_BitCast,
DictLiteralKeyME);
@@ -2969,7 +2969,7 @@
SmallVector<QualType, 8> ArgTypes;
- ArgTypes.push_back(Context->getObjCIdType());
+ ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
for (const auto *PI : DictMethod->params()) {
QualType T = PI->getType();
@@ -3225,15 +3225,15 @@
FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("s"),
- returnType, nullptr,
- /*BitWidth=*/nullptr,
- /*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(STCE, false, SourceLocation(), FieldD, SourceLocation(),
- FieldD->getType(), VK_LValue, OK_Ordinary);
-
- return ME;
-}
+ returnType, nullptr,
+ /*BitWidth=*/nullptr,
+ /*Mutable=*/true, ICIS_NoInit);
+ MemberExpr *ME = new (Context)
+ MemberExpr(STCE, false, SourceLocation(), FieldD, SourceLocation(),
+ FieldD->getType(), VK_LValue, OK_Ordinary);
+
+ return ME;
+}
Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation StartLoc,
@@ -4723,16 +4723,16 @@
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("FuncPtr"),
- Context->VoidPtrTy, nullptr,
- /*BitWidth=*/nullptr, /*Mutable=*/true,
- ICIS_NoInit);
- MemberExpr *ME =
- new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
-
- CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
- CK_BitCast, ME);
- PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
+ ICIS_NoInit);
+ MemberExpr *ME =
+ new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
+
+ CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
+ CK_BitCast, ME);
+ PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
SmallVector<Expr*, 8> BlkExprs;
// Add the implicit argument.
@@ -4771,26 +4771,26 @@
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("__forwarding"),
- Context->VoidPtrTy, nullptr,
- /*BitWidth=*/nullptr, /*Mutable=*/true,
- ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
-
- StringRef Name = VD->getName();
- FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
+ ICIS_NoInit);
+ MemberExpr *ME = new (Context)
+ MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
+
+ StringRef Name = VD->getName();
+ FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
&Context->Idents.get(Name),
- Context->VoidPtrTy, nullptr,
- /*BitWidth=*/nullptr, /*Mutable=*/true,
- ICIS_NoInit);
- ME =
- new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
- DeclRefExp->getType(), VK_LValue, OK_Ordinary);
-
- // Need parens to enforce precedence.
- ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
- DeclRefExp->getExprLoc(),
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
+ ICIS_NoInit);
+ ME =
+ new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
+ DeclRefExp->getType(), VK_LValue, OK_Ordinary);
+
+ // Need parens to enforce precedence.
+ ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
+ DeclRefExp->getExprLoc(),
ME);
ReplaceStmt(DeclRefExp, PE);
return PE;
@@ -7682,15 +7682,15 @@
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get(D->getNameAsString()),
- IvarT, nullptr,
- /*BitWidth=*/nullptr,
- /*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
- IvarT = Context->getDecltypeType(ME, ME->getType());
- }
- }
+ IvarT, nullptr,
+ /*BitWidth=*/nullptr,
+ /*Mutable=*/true, ICIS_NoInit);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
+ IvarT = Context->getDecltypeType(ME, ME->getType());
+ }
+ }
convertObjCTypeToCStyleType(IvarT);
QualType castT = Context->getPointerType(IvarT);
@@ -7711,15 +7711,15 @@
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get(D->getNameAsString()),
- D->getType(), nullptr,
- /*BitWidth=*/D->getBitWidth(),
- /*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(PE, /*isArrow*/ false, SourceLocation(), FD,
- SourceLocation(), FD->getType(), VK_LValue, OK_Ordinary);
- Replacement = ME;
-
- }
+ D->getType(), nullptr,
+ /*BitWidth=*/D->getBitWidth(),
+ /*Mutable=*/true, ICIS_NoInit);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, /*isArrow*/ false, SourceLocation(), FD,
+ SourceLocation(), FD->getType(), VK_LValue, OK_Ordinary);
+ Replacement = ME;
+
+ }
else
Replacement = PE;
}
diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp
index 5802ba7..170c209 100644
--- a/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -193,7 +193,7 @@
DiagnosticsEngine &D, const LangOptions &LOpts,
bool silenceMacroWarn);
- ~RewriteObjC() {}
+ ~RewriteObjC() override {}
void HandleTranslationUnit(ASTContext &C) override;
@@ -511,8 +511,8 @@
bool silenceMacroWarn) : RewriteObjC(inFile, OS,
D, LOpts,
silenceMacroWarn) {}
-
- ~RewriteObjCFragileABI() {}
+
+ ~RewriteObjCFragileABI() override {}
void Initialize(ASTContext &context) override;
// Rewriting metadata
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 5dcacfa..d31b12e 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -61,8 +61,8 @@
DiagnosticOptions *DiagOpts)
: DiagnosticNoteRenderer(LangOpts, DiagOpts), Writer(Writer) {}
- virtual ~SDiagsRenderer() {}
-
+ ~SDiagsRenderer() override {}
+
protected:
void emitDiagnosticMessage(SourceLocation Loc,
PresumedLoc PLoc,
@@ -158,7 +158,7 @@
EmitPreamble();
}
- ~SDiagsWriter() {}
+ ~SDiagsWriter() override {}
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override;
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 3ff6b18..910e394 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -58,9 +58,9 @@
/// \brief Hook into the preprocessor and update the list of parsed
/// files when the preprocessor indicates a new file is entered.
- virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
- SrcMgr::CharacteristicKind FileType,
- FileID PrevFID) {
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override {
Verify.UpdateParsedFileStatus(SM, SM.getFileID(Loc),
VerifyDiagnosticConsumer::IsParsed);
}
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index 080550f..5429092 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -18,6 +18,8 @@
float.h
fma4intrin.h
fmaintrin.h
+ htmintrin.h
+ htmxlintrin.h
ia32intrin.h
immintrin.h
Intrin.h
@@ -34,6 +36,7 @@
prfchwintrin.h
rdseedintrin.h
rtmintrin.h
+ s390intrin.h
shaintrin.h
smmintrin.h
stdalign.h
diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h
index 7485bdd..949195b 100644
--- a/lib/Headers/avx2intrin.h
+++ b/lib/Headers/avx2intrin.h
@@ -160,7 +160,7 @@
#define _mm256_blend_epi16(V1, V2, M) __extension__ ({ \
__m256i __V1 = (V1); \
__m256i __V2 = (V2); \
- (__m256d)__builtin_shufflevector((__v16hi)__V1, (__v16hi)__V2, \
+ (__m256i)__builtin_shufflevector((__v16hi)__V1, (__v16hi)__V2, \
(((M) & 0x01) ? 16 : 0), \
(((M) & 0x02) ? 17 : 1), \
(((M) & 0x04) ? 18 : 2), \
diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h
index c6d46cb..72af281 100644
--- a/lib/Headers/avx512fintrin.h
+++ b/lib/Headers/avx512fintrin.h
@@ -162,6 +162,168 @@
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3);
}
+/* Bitwise operators */
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_and_epi32(__m512i __a, __m512i __b)
+{
+ return __a & __b;
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_mask_and_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pandd512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si) __src,
+ (__mmask16) __k);
+}
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_maskz_and_epi32(__mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pandd512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __k);
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_and_epi64(__m512i __a, __m512i __b)
+{
+ return __a & __b;
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_mask_and_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pandq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di) __src,
+ (__mmask8) __k);
+}
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_maskz_and_epi64(__mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pandq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __k);
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_or_epi32(__m512i __a, __m512i __b)
+{
+ return __a | __b;
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_mask_or_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pord512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si) __src,
+ (__mmask16) __k);
+}
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_maskz_or_epi32(__mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pord512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __k);
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_or_epi64(__m512i __a, __m512i __b)
+{
+ return __a | __b;
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_mask_or_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_porq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di) __src,
+ (__mmask8) __k);
+}
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_maskz_or_epi64(__mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_porq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __k);
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_xor_epi32(__m512i __a, __m512i __b)
+{
+ return __a ^ __b;
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_mask_xor_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pxord512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si) __src,
+ (__mmask16) __k);
+}
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_maskz_xor_epi32(__mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pxord512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __k);
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_xor_epi64(__m512i __a, __m512i __b)
+{
+ return __a ^ __b;
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_mask_xor_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pxorq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di) __src,
+ (__mmask8) __k);
+}
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_maskz_xor_epi64(__mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pxorq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __k);
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_and_si512(__m512i __a, __m512i __b)
+{
+ return __a & __b;
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_or_si512(__m512i __a, __m512i __b)
+{
+ return __a | __b;
+}
+
+static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))
+_mm512_xor_si512(__m512i __a, __m512i __b)
+{
+ return __a ^ __b;
+}
/* Arithmetic */
static __inline __m512d __attribute__((__always_inline__, __nodebug__))
diff --git a/lib/Headers/htmintrin.h b/lib/Headers/htmintrin.h
index 4598ee0..0088c7c 100644
--- a/lib/Headers/htmintrin.h
+++ b/lib/Headers/htmintrin.h
@@ -128,4 +128,99 @@
#endif /* __powerpc */
+#ifdef __s390__
+
+/* Condition codes generated by tbegin */
+#define _HTM_TBEGIN_STARTED 0
+#define _HTM_TBEGIN_INDETERMINATE 1
+#define _HTM_TBEGIN_TRANSIENT 2
+#define _HTM_TBEGIN_PERSISTENT 3
+
+/* The abort codes below this threshold are reserved for machine use. */
+#define _HTM_FIRST_USER_ABORT_CODE 256
+
+/* The transaction diagnostic block is it is defined in the Principles
+ of Operation chapter 5-91. */
+
+struct __htm_tdb {
+ unsigned char format; /* 0 */
+ unsigned char flags;
+ unsigned char reserved1[4];
+ unsigned short nesting_depth;
+ unsigned long long abort_code; /* 8 */
+ unsigned long long conflict_token; /* 16 */
+ unsigned long long atia; /* 24 */
+ unsigned char eaid; /* 32 */
+ unsigned char dxc;
+ unsigned char reserved2[2];
+ unsigned int program_int_id;
+ unsigned long long exception_id; /* 40 */
+ unsigned long long bea; /* 48 */
+ unsigned char reserved3[72]; /* 56 */
+ unsigned long long gprs[16]; /* 128 */
+} __attribute__((__packed__, __aligned__ (8)));
+
+
+/* Helper intrinsics to retry tbegin in case of transient failure. */
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+__builtin_tbegin_retry_null (int retry)
+{
+ int cc, i = 0;
+
+ while ((cc = __builtin_tbegin(0)) == _HTM_TBEGIN_TRANSIENT
+ && i++ < retry)
+ __builtin_tx_assist(i);
+
+ return cc;
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+__builtin_tbegin_retry_tdb (void *tdb, int retry)
+{
+ int cc, i = 0;
+
+ while ((cc = __builtin_tbegin(tdb)) == _HTM_TBEGIN_TRANSIENT
+ && i++ < retry)
+ __builtin_tx_assist(i);
+
+ return cc;
+}
+
+#define __builtin_tbegin_retry(tdb, retry) \
+ (__builtin_constant_p(tdb == 0) && tdb == 0 ? \
+ __builtin_tbegin_retry_null(retry) : \
+ __builtin_tbegin_retry_tdb(tdb, retry))
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+__builtin_tbegin_retry_nofloat_null (int retry)
+{
+ int cc, i = 0;
+
+ while ((cc = __builtin_tbegin_nofloat(0)) == _HTM_TBEGIN_TRANSIENT
+ && i++ < retry)
+ __builtin_tx_assist(i);
+
+ return cc;
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+__builtin_tbegin_retry_nofloat_tdb (void *tdb, int retry)
+{
+ int cc, i = 0;
+
+ while ((cc = __builtin_tbegin_nofloat(tdb)) == _HTM_TBEGIN_TRANSIENT
+ && i++ < retry)
+ __builtin_tx_assist(i);
+
+ return cc;
+}
+
+#define __builtin_tbegin_retry_nofloat(tdb, retry) \
+ (__builtin_constant_p(tdb == 0) && tdb == 0 ? \
+ __builtin_tbegin_retry_nofloat_null(retry) : \
+ __builtin_tbegin_retry_nofloat_tdb(tdb, retry))
+
+#endif /* __s390__ */
+
#endif /* __HTMINTRIN_H */
diff --git a/lib/Headers/htmxlintrin.h b/lib/Headers/htmxlintrin.h
index 8791afe..30f524d 100644
--- a/lib/Headers/htmxlintrin.h
+++ b/lib/Headers/htmxlintrin.h
@@ -212,4 +212,152 @@
#endif /* __powerpc__ */
+#ifdef __s390__
+
+#include <stdint.h>
+
+/* These intrinsics are being made available for compatibility with
+ the IBM XL compiler. For documentation please see the "z/OS XL
+ C/C++ Programming Guide" publically available on the web. */
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_simple_begin ()
+{
+ return __builtin_tbegin_nofloat (0);
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_begin (void* const tdb)
+{
+ return __builtin_tbegin_nofloat (tdb);
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_end ()
+{
+ return __builtin_tend ();
+}
+
+static __inline void __attribute__((__always_inline__))
+__TM_abort ()
+{
+ return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+__TM_named_abort (unsigned char const code)
+{
+ return __builtin_tabort ((int)_HTM_FIRST_USER_ABORT_CODE + code);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+__TM_non_transactional_store (void* const addr, long long const value)
+{
+ __builtin_non_tx_store ((uint64_t*)addr, (uint64_t)value);
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_nesting_depth (void* const tdb_ptr)
+{
+ int depth = __builtin_tx_nesting_depth ();
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (depth != 0)
+ return depth;
+
+ if (tdb->format != 1)
+ return 0;
+ return tdb->nesting_depth;
+}
+
+/* Transaction failure diagnostics */
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_user_abort (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (tdb->format != 1)
+ return 0;
+
+ return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE);
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_named_user_abort (void* const tdb_ptr, unsigned char* code)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (tdb->format != 1)
+ return 0;
+
+ if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE)
+ {
+ *code = tdb->abort_code - _HTM_FIRST_USER_ABORT_CODE;
+ return 1;
+ }
+ return 0;
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_illegal (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 4 /* unfiltered program interruption */
+ || tdb->abort_code == 11 /* restricted instruction */));
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_footprint_exceeded (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 7 /* fetch overflow */
+ || tdb->abort_code == 8 /* store overflow */));
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_nested_too_deep (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return tdb->format == 1 && tdb->abort_code == 13; /* depth exceeded */
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_conflict (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 9 /* fetch conflict */
+ || tdb->abort_code == 10 /* store conflict */));
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_failure_persistent (long const result)
+{
+ return result == _HTM_TBEGIN_PERSISTENT;
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_failure_address (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+ return tdb->atia;
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_failure_code (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return tdb->abort_code;
+}
+
+#endif /* __s390__ */
+
#endif /* __HTMXLINTRIN_H */
diff --git a/lib/Headers/module.modulemap b/lib/Headers/module.modulemap
index 062464e..bb2ca95 100644
--- a/lib/Headers/module.modulemap
+++ b/lib/Headers/module.modulemap
@@ -169,6 +169,19 @@
header "__wmmintrin_pclmul.h"
}
}
+
+ explicit module systemz {
+ requires systemz
+ export *
+
+ header "s390intrin.h"
+
+ explicit module htm {
+ requires htm
+ header "htmintrin.h"
+ header "htmxlintrin.h"
+ }
+ }
}
module _Builtin_stddef_max_align_t [system] [extern_c] {
diff --git a/lib/Headers/s390intrin.h b/lib/Headers/s390intrin.h
new file mode 100644
index 0000000..b209895
--- /dev/null
+++ b/lib/Headers/s390intrin.h
@@ -0,0 +1,35 @@
+/*===---- s390intrin.h - SystemZ intrinsics --------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __S390INTRIN_H
+#define __S390INTRIN_H
+
+#ifndef __s390__
+#error "<s390intrin.h> is for s390 only"
+#endif
+
+#ifdef __HTM__
+#include <htmintrin.h>
+#endif
+
+#endif /* __S390INTRIN_H*/
diff --git a/lib/Index/SimpleFormatContext.h b/lib/Index/SimpleFormatContext.h
index 080a4ad..b884214 100644
--- a/lib/Index/SimpleFormatContext.h
+++ b/lib/Index/SimpleFormatContext.h
@@ -44,8 +44,6 @@
Diagnostics->setClient(new IgnoringDiagConsumer, true);
}
- ~SimpleFormatContext() { }
-
FileID createInMemoryFile(StringRef Name, StringRef Content) {
std::unique_ptr<llvm::MemoryBuffer> Source =
llvm::MemoryBuffer::getMemBuffer(Content);
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index af3e27f..aed9164 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -597,7 +597,8 @@
if (isFloat) break; // LF invalid.
// Check for long long. The L's need to be adjacent and the same case.
- if (s+1 != ThisTokEnd && s[1] == s[0]) {
+ if (s[1] == s[0]) {
+ assert(s + 1 < ThisTokEnd && "didn't maximally munch?");
if (isFPConstant) break; // long long invalid for floats.
isLongLong = true;
++s; // Eat both of them.
@@ -611,54 +612,45 @@
if (isLong || isLongLong || MicrosoftInteger)
break;
- // Allow i8, i16, i32, i64, and i128.
- if (s + 1 != ThisTokEnd) {
+ if (!isFPConstant) {
+ // Allow i8, i16, i32, i64, and i128.
switch (s[1]) {
- case '8':
- if (isFPConstant) break;
- s += 2; // i8 suffix
- MicrosoftInteger = 8;
- break;
- case '1':
- if (isFPConstant) break;
- if (s + 2 == ThisTokEnd) break;
- if (s[2] == '6') {
- s += 3; // i16 suffix
- MicrosoftInteger = 16;
- }
- else if (s[2] == '2') {
- if (s + 3 == ThisTokEnd) break;
- if (s[3] == '8') {
- s += 4; // i128 suffix
- MicrosoftInteger = 128;
- }
- }
- break;
- case '3':
- if (isFPConstant) break;
- if (s + 2 == ThisTokEnd) break;
- if (s[2] == '2') {
- s += 3; // i32 suffix
- MicrosoftInteger = 32;
- }
- break;
- case '6':
- if (isFPConstant) break;
- if (s + 2 == ThisTokEnd) break;
- if (s[2] == '4') {
- s += 3; // i64 suffix
- MicrosoftInteger = 64;
- }
- break;
- default:
- break;
- }
- if (MicrosoftInteger)
+ case '8':
+ s += 2; // i8 suffix
+ MicrosoftInteger = 8;
break;
+ case '1':
+ if (s[2] == '6') {
+ s += 3; // i16 suffix
+ MicrosoftInteger = 16;
+ } else if (s[2] == '2' && s[3] == '8') {
+ s += 4; // i128 suffix
+ MicrosoftInteger = 128;
+ }
+ break;
+ case '3':
+ if (s[2] == '2') {
+ s += 3; // i32 suffix
+ MicrosoftInteger = 32;
+ }
+ break;
+ case '6':
+ if (s[2] == '4') {
+ s += 3; // i64 suffix
+ MicrosoftInteger = 64;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (MicrosoftInteger) {
+ assert(s <= ThisTokEnd && "didn't maximally munch?");
+ break;
}
}
// "i", "if", and "il" are user-defined suffixes in C++1y.
- if (PP.getLangOpts().CPlusPlus14 && *s == 'i')
+ if (*s == 'i' && PP.getLangOpts().CPlusPlus14)
break;
// fall through.
case 'j':
@@ -756,11 +748,11 @@
s++;
int c1 = s[0];
- int c2 = s[1];
// Handle a hex number like 0x1234.
- if ((c1 == 'x' || c1 == 'X') && (isHexDigit(c2) || c2 == '.')) {
+ if ((c1 == 'x' || c1 == 'X') && (isHexDigit(s[1]) || s[1] == '.')) {
s++;
+ assert(s < ThisTokEnd && "didn't maximally munch?");
radix = 16;
DigitsBegin = s;
s = SkipHexDigits(s);
@@ -812,7 +804,7 @@
}
// Handle simple binary numbers 0b01010
- if ((c1 == 'b' || c1 == 'B') && (c2 == '0' || c2 == '1')) {
+ if ((c1 == 'b' || c1 == 'B') && (s[1] == '0' || s[1] == '1')) {
// 0b101010 is a C++1y / GCC extension.
PP.Diag(TokLoc,
PP.getLangOpts().CPlusPlus14
@@ -821,6 +813,7 @@
? diag::ext_binary_literal_cxx14
: diag::ext_binary_literal);
++s;
+ assert(s < ThisTokEnd && "didn't maximally munch?");
radix = 2;
DigitsBegin = s;
s = SkipBinaryDigits(s);
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 7763181..3ceba05 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -1073,6 +1073,9 @@
// These expressions are only allowed within a preprocessor directive.
if (!PP.isParsingIfOrElifDirective()) {
PP.Diag(LParenLoc, diag::err_pp_directive_required) << II->getName();
+ // Return a valid identifier token.
+ assert(Tok.is(tok::identifier));
+ Tok.setIdentifierInfo(II);
return false;
}
@@ -1461,9 +1464,11 @@
Value = EvaluateHasInclude(Tok, II, *this);
else
Value = EvaluateHasIncludeNext(Tok, II, *this);
+
+ if (Tok.isNot(tok::r_paren))
+ return;
OS << (int)Value;
- if (Tok.is(tok::r_paren))
- Tok.setKind(tok::numeric_constant);
+ Tok.setKind(tok::numeric_constant);
} else if (II == Ident__has_warning) {
// The argument should be a parenthesized string literal.
// The argument to these builtins should be a parenthesized identifier.
diff --git a/lib/Lex/ScratchBuffer.cpp b/lib/Lex/ScratchBuffer.cpp
index 3bac889..cd8a27e 100644
--- a/lib/Lex/ScratchBuffer.cpp
+++ b/lib/Lex/ScratchBuffer.cpp
@@ -64,12 +64,13 @@
if (RequestLen < ScratchBufSize)
RequestLen = ScratchBufSize;
+ // Get scratch buffer. Zero-initialize it so it can be dumped into a PCH file
+ // deterministically.
std::unique_ptr<llvm::MemoryBuffer> OwnBuf =
llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
llvm::MemoryBuffer &Buf = *OwnBuf;
FileID FID = SourceMgr.createFileID(std::move(OwnBuf));
BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
CurBuffer = const_cast<char*>(Buf.getBufferStart());
- BytesUsed = 1;
- CurBuffer[0] = '0'; // Start out with a \0 for cleanliness.
+ BytesUsed = 0;
}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 5726fb6..8f4afdf 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -4782,7 +4782,8 @@
D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
DS.getConstSpecLoc(),
DS.getVolatileSpecLoc(),
- DS.getRestrictSpecLoc()),
+ DS.getRestrictSpecLoc(),
+ DS.getAtomicSpecLoc()),
DS.getAttributes(),
SourceLocation());
else
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index ec19f35..c74b028 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -799,7 +799,10 @@
// The operand of the decltype specifier is an unevaluated operand.
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
nullptr,/*IsDecltype=*/true);
- Result = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+ Result =
+ Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) {
+ return E->hasPlaceholderType() ? ExprError() : E;
+ });
if (Result.isInvalid()) {
DS.SetTypeSpecError();
if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
@@ -3527,7 +3530,9 @@
// Alternative tokens do not have identifier info, but their spelling
// starts with an alphabetical character.
SmallString<8> SpellingBuf;
- StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf);
+ SourceLocation SpellingLoc =
+ PP.getSourceManager().getSpellingLoc(Tok.getLocation());
+ StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf);
if (isLetter(Spelling[0])) {
Loc = ConsumeToken();
return &PP.getIdentifierTable().get(Spelling);
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 72af14d..315c957 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -928,7 +928,8 @@
Res = Actions.ActOnIdExpression(
getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),
isAddressOfOperand, std::move(Validator),
- /*IsInlineAsmIdentifier=*/false, &Replacement);
+ /*IsInlineAsmIdentifier=*/false,
+ Tok.is(tok::r_paren) ? nullptr : &Replacement);
if (!Res.isInvalid() && !Res.get()) {
UnconsumeToken(Replacement);
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 1030072..08606d0 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -2535,7 +2535,7 @@
if (SS.isNotEmpty())
ObjectType = ParsedType();
if (Tok.isNot(tok::identifier) || NextToken().is(tok::coloncolon) ||
- SS.isInvalid()) {
+ !SS.isSet()) {
Diag(TildeLoc, diag::err_destructor_tilde_scope);
return true;
}
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 764619a..143ef70 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -257,13 +257,8 @@
// Parse statement
AssociatedStmt = ParseStatement();
Actions.ActOnFinishOfCompoundStmt();
- if (!AssociatedStmt.isUsable()) {
- Actions.ActOnCapturedRegionError();
- CreateDirective = false;
- } else {
- AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
- CreateDirective = AssociatedStmt.isUsable();
- }
+ AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
+ CreateDirective = AssociatedStmt.isUsable();
}
if (CreateDirective)
Directive = Actions.ActOnOpenMPExecutableDirective(
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index d15f2af..c31216d 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -476,7 +476,7 @@
{
ParseScopeFlags FilterScope(this, getCurScope()->getFlags() |
Scope::SEHFilterScope);
- FilterExpr = ParseExpression();
+ FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression());
}
if (getLangOpts().Borland) {
diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp
index 9523ec3..85eff17 100644
--- a/lib/Parse/ParseStmtAsm.cpp
+++ b/lib/Parse/ParseStmtAsm.cpp
@@ -530,7 +530,7 @@
TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
std::unique_ptr<llvm::MCInstPrinter> IP(
- TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI));
+ TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI));
// Change to the Intel dialect.
Parser->setAssemblerDialect(1);
diff --git a/lib/Rewrite/RewriteRope.cpp b/lib/Rewrite/RewriteRope.cpp
index 1c82ee4..451ad07 100644
--- a/lib/Rewrite/RewriteRope.cpp
+++ b/lib/Rewrite/RewriteRope.cpp
@@ -89,9 +89,9 @@
bool IsLeaf;
RopePieceBTreeNode(bool isLeaf) : Size(0), IsLeaf(isLeaf) {}
- ~RopePieceBTreeNode() {}
- public:
+ ~RopePieceBTreeNode() = default;
+ public:
bool isLeaf() const { return IsLeaf; }
unsigned size() const { return Size; }
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 8ee2410..d697ecb 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -139,7 +139,7 @@
return false;
}
- void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {
+ void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override {
if (HasMacroID(B))
return;
@@ -148,7 +148,8 @@
<< DiagRange << isAlwaysTrue;
}
- void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue) {
+ void compareBitwiseEquality(const BinaryOperator *B,
+ bool isAlwaysTrue) override {
if (HasMacroID(B))
return;
@@ -1333,9 +1334,7 @@
public:
UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {}
- ~UninitValsDiagReporter() {
- flushDiagnostics();
- }
+ ~UninitValsDiagReporter() override { flushDiagnostics(); }
MappedType &getUses(const VarDecl *vd) {
if (!uses)
@@ -1663,9 +1662,8 @@
}
}
-
- virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
- SourceLocation Loc) override {
+ void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
+ SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc,
S.PDiag(diag::warn_acquire_requires_negative_cap)
<< Kind << LockName << Neg);
@@ -1680,17 +1678,14 @@
Warnings.push_back(DelayedDiag(Warning, getNotes()));
}
-
- virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
- Name L2Name, SourceLocation Loc)
- override {
+ void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
+ SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc,
S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
Warnings.push_back(DelayedDiag(Warning, getNotes()));
}
- virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc)
- override {
+ void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc,
S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
Warnings.push_back(DelayedDiag(Warning, getNotes()));
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index f6689a9..1e7fc75 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -345,8 +345,9 @@
bool Declarator::isStaticMember() {
assert(getContext() == MemberContext);
return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
- CXXMethodDecl::isStaticOverloadedOperator(
- getName().OperatorFunctionId.Operator);
+ (getName().Kind == UnqualifiedId::IK_OperatorFunctionId &&
+ CXXMethodDecl::isStaticOverloadedOperator(
+ getName().OperatorFunctionId.Operator));
}
bool DeclSpec::hasTagDefinition() const {
diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp
index 6033821..5973500 100644
--- a/lib/Sema/SemaCUDA.cpp
+++ b/lib/Sema/SemaCUDA.cpp
@@ -62,6 +62,11 @@
bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
const FunctionDecl *Callee) {
+ // The CUDADisableTargetCallChecks short-circuits this check: we assume all
+ // cross-target calls are valid.
+ if (getLangOpts().CUDADisableTargetCallChecks)
+ return false;
+
CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller),
CalleeTarget = IdentifyCUDATarget(Callee);
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index abcccba..05eaaec 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -546,11 +546,21 @@
if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::systemz:
+ if (CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ if (CheckPPCBuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
default:
break;
}
@@ -895,6 +905,63 @@
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
+bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ unsigned i = 0, l = 0, u = 0;
+ bool Is64BitBltin = BuiltinID == PPC::BI__builtin_divde ||
+ BuiltinID == PPC::BI__builtin_divdeu ||
+ BuiltinID == PPC::BI__builtin_bpermd;
+ bool IsTarget64Bit = Context.getTargetInfo()
+ .getTypeWidth(Context
+ .getTargetInfo()
+ .getIntPtrType()) == 64;
+ bool IsBltinExtDiv = BuiltinID == PPC::BI__builtin_divwe ||
+ BuiltinID == PPC::BI__builtin_divweu ||
+ BuiltinID == PPC::BI__builtin_divde ||
+ BuiltinID == PPC::BI__builtin_divdeu;
+
+ if (Is64BitBltin && !IsTarget64Bit)
+ return Diag(TheCall->getLocStart(), diag::err_64_bit_builtin_32_bit_tgt)
+ << TheCall->getSourceRange();
+
+ if ((IsBltinExtDiv && !Context.getTargetInfo().hasFeature("extdiv")) ||
+ (BuiltinID == PPC::BI__builtin_bpermd &&
+ !Context.getTargetInfo().hasFeature("bpermd")))
+ return Diag(TheCall->getLocStart(), diag::err_ppc_builtin_only_on_pwr7)
+ << TheCall->getSourceRange();
+
+ switch (BuiltinID) {
+ default: return false;
+ case PPC::BI__builtin_altivec_crypto_vshasigmaw:
+ case PPC::BI__builtin_altivec_crypto_vshasigmad:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) ||
+ SemaBuiltinConstantArgRange(TheCall, 2, 0, 15);
+ case PPC::BI__builtin_tbegin:
+ case PPC::BI__builtin_tend: i = 0; l = 0; u = 1; break;
+ case PPC::BI__builtin_tsr: i = 0; l = 0; u = 7; break;
+ case PPC::BI__builtin_tabortwc:
+ case PPC::BI__builtin_tabortdc: i = 0; l = 0; u = 31; break;
+ case PPC::BI__builtin_tabortwci:
+ case PPC::BI__builtin_tabortdci:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) ||
+ SemaBuiltinConstantArgRange(TheCall, 2, 0, 31);
+ }
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u);
+}
+
+bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+ if (BuiltinID == SystemZ::BI__builtin_tabort) {
+ Expr *Arg = TheCall->getArg(0);
+ llvm::APSInt AbortCode(32);
+ if (Arg->isIntegerConstantExpr(AbortCode, Context) &&
+ AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256)
+ return Diag(Arg->getLocStart(), diag::err_systemz_invalid_tabort_code)
+ << Arg->getSourceRange();
+ }
+
+ return false;
+}
+
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
@@ -7660,6 +7727,35 @@
(void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc);
}
+static void diagnoseArrayStarInParamType(Sema &S, QualType PType,
+ SourceLocation Loc) {
+ if (!PType->isVariablyModifiedType())
+ return;
+ if (const auto *PointerTy = dyn_cast<PointerType>(PType)) {
+ diagnoseArrayStarInParamType(S, PointerTy->getPointeeType(), Loc);
+ return;
+ }
+ if (const auto *ReferenceTy = dyn_cast<ReferenceType>(PType)) {
+ diagnoseArrayStarInParamType(S, ReferenceTy->getPointeeType(), Loc);
+ return;
+ }
+ if (const auto *ParenTy = dyn_cast<ParenType>(PType)) {
+ diagnoseArrayStarInParamType(S, ParenTy->getInnerType(), Loc);
+ return;
+ }
+
+ const ArrayType *AT = S.Context.getAsArrayType(PType);
+ if (!AT)
+ return;
+
+ if (AT->getSizeModifier() != ArrayType::Star) {
+ diagnoseArrayStarInParamType(S, AT->getElementType(), Loc);
+ return;
+ }
+
+ S.Diag(Loc, diag::err_array_star_in_function_definition);
+}
+
/// CheckParmsForFunctionDef - Check that the parameters of the given
/// function are appropriate for the definition of a function. This
/// takes care of any checks that cannot be performed on the
@@ -7698,15 +7794,9 @@
// notation in their sequences of declarator specifiers to specify
// variable length array types.
QualType PType = Param->getOriginalType();
- while (const ArrayType *AT = Context.getAsArrayType(PType)) {
- if (AT->getSizeModifier() == ArrayType::Star) {
- // FIXME: This diagnostic should point the '[*]' if source-location
- // information is added for it.
- Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
- break;
- }
- PType= AT->getElementType();
- }
+ // FIXME: This diagnostic should point the '[*]' if source-location
+ // information is added for it.
+ diagnoseArrayStarInParamType(*this, PType, Param->getLocation());
// MSVC destroys objects passed by value in the callee. Therefore a
// function definition which takes such a parameter must be able to call the
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9bbfeaf..1bad38f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7489,23 +7489,10 @@
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
- QualType RetType = NewFD->getReturnType();
- const CXXRecordDecl *Ret = RetType->isRecordType() ?
- RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl();
- if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() &&
- Ret && Ret->hasAttr<WarnUnusedResultAttr>()) {
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
- // Attach WarnUnusedResult to functions returning types with that attribute.
- // Don't apply the attribute to that type's own non-static member functions
- // (to avoid warning on things like assignment operators)
- if (!MD || MD->getParent() != Ret)
- NewFD->addAttr(WarnUnusedResultAttr::CreateImplicit(Context));
- }
-
if (getLangOpts().OpenCL) {
// OpenCL v1.1 s6.5: Using an address space qualifier in a function return
// type declaration will generate a compilation error.
- unsigned AddressSpace = RetType.getAddressSpace();
+ unsigned AddressSpace = NewFD->getReturnType().getAddressSpace();
if (AddressSpace == LangAS::opencl_local ||
AddressSpace == LangAS::opencl_global ||
AddressSpace == LangAS::opencl_constant) {
@@ -10282,6 +10269,18 @@
if (canRedefineFunction(Definition, getLangOpts()))
return;
+ // If we don't have a visible definition of the function, and it's inline or
+ // a template, it's OK to form another definition of it.
+ //
+ // FIXME: Should we skip the body of the function and use the old definition
+ // in this case? That may be necessary for functions that return local types
+ // through a deduced return type, or instantiate templates with local types.
+ if (!hasVisibleDefinition(Definition) &&
+ (Definition->isInlineSpecified() ||
+ Definition->getDescribedFunctionTemplate() ||
+ Definition->getNumTemplateParameterLists()))
+ return;
+
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
Definition->getStorageClass() == SC_Extern)
Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1c50d77..4f3fed5 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -51,6 +51,11 @@
static bool isFunctionOrMethod(const Decl *D) {
return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
}
+/// \brief Return true if the given decl has function type (function or
+/// function-typed variable) or an Objective-C method or a block.
+static bool isFunctionOrMethodOrBlock(const Decl *D) {
+ return isFunctionOrMethod(D) || isa<BlockDecl>(D);
+}
/// Return true if the given decl has a declarator that should have
/// been processed by Sema::GetTypeForDeclarator.
@@ -257,7 +262,7 @@
unsigned AttrArgNum,
const Expr *IdxExpr,
uint64_t &Idx) {
- assert(isFunctionOrMethod(D));
+ assert(isFunctionOrMethodOrBlock(D));
// In C++ the implicit 'this' function parameter also counts.
// Parameters are counted from one.
@@ -1611,7 +1616,7 @@
// The checking path for 'noreturn' and 'analyzer_noreturn' are different
// because 'analyzer_noreturn' does not impact the type.
- if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) {
+ if (!isFunctionOrMethodOrBlock(D)) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD || (!VD->getType()->isBlockPointerType() &&
!VD->getType()->isFunctionPointerType())) {
@@ -2127,6 +2132,22 @@
Attr.getAttributeSpellingListIndex()));
}
+static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+ QualType T = TD->getUnderlyingType();
+ if (!T->isObjCObjectPointerType()) {
+ S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
+ return;
+ }
+ } else {
+ S.Diag(D->getLocation(), diag::warn_independentclass_attribute);
+ return;
+ }
+ D->addAttr(::new (S.Context)
+ ObjCIndependentClassAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!Attr.isArgIdent(0)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
@@ -2873,6 +2894,16 @@
if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
return;
+ if (E->isValueDependent()) {
+ if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
+ if (!TND->getUnderlyingType()->isDependentType()) {
+ S.Diag(Attr.getLoc(), diag::err_alignment_dependent_typedef_name)
+ << E->getSourceRange();
+ return;
+ }
+ }
+ }
+
S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(),
Attr.isPackExpansion());
}
@@ -4676,6 +4707,9 @@
case AttributeList::AT_ObjCNSObject:
handleObjCNSObject(S, D, Attr);
break;
+ case AttributeList::AT_ObjCIndependentClass:
+ handleObjCIndependentClass(S, D, Attr);
+ break;
case AttributeList::AT_Blocks:
handleBlocksAttr(S, D, Attr);
break;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f7183bc..b0e6aca 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -316,8 +316,17 @@
if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) {
Param->setInvalidDecl();
return;
- }
-
+ }
+
+ // C++11 [dcl.fct.default]p3
+ // A default argument expression [...] shall not be specified for a
+ // parameter pack.
+ if (Param->isParameterPack()) {
+ Diag(EqualLoc, diag::err_param_default_argument_on_parameter_pack)
+ << DefaultArg->getSourceRange();
+ return;
+ }
+
// Check that the default argument is well-formed
CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this);
if (DefaultArgChecker.Visit(DefaultArg)) {
@@ -606,7 +615,8 @@
<< New << New->isConstexpr();
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
- } else if (!Old->isInlined() && New->isInlined() && Old->isDefined(Def)) {
+ } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
+ Old->isDefined(Def)) {
// C++11 [dcl.fcn.spec]p4:
// If the definition of a function appears in a translation unit before its
// first declaration as inline, the program is ill-formed.
@@ -688,16 +698,16 @@
break;
}
- // C++ [dcl.fct.default]p4:
- // In a given function declaration, all parameters
- // subsequent to a parameter with a default argument shall
- // have default arguments supplied in this or previous
- // declarations. A default argument shall not be redefined
- // by a later declaration (not even to the same value).
+ // C++11 [dcl.fct.default]p4:
+ // In a given function declaration, each parameter subsequent to a parameter
+ // with a default argument shall have a default argument supplied in this or
+ // a previous declaration or shall be a function parameter pack. A default
+ // argument shall not be redefined by a later declaration (not even to the
+ // same value).
unsigned LastMissingDefaultArg = 0;
for (; p < NumParams; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
- if (!Param->hasDefaultArg()) {
+ if (!Param->hasDefaultArg() && !Param->isParameterPack()) {
if (Param->isInvalidDecl())
/* We already complained about this parameter. */;
else if (Param->getIdentifier())
@@ -8082,15 +8092,7 @@
if (RequireCompleteDeclContext(SS, LookupContext))
return BuildInvalid();
- // The normal rules do not apply to inheriting constructor declarations.
- if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
- UsingDecl *UD = BuildValid();
- CheckInheritingConstructorUsingDecl(UD);
- return UD;
- }
-
- // Otherwise, look up the target name.
-
+ // Look up the target name.
LookupResult R(*this, NameInfo, LookupOrdinaryName);
// Unlike most lookups, we don't always want to hide tag
@@ -8109,8 +8111,12 @@
LookupQualifiedName(R, LookupContext);
- // Try to correct typos if possible.
- if (R.empty()) {
+ // Try to correct typos if possible. If constructor name lookup finds no
+ // results, that means the named class has no explicit constructors, and we
+ // suppressed declaring implicit ones (probably because it's dependent or
+ // invalid).
+ if (R.empty() &&
+ NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) {
if (TypoCorrection Corrected = CorrectTypo(
R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
llvm::make_unique<UsingValidatorCCC>(
@@ -8140,16 +8146,12 @@
NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Context.getRecordType(RD))));
NameInfo.setNamedTypeInfo(nullptr);
-
- // Build it and process it as an inheriting constructor.
- UsingDecl *UD = BuildValid();
- CheckInheritingConstructorUsingDecl(UD);
- return UD;
+ for (auto *Ctor : LookupConstructors(RD))
+ R.addDecl(Ctor);
+ } else {
+ // FIXME: Pick up all the declarations if we found an overloaded function.
+ R.addDecl(ND);
}
-
- // FIXME: Pick up all the declarations if we found an overloaded function.
- R.setLookupName(Corrected.getCorrection());
- R.addDecl(ND);
} else {
Diag(IdentLoc, diag::err_no_member)
<< NameInfo.getName() << LookupContext << SS.getRange();
@@ -8189,6 +8191,18 @@
}
UsingDecl *UD = BuildValid();
+
+ // The normal rules do not apply to inheriting constructor declarations.
+ if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
+ // Suppress access diagnostics; the access check is instead performed at the
+ // point of use for an inheriting constructor.
+ R.suppressDiagnostics();
+ CheckInheritingConstructorUsingDecl(UD);
+ return UD;
+ }
+
+ // Otherwise, look up the target name.
+
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
UsingShadowDecl *PrevDecl = nullptr;
if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 4865b08..dc47ce9 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -2240,8 +2240,14 @@
if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty())
continue;
- if (!MatchTwoMethodDeclarations(Method, List->getMethod()))
+ if (!MatchTwoMethodDeclarations(Method, List->getMethod())) {
+ // Even if two method types do not match, we would like to say
+ // there is more than one declaration so unavailability/deprecated
+ // warning is not too noisy.
+ if (!Method->isDefined())
+ List->setHasMoreThanOneDecl(true);
continue;
+ }
ObjCMethodDecl *PrevObjCMethod = List->getMethod();
@@ -2340,19 +2346,33 @@
return Methods.size() > 1;
}
-bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, bool instance) {
+bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+ SourceRange R,
+ bool receiverIdOrClass) {
GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
// Test for no method in the pool which should not trigger any warning by
// caller.
if (Pos == MethodPool.end())
return true;
- ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+ ObjCMethodList &MethList =
+ BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second;
+
+ // Diagnose finding more than one method in global pool
+ SmallVector<ObjCMethodDecl *, 4> Methods;
+ Methods.push_back(BestMethod);
+ for (ObjCMethodList *M = &MethList; M; M = M->getNext())
+ if (M->getMethod() && !M->getMethod()->isHidden() &&
+ M->getMethod() != BestMethod)
+ Methods.push_back(M->getMethod());
+ if (Methods.size() > 1)
+ DiagnoseMultipleMethodInGlobalPool(Methods, Sel, R, receiverIdOrClass);
+
return MethList.hasMoreThanOneDecl();
}
ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
bool receiverIdOrClass,
- bool warn, bool instance) {
+ bool instance) {
if (ExternalSource)
ReadMethodPool(Sel);
@@ -2364,31 +2384,23 @@
ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
SmallVector<ObjCMethodDecl *, 4> Methods;
for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {
- if (M->getMethod() && !M->getMethod()->isHidden()) {
- // If we're not supposed to warn about mismatches, we're done.
- if (!warn)
- return M->getMethod();
-
- Methods.push_back(M->getMethod());
- }
+ if (M->getMethod() && !M->getMethod()->isHidden())
+ return M->getMethod();
}
+ return nullptr;
+}
- // If there aren't any visible methods, we're done.
- // FIXME: Recover if there are any known-but-hidden methods?
- if (Methods.empty())
- return nullptr;
-
- if (Methods.size() == 1)
- return Methods[0];
-
+void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
+ Selector Sel, SourceRange R,
+ bool receiverIdOrClass) {
// We found multiple methods, so we may have to complain.
bool issueDiagnostic = false, issueError = false;
-
+
// We support a warning which complains about *any* difference in
// method signature.
bool strictSelectorMatch =
- receiverIdOrClass && warn &&
- !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin());
+ receiverIdOrClass &&
+ !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin());
if (strictSelectorMatch) {
for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) {
@@ -2397,7 +2409,7 @@
}
}
}
-
+
// If we didn't see any strict differences, we won't see any loose
// differences. In ARC, however, we also need to check for loose
// mismatches, because most of them are errors.
@@ -2413,7 +2425,7 @@
break;
}
}
-
+
if (issueDiagnostic) {
if (issueError)
Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;
@@ -2421,16 +2433,15 @@
Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
else
Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
-
+
Diag(Methods[0]->getLocStart(),
issueError ? diag::note_possibility : diag::note_using)
- << Methods[0]->getSourceRange();
+ << Methods[0]->getSourceRange();
for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
Diag(Methods[I]->getLocStart(), diag::note_also_found)
- << Methods[I]->getSourceRange();
+ << Methods[I]->getSourceRange();
+ }
}
- }
- return Methods[0];
}
ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
@@ -2574,10 +2585,9 @@
case Decl::ObjCProtocol:
return Sema::OCK_Protocol;
case Decl::ObjCCategory:
- if (dyn_cast<ObjCCategoryDecl>(CurContext)->IsClassExtension())
+ if (cast<ObjCCategoryDecl>(CurContext)->IsClassExtension())
return Sema::OCK_ClassExtension;
- else
- return Sema::OCK_Category;
+ return Sema::OCK_Category;
case Decl::ObjCImplementation:
return Sema::OCK_Implementation;
case Decl::ObjCCategoryImpl:
@@ -3289,7 +3299,7 @@
case OMF_alloc:
case OMF_new:
- InferRelatedResultType = ObjCMethod->isClassMethod();
+ InferRelatedResultType = ObjCMethod->isClassMethod();
break;
case OMF_init:
@@ -3300,7 +3310,8 @@
break;
}
- if (InferRelatedResultType)
+ if (InferRelatedResultType &&
+ !ObjCMethod->getReturnType()->isObjCIndependentClassType())
ObjCMethod->SetRelatedResultType();
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 6eac5b6..d18aeab 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4608,6 +4608,83 @@
return hasInvalid;
}
+/// If a builtin function has a pointer argument with no explicit address
+/// space, than it should be able to accept a pointer to any address
+/// space as input. In order to do this, we need to replace the
+/// standard builtin declaration with one that uses the same address space
+/// as the call.
+///
+/// \returns nullptr If this builtin is not a candidate for a rewrite i.e.
+/// it does not contain any pointer arguments without
+/// an address space qualifer. Otherwise the rewritten
+/// FunctionDecl is returned.
+/// TODO: Handle pointer return types.
+static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
+ const FunctionDecl *FDecl,
+ MultiExprArg ArgExprs) {
+
+ QualType DeclType = FDecl->getType();
+ const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(DeclType);
+
+ if (!Context.BuiltinInfo.hasPtrArgsOrResult(FDecl->getBuiltinID()) ||
+ !FT || FT->isVariadic() || ArgExprs.size() != FT->getNumParams())
+ return nullptr;
+
+ bool NeedsNewDecl = false;
+ unsigned i = 0;
+ SmallVector<QualType, 8> OverloadParams;
+
+ for (QualType ParamType : FT->param_types()) {
+
+ // Convert array arguments to pointer to simplify type lookup.
+ Expr *Arg = Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]).get();
+ QualType ArgType = Arg->getType();
+ if (!ParamType->isPointerType() ||
+ ParamType.getQualifiers().hasAddressSpace() ||
+ !ArgType->isPointerType() ||
+ !ArgType->getPointeeType().getQualifiers().hasAddressSpace()) {
+ OverloadParams.push_back(ParamType);
+ continue;
+ }
+
+ NeedsNewDecl = true;
+ unsigned AS = ArgType->getPointeeType().getQualifiers().getAddressSpace();
+
+ QualType PointeeType = ParamType->getPointeeType();
+ PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
+ OverloadParams.push_back(Context.getPointerType(PointeeType));
+ }
+
+ if (!NeedsNewDecl)
+ return nullptr;
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ QualType OverloadTy = Context.getFunctionType(FT->getReturnType(),
+ OverloadParams, EPI);
+ DeclContext *Parent = Context.getTranslationUnitDecl();
+ FunctionDecl *OverloadDecl = FunctionDecl::Create(Context, Parent,
+ FDecl->getLocation(),
+ FDecl->getLocation(),
+ FDecl->getIdentifier(),
+ OverloadTy,
+ /*TInfo=*/nullptr,
+ SC_Extern, false,
+ /*hasPrototype=*/true);
+ SmallVector<ParmVarDecl*, 16> Params;
+ FT = cast<FunctionProtoType>(OverloadTy);
+ for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
+ QualType ParamType = FT->getParamType(i);
+ ParmVarDecl *Parm =
+ ParmVarDecl::Create(Context, OverloadDecl, SourceLocation(),
+ SourceLocation(), nullptr, ParamType,
+ /*TInfo=*/nullptr, SC_None, nullptr);
+ Parm->setScopeInfo(0, i);
+ Params.push_back(Parm);
+ }
+ OverloadDecl->setParams(Params);
+ return OverloadDecl;
+}
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
@@ -4711,10 +4788,24 @@
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
if (UnOp->getOpcode() == UO_AddrOf)
NakedFn = UnOp->getSubExpr()->IgnoreParens();
-
- if (isa<DeclRefExpr>(NakedFn))
+
+ if (isa<DeclRefExpr>(NakedFn)) {
NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
- else if (isa<MemberExpr>(NakedFn))
+
+ FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl);
+ if (FDecl && FDecl->getBuiltinID()) {
+ // Rewrite the function decl for this builtin by replacing paramaters
+ // with no explicit address space with the address space of the arguments
+ // in ArgExprs.
+ if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) {
+ NDecl = FDecl;
+ Fn = DeclRefExpr::Create(Context, FDecl->getQualifierLoc(),
+ SourceLocation(), FDecl, false,
+ SourceLocation(), FDecl->getType(),
+ Fn->getValueKind(), FDecl);
+ }
+ }
+ } else if (isa<MemberExpr>(NakedFn))
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) {
@@ -8084,8 +8175,7 @@
if (Type->isObjCIdType()) {
// For 'id', just check the global pool.
Method = S.LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(),
- /*receiverId=*/true,
- /*warn=*/false);
+ /*receiverId=*/true);
} else {
// Check protocols.
Method = S.LookupMethodInQualifiedType(IsEqualSel, Type,
@@ -8891,6 +8981,139 @@
return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
}
+static bool IsTypeModifiable(QualType Ty, bool IsDereference) {
+ Ty = Ty.getNonReferenceType();
+ if (IsDereference && Ty->isPointerType())
+ Ty = Ty->getPointeeType();
+ return !Ty.isConstQualified();
+}
+
+/// Emit the "read-only variable not assignable" error and print notes to give
+/// more information about why the variable is not assignable, such as pointing
+/// to the declaration of a const variable, showing that a method is const, or
+/// that the function is returning a const reference.
+static void DiagnoseConstAssignment(Sema &S, const Expr *E,
+ SourceLocation Loc) {
+ // Update err_typecheck_assign_const and note_typecheck_assign_const
+ // when this enum is changed.
+ enum {
+ ConstFunction,
+ ConstVariable,
+ ConstMember,
+ ConstMethod,
+ ConstUnknown, // Keep as last element
+ };
+
+ SourceRange ExprRange = E->getSourceRange();
+
+ // Only emit one error on the first const found. All other consts will emit
+ // a note to the error.
+ bool DiagnosticEmitted = false;
+
+ // Track if the current expression is the result of a derefence, and if the
+ // next checked expression is the result of a derefence.
+ bool IsDereference = false;
+ bool NextIsDereference = false;
+
+ // Loop to process MemberExpr chains.
+ while (true) {
+ IsDereference = NextIsDereference;
+ NextIsDereference = false;
+
+ E = E->IgnoreParenImpCasts();
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ NextIsDereference = ME->isArrow();
+ const ValueDecl *VD = ME->getMemberDecl();
+ if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) {
+ // Mutable fields can be modified even if the class is const.
+ if (Field->isMutable()) {
+ assert(DiagnosticEmitted && "Expected diagnostic not emitted.");
+ break;
+ }
+
+ if (!IsTypeModifiable(Field->getType(), IsDereference)) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const)
+ << ExprRange << ConstMember << false /*static*/ << Field
+ << Field->getType();
+ DiagnosticEmitted = true;
+ }
+ S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
+ << ConstMember << false /*static*/ << Field << Field->getType()
+ << Field->getSourceRange();
+ }
+ E = ME->getBase();
+ continue;
+ } else if (const VarDecl *VDecl = dyn_cast<VarDecl>(VD)) {
+ if (VDecl->getType().isConstQualified()) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const)
+ << ExprRange << ConstMember << true /*static*/ << VDecl
+ << VDecl->getType();
+ DiagnosticEmitted = true;
+ }
+ S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
+ << ConstMember << true /*static*/ << VDecl << VDecl->getType()
+ << VDecl->getSourceRange();
+ }
+ // Static fields do not inherit constness from parents.
+ break;
+ }
+ break;
+ } // End MemberExpr
+ break;
+ }
+
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+ // Function calls
+ const FunctionDecl *FD = CE->getDirectCallee();
+ if (!IsTypeModifiable(FD->getReturnType(), IsDereference)) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
+ << ConstFunction << FD;
+ DiagnosticEmitted = true;
+ }
+ S.Diag(FD->getReturnTypeSourceRange().getBegin(),
+ diag::note_typecheck_assign_const)
+ << ConstFunction << FD << FD->getReturnType()
+ << FD->getReturnTypeSourceRange();
+ }
+ } else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ // Point to variable declaration.
+ if (const ValueDecl *VD = DRE->getDecl()) {
+ if (!IsTypeModifiable(VD->getType(), IsDereference)) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const)
+ << ExprRange << ConstVariable << VD << VD->getType();
+ DiagnosticEmitted = true;
+ }
+ S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
+ << ConstVariable << VD << VD->getType() << VD->getSourceRange();
+ }
+ }
+ } else if (isa<CXXThisExpr>(E)) {
+ if (const DeclContext *DC = S.getFunctionLevelDeclContext()) {
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
+ if (MD->isConst()) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
+ << ConstMethod << MD;
+ DiagnosticEmitted = true;
+ }
+ S.Diag(MD->getLocation(), diag::note_typecheck_assign_const)
+ << ConstMethod << MD << MD->getSourceRange();
+ }
+ }
+ }
+ }
+
+ if (DiagnosticEmitted)
+ return;
+
+ // Can't determine a more specific message, so display the generic error.
+ S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstUnknown;
+}
+
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
/// emit an error and return true. If so, return false.
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
@@ -8907,8 +9130,6 @@
bool NeedType = false;
switch (IsLV) { // C99 6.5.16p2
case Expr::MLV_ConstQualified:
- DiagID = diag::err_typecheck_assign_const;
-
// Use a specialized diagnostic when we're assigning to an object
// from an enclosing function or block.
if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) {
@@ -8947,13 +9168,20 @@
if (Loc != OrigLoc)
Assign = SourceRange(OrigLoc, OrigLoc);
S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
- // We need to preserve the AST regardless, so migration tool
+ // We need to preserve the AST regardless, so migration tool
// can do its job.
return false;
}
}
}
+ // If none of the special cases above are triggered, then this is a
+ // simple const assignment.
+ if (DiagID == 0) {
+ DiagnoseConstAssignment(S, E, Loc);
+ return true;
+ }
+
break;
case Expr::MLV_ArrayType:
case Expr::MLV_ArrayTemporary:
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 5c43e0c..b050c93 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1418,8 +1418,9 @@
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
+ SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) override {
return S.Diag(Loc,
S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_array_size_conversion
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index fab2fe1..2da4488 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -109,9 +109,8 @@
NamedDecl *D = *I;
if (D->isCXXInstanceMember()) {
- if (dyn_cast<FieldDecl>(D) || dyn_cast<MSPropertyDecl>(D)
- || dyn_cast<IndirectFieldDecl>(D))
- isField = true;
+ isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) ||
+ isa<IndirectFieldDecl>(D);
CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
Classes.insert(R->getCanonicalDecl());
@@ -1536,7 +1535,15 @@
if (BaseType->isExtVectorType()) {
// FIXME: this expr should store IsArrow.
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
- ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());
+ ExprValueKind VK;
+ if (IsArrow)
+ VK = VK_LValue;
+ else {
+ if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(BaseExpr.get()))
+ VK = POE->getSyntacticForm()->getValueKind();
+ else
+ VK = BaseExpr.get()->getValueKind();
+ }
QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,
Member, MemberLoc);
if (ret.isNull())
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 52a384f..63b7485 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1043,7 +1043,7 @@
SourceLocation RParenLoc,
bool WarnMultipleSelectors) {
ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LParenLoc, RParenLoc), false, false);
+ SourceRange(LParenLoc, RParenLoc));
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LParenLoc, RParenLoc));
@@ -2393,8 +2393,11 @@
if (ObjCMethodDecl *BestMethod =
SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
Method = BestMethod;
- if (!AreMultipleMethodsInGlobalPool(Sel, Method->isInstanceMethod()))
+ if (!AreMultipleMethodsInGlobalPool(Sel, Method,
+ SourceRange(LBracLoc, RBracLoc),
+ receiverIsId)) {
DiagnoseUseOfDecl(Method, SelLoc);
+ }
}
} else if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType()) {
@@ -2432,14 +2435,12 @@
// If not messaging 'self', look for any factory method named 'Sel'.
if (!Receiver || !isSelfExpr(Receiver)) {
Method = LookupFactoryMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc),
- true);
+ SourceRange(LBracLoc, RBracLoc));
if (!Method) {
// If no class (factory) method was found, check if an _instance_
// method of the same name exists in the root class only.
Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc),
- true);
+ SourceRange(LBracLoc, RBracLoc));
if (Method)
if (const ObjCInterfaceDecl *ID =
dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
@@ -2516,6 +2517,14 @@
if (OCIType->qual_empty()) {
Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc));
+ if (Method) {
+ if (auto BestMethod =
+ SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
+ Method = BestMethod;
+ AreMultipleMethodsInGlobalPool(Sel, Method,
+ SourceRange(LBracLoc, RBracLoc),
+ true);
+ }
if (Method && !forwardClass)
Diag(SelLoc, diag::warn_maynot_respond)
<< OCIType->getInterfaceDecl()->getIdentifier()
@@ -3357,7 +3366,7 @@
ObjCInterfaceDecl *CastClass
= InterfacePointerType->getObjectType()->getInterface();
if ((CastClass == ExprClass) ||
- (CastClass && ExprClass->isSuperClassOf(CastClass)))
+ (CastClass && CastClass->isSuperClassOf(ExprClass)))
return true;
if (warn)
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
@@ -3380,12 +3389,13 @@
return false;
}
}
+ } else if (!castType->isObjCIdType()) {
+ S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
+ << castExpr->getType() << Parm;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (Target)
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
}
- S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
- << castExpr->getType() << Parm;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
- if (Target)
- S.Diag(Target->getLocStart(), diag::note_declared_at);
return true;
}
return false;
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 4a6531e..75ccc4e 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -6753,9 +6753,9 @@
case FK_TooManyInitsForScalar: {
SourceRange R;
- if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
- R = SourceRange(InitList->getInit(0)->getLocEnd(),
- InitList->getLocEnd());
+ auto *InitList = dyn_cast<InitListExpr>(Args[0]);
+ if (InitList && InitList->getNumInits() == 1)
+ R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd());
else
R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd());
@@ -7356,7 +7356,6 @@
EqualLoc,
AllowExplicit);
InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList);
- Init.get();
ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE);
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 90a81f4..147dd7e 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -1340,22 +1340,27 @@
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
- const FunctionProtoType *Proto
- = CallOperator->getType()->getAs<FunctionProtoType>();
- QualType BlockPtrTy;
- {
- FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
- ExtInfo.TypeQuals = 0;
- QualType FunctionTy = S.Context.getFunctionType(
- Proto->getReturnType(), Proto->getParamTypes(), ExtInfo);
- BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
- }
+ const FunctionProtoType *Proto =
+ CallOperator->getType()->getAs<FunctionProtoType>();
- FunctionProtoType::ExtProtoInfo ExtInfo(S.Context.getDefaultCallingConvention(
- /*IsVariadic=*/false, /*IsCXXMethod=*/true));
- ExtInfo.TypeQuals = Qualifiers::Const;
- QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ExtInfo);
-
+ // The function type inside the block pointer type is the same as the call
+ // operator with some tweaks. The calling convention is the default free
+ // function convention, and the type qualifications are lost.
+ FunctionProtoType::ExtProtoInfo BlockEPI = Proto->getExtProtoInfo();
+ BlockEPI.ExtInfo =
+ BlockEPI.ExtInfo.withCallingConv(S.Context.getDefaultCallingConvention(
+ Proto->isVariadic(), /*IsCXXMethod=*/false));
+ BlockEPI.TypeQuals = 0;
+ QualType FunctionTy = S.Context.getFunctionType(
+ Proto->getReturnType(), Proto->getParamTypes(), BlockEPI);
+ QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
+
+ FunctionProtoType::ExtProtoInfo ConversionEPI(
+ S.Context.getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true));
+ ConversionEPI.TypeQuals = Qualifiers::Const;
+ QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI);
+
SourceLocation Loc = IntroducerRange.getBegin();
DeclarationName Name
= S.Context.DeclarationNames.getCXXConversionFunctionName(
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index ac7376e..09424a4 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1226,8 +1226,7 @@
DeclContext *DC = D->getLexicalDeclContext();
if (!D->isModulePrivate() &&
DC && !DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) {
- NamedDecl *Hidden;
- if (SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC), &Hidden)) {
+ if (SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) {
if (SemaRef.ActiveTemplateInstantiations.empty()) {
// Cache the fact that this declaration is implicitly visible because
// its parent has a visible definition.
@@ -3071,7 +3070,7 @@
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
// Enumerate all of the results in this context.
- for (const auto &R : Ctx->lookups()) {
+ for (DeclContextLookupResult R : Ctx->lookups()) {
for (auto *D : R) {
if (auto *ND = Result.getAcceptableDecl(D)) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index f4f4336..5e7b4b8 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -407,9 +407,11 @@
// this conversion is safe only because the wider type is for a 'readonly'
// property in primary class and 'narrowed' type for a 'readwrite' property
// in continuation class.
- if (!isa<ObjCObjectPointerType>(PIDecl->getType()) ||
- !isa<ObjCObjectPointerType>(PDecl->getType()) ||
- (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(),
+ QualType PrimaryClassPropertyT = Context.getCanonicalType(PIDecl->getType());
+ QualType ClassExtPropertyT = Context.getCanonicalType(PDecl->getType());
+ if (!isa<ObjCObjectPointerType>(PrimaryClassPropertyT) ||
+ !isa<ObjCObjectPointerType>(ClassExtPropertyT) ||
+ (!isObjCPointerConversion(ClassExtPropertyT, PrimaryClassPropertyT,
ConvertedType, IncompatibleObjC))
|| IncompatibleObjC) {
Diag(AtLoc,
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index e027e55..fed0ac7 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -238,6 +238,7 @@
DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
VarDecl *D) {
+ D = D->getCanonicalDecl();
DSAVarData DVar;
if (Iter == std::prev(Stack.rend())) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -342,6 +343,7 @@
DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {
assert(Stack.size() > 1 && "Data sharing attributes stack is empty");
+ D = D->getCanonicalDecl();
auto It = Stack.back().AlignedMap.find(D);
if (It == Stack.back().AlignedMap.end()) {
assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
@@ -355,6 +357,7 @@
}
void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
+ D = D->getCanonicalDecl();
if (A == OMPC_threadprivate) {
Stack[0].SharingMap[D].Attributes = A;
Stack[0].SharingMap[D].RefExpr = E;
@@ -366,6 +369,7 @@
}
bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+ D = D->getCanonicalDecl();
if (Stack.size() > 2) {
reverse_iterator I = Iter, E = std::prev(Stack.rend());
Scope *TopScope = nullptr;
@@ -385,6 +389,7 @@
}
DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
+ D = D->getCanonicalDecl();
DSAVarData DVar;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -477,6 +482,7 @@
}
DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) {
+ D = D->getCanonicalDecl();
auto StartI = Stack.rbegin();
auto EndI = std::prev(Stack.rend());
if (FromParent && StartI != EndI) {
@@ -489,6 +495,7 @@
DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred,
DirectivesPredicate DPred,
bool FromParent) {
+ D = D->getCanonicalDecl();
auto StartI = std::next(Stack.rbegin());
auto EndI = std::prev(Stack.rend());
if (FromParent && StartI != EndI) {
@@ -508,6 +515,7 @@
DSAStackTy::DSAVarData
DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
DirectivesPredicate DPred, bool FromParent) {
+ D = D->getCanonicalDecl();
auto StartI = std::next(Stack.rbegin());
auto EndI = std::prev(Stack.rend());
if (FromParent && StartI != EndI) {
@@ -546,6 +554,7 @@
bool Sema::IsOpenMPCapturedVar(VarDecl *VD) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ VD = VD->getCanonicalDecl();
if (DSAStack->getCurrentDirective() != OMPD_unknown) {
auto DVarPrivate = DSAStack->getTopDSA(VD, /*FromParent=*/false);
if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind))
@@ -573,46 +582,44 @@
// class type, unless the list item is also specified in a firstprivate
// clause.
if (auto D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
- for (auto C : D->clauses()) {
- if (auto Clause = dyn_cast<OMPLastprivateClause>(C)) {
- for (auto VarRef : Clause->varlists()) {
- if (VarRef->isValueDependent() || VarRef->isTypeDependent())
+ for (auto *C : D->clauses()) {
+ if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
+ SmallVector<Expr *, 8> PrivateCopies;
+ for (auto *DE : Clause->varlists()) {
+ if (DE->isValueDependent() || DE->isTypeDependent()) {
+ PrivateCopies.push_back(nullptr);
continue;
- auto VD = cast<VarDecl>(cast<DeclRefExpr>(VarRef)->getDecl());
+ }
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl());
auto DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_lastprivate) {
- SourceLocation ELoc = VarRef->getExprLoc();
- auto Type = VarRef->getType();
- if (Type->isArrayType())
- Type = QualType(Type->getArrayElementTypeNoTypeQual(), 0);
- CXXRecordDecl *RD =
- getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
- // FIXME This code must be replaced by actual constructing of the
- // lastprivate variable.
- if (RD) {
- CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
- PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (!CD ||
- CheckConstructorAccess(
- ELoc, CD, InitializedEntity::InitializeTemporary(Type),
- CD->getAccess(), PD) == AR_inaccessible ||
- CD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_lastprivate) << 0;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl
- : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, CD);
- DiagnoseUseOfDecl(CD, ELoc);
- }
+ // Generate helper private variable and initialize it with the
+ // default value. The address of the original variable is replaced
+ // by the address of the new private variable in CodeGen. This new
+ // variable is not added to IdResolver, so the code in the OpenMP
+ // region uses original variable for proper diagnostics.
+ auto *VDPrivate = VarDecl::Create(
+ Context, CurContext, DE->getLocStart(), DE->getExprLoc(),
+ VD->getIdentifier(), VD->getType(), VD->getTypeSourceInfo(),
+ SC_Auto);
+ ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
+ if (VDPrivate->isInvalidDecl())
+ continue;
+ CurContext->addDecl(VDPrivate);
+ PrivateCopies.push_back(DeclRefExpr::Create(
+ Context, NestedNameSpecifierLoc(), SourceLocation(), VDPrivate,
+ /*RefersToEnclosingVariableOrCapture=*/false, SourceLocation(),
+ DE->getType(), VK_LValue));
+ } else {
+ // The variable is also a firstprivate, so initialization sequence
+ // for private copy is generated already.
+ PrivateCopies.push_back(nullptr);
}
}
+ // Set initializers to private copies if no errors were found.
+ if (PrivateCopies.size() == Clause->varlist_size()) {
+ Clause->setPrivateCopies(PrivateCopies);
+ }
}
}
}
@@ -759,7 +766,7 @@
// OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
// A threadprivate directive must lexically precede all references to any
// of the variables in its list.
- if (VD->isUsed()) {
+ if (VD->isUsed() && !DSAStack->isThreadPrivate(VD)) {
Diag(Id.getLoc(), diag::err_omp_var_used)
<< getOpenMPDirectiveName(OMPD_threadprivate) << VD;
return ExprError();
@@ -817,6 +824,13 @@
VarDecl *VD = cast<VarDecl>(DE->getDecl());
SourceLocation ILoc = DE->getExprLoc();
+ QualType QType = VD->getType();
+ if (QType->isDependentType() || QType->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
// OpenMP [2.9.2, Restrictions, C/C++, p.10]
// A threadprivate variable must not have an incomplete type.
if (RequireCompleteType(ILoc, VD->getType(),
@@ -1117,7 +1131,11 @@
break;
}
case OMPD_parallel_sections: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
@@ -1187,6 +1205,26 @@
}
}
+StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
+ ArrayRef<OMPClause *> Clauses) {
+ if (!S.isUsable()) {
+ ActOnCapturedRegionError();
+ return StmtError();
+ }
+ // Mark all variables in private list clauses as used in inner region. This is
+ // required for proper codegen.
+ for (auto *Clause : Clauses) {
+ if (isOpenMPPrivate(Clause->getClauseKind())) {
+ for (auto *VarRef : Clause->children()) {
+ if (auto *E = cast_or_null<Expr>(VarRef)) {
+ MarkDeclarationsReferencedInExpr(E);
+ }
+ }
+ }
+ }
+ return ActOnCapturedRegionEnd(S.get());
+}
+
static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
OpenMPDirectiveKind CurrentRegion,
const DeclarationNameInfo &CurrentName,
@@ -3282,40 +3320,54 @@
Sema &SemaRef;
/// \brief A location for note diagnostics (when error is found).
SourceLocation NoteLoc;
- /// \brief Atomic operation supposed to be performed on source expression.
- BinaryOperatorKind OpKind;
/// \brief 'x' lvalue part of the source atomic expression.
Expr *X;
- /// \brief 'x' rvalue part of the source atomic expression, used in the right
- /// hand side of the expression. We need this to properly generate RHS part of
- /// the source expression (x = x'rval' binop expr or x = expr binop x'rval').
- Expr *XRVal;
/// \brief 'expr' rvalue part of the source atomic expression.
Expr *E;
+ /// \brief Helper expression of the form
+ /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
+ /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
+ Expr *UpdateExpr;
+ /// \brief Is 'x' a LHS in a RHS part of full update expression. It is
+ /// important for non-associative operations.
+ bool IsXLHSInRHSPart;
+ BinaryOperatorKind Op;
+ SourceLocation OpLoc;
+ /// \brief true if the source expression is a postfix unary operation, false
+ /// if it is a prefix unary operation.
+ bool IsPostfixUpdate;
public:
OpenMPAtomicUpdateChecker(Sema &SemaRef)
- : SemaRef(SemaRef), OpKind(BO_PtrMemD), X(nullptr), XRVal(nullptr),
- E(nullptr) {}
+ : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
+ IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
/// \brief Check specified statement that it is suitable for 'atomic update'
/// constructs and extract 'x', 'expr' and Operation from the original
- /// expression.
+ /// expression. If DiagId and NoteId == 0, then only check is performed
+ /// without error notification.
/// \param DiagId Diagnostic which should be emitted if error is found.
/// \param NoteId Diagnostic note for the main error message.
/// \return true if statement is not an update expression, false otherwise.
- bool checkStatement(Stmt *S, unsigned DiagId, unsigned NoteId);
+ bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
/// \brief Return the 'x' lvalue part of the source atomic expression.
Expr *getX() const { return X; }
- /// \brief Return the 'x' rvalue part of the source atomic expression, used in
- /// the RHS part of the source expression.
- Expr *getXRVal() const { return XRVal; }
/// \brief Return the 'expr' rvalue part of the source atomic expression.
Expr *getExpr() const { return E; }
- /// \brief Return required atomic operation.
- BinaryOperatorKind getOpKind() const {return OpKind;}
+ /// \brief Return the update expression used in calculation of the updated
+ /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
+ /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
+ Expr *getUpdateExpr() const { return UpdateExpr; }
+ /// \brief Return true if 'x' is LHS in RHS part of full update expression,
+ /// false otherwise.
+ bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
+
+ /// \brief true if the source expression is a postfix unary operation, false
+ /// if it is a prefix unary operation.
+ bool isPostfixUpdate() const { return IsPostfixUpdate; }
+
private:
- bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId,
- unsigned NoteId);
+ bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
+ unsigned NoteId = 0);
};
} // namespace
@@ -3334,7 +3386,8 @@
if (AtomicInnerBinOp->isMultiplicativeOp() ||
AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
AtomicInnerBinOp->isBitwiseOp()) {
- OpKind = AtomicInnerBinOp->getOpcode();
+ Op = AtomicInnerBinOp->getOpcode();
+ OpLoc = AtomicInnerBinOp->getOperatorLoc();
auto *LHS = AtomicInnerBinOp->getLHS();
auto *RHS = AtomicInnerBinOp->getRHS();
llvm::FoldingSetNodeID XId, LHSId, RHSId;
@@ -3346,10 +3399,10 @@
/*Canonical=*/true);
if (XId == LHSId) {
E = RHS;
- XRVal = LHS;
+ IsXLHSInRHSPart = true;
} else if (XId == RHSId) {
E = LHS;
- XRVal = RHS;
+ IsXLHSInRHSPart = false;
} else {
ErrorLoc = AtomicInnerBinOp->getExprLoc();
ErrorRange = AtomicInnerBinOp->getSourceRange();
@@ -3376,12 +3429,12 @@
NoteRange = SourceRange(NoteLoc, NoteLoc);
ErrorFound = NotAnAssignmentOp;
}
- if (ErrorFound != NoError) {
+ if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
return true;
} else if (SemaRef.CurContext->isDependentContext())
- E = X = XRVal = nullptr;
+ E = X = UpdateExpr = nullptr;
return false;
}
@@ -3405,26 +3458,27 @@
if (auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
AtomicBody->IgnoreParenImpCasts())) {
// Check for Compound Assignment Operation
- OpKind = BinaryOperator::getOpForCompoundAssignment(
+ Op = BinaryOperator::getOpForCompoundAssignment(
AtomicCompAssignOp->getOpcode());
- X = AtomicCompAssignOp->getLHS();
- XRVal = SemaRef.PerformImplicitConversion(
- X, AtomicCompAssignOp->getComputationLHSType(),
- Sema::AA_Casting, /*AllowExplicit=*/true).get();
+ OpLoc = AtomicCompAssignOp->getOperatorLoc();
E = AtomicCompAssignOp->getRHS();
+ X = AtomicCompAssignOp->getLHS();
+ IsXLHSInRHSPart = true;
} else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
AtomicBody->IgnoreParenImpCasts())) {
// Check for Binary Operation
- return checkBinaryOperation(AtomicBinOp, DiagId, NoteId);
+ if(checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
+ return true;
} else if (auto *AtomicUnaryOp =
- // Check for Binary Operation
dyn_cast<UnaryOperator>(AtomicBody->IgnoreParenImpCasts())) {
// Check for Unary Operation
if (AtomicUnaryOp->isIncrementDecrementOp()) {
- OpKind = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
- XRVal = X = AtomicUnaryOp->getSubExpr();
- E = SemaRef.ActOnIntegerConstant(AtomicUnaryOp->getOperatorLoc(), 1)
- .get();
+ IsPostfixUpdate = AtomicUnaryOp->isPostfix();
+ Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
+ OpLoc = AtomicUnaryOp->getOperatorLoc();
+ X = AtomicUnaryOp->getSubExpr();
+ E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
+ IsXLHSInRHSPart = true;
} else {
ErrorFound = NotAnUnaryIncDecExpression;
ErrorLoc = AtomicUnaryOp->getExprLoc();
@@ -3447,12 +3501,31 @@
NoteLoc = ErrorLoc = S->getLocStart();
NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
}
- if (ErrorFound != NoError) {
+ if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
return true;
} else if (SemaRef.CurContext->isDependentContext())
- E = X = XRVal = nullptr;
+ E = X = UpdateExpr = nullptr;
+ if (E && X) {
+ // Build an update expression of form 'OpaqueValueExpr(x) binop
+ // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
+ // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
+ auto *OVEX = new (SemaRef.getASTContext())
+ OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_RValue);
+ auto *OVEExpr = new (SemaRef.getASTContext())
+ OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_RValue);
+ auto Update =
+ SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
+ IsXLHSInRHSPart ? OVEExpr : OVEX);
+ if (Update.isInvalid())
+ return true;
+ Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
+ Sema::AA_Casting);
+ if (Update.isInvalid())
+ return true;
+ UpdateExpr = Update.get();
+ }
return false;
}
@@ -3467,7 +3540,6 @@
// top and a single exit at the bottom.
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
- // TODO further analysis of associated statements and clauses.
OpenMPClauseKind AtomicKind = OMPC_unknown;
SourceLocation AtomicKindLoc;
for (auto *C : Clauses) {
@@ -3490,11 +3562,12 @@
if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
Body = EWC->getSubExpr();
- BinaryOperatorKind OpKind = BO_PtrMemD;
Expr *X = nullptr;
- Expr *XRVal = nullptr;
Expr *V = nullptr;
Expr *E = nullptr;
+ Expr *UE = nullptr;
+ bool IsXLHSInRHSPart = false;
+ bool IsPostfixUpdate = false;
// OpenMP [2.12.6, atomic Construct]
// In the next expressions:
// * x and v (as applicable) are both l-value expressions with scalar type.
@@ -3517,14 +3590,14 @@
// expr or subexpressions of expr.
// * For forms that allow multiple occurrences of x, the number of times
// that x is evaluated is unspecified.
- enum {
- NotAnExpression,
- NotAnAssignmentOp,
- NotAScalarType,
- NotAnLValue,
- NoError
- } ErrorFound = NoError;
if (AtomicKind == OMPC_read) {
+ enum {
+ NotAnExpression,
+ NotAnAssignmentOp,
+ NotAScalarType,
+ NotAnLValue,
+ NoError
+ } ErrorFound = NoError;
SourceLocation ErrorLoc, NoteLoc;
SourceRange ErrorRange, NoteRange;
// If clause is read:
@@ -3580,6 +3653,13 @@
} else if (CurContext->isDependentContext())
V = X = nullptr;
} else if (AtomicKind == OMPC_write) {
+ enum {
+ NotAnExpression,
+ NotAnAssignmentOp,
+ NotAScalarType,
+ NotAnLValue,
+ NoError
+ } ErrorFound = NoError;
SourceLocation ErrorLoc, NoteLoc;
SourceRange ErrorRange, NoteRange;
// If clause is write:
@@ -3652,25 +3732,222 @@
if (!CurContext->isDependentContext()) {
E = Checker.getExpr();
X = Checker.getX();
- XRVal = Checker.getXRVal();
- OpKind = Checker.getOpKind();
+ UE = Checker.getUpdateExpr();
+ IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
}
} else if (AtomicKind == OMPC_capture) {
- if (isa<Expr>(Body) && !isa<BinaryOperator>(Body)) {
- Diag(Body->getLocStart(),
- diag::err_omp_atomic_capture_not_expression_statement);
- return StmtError();
- } else if (!isa<Expr>(Body) && !isa<CompoundStmt>(Body)) {
- Diag(Body->getLocStart(),
- diag::err_omp_atomic_capture_not_compound_statement);
- return StmtError();
+ enum {
+ NotAnAssignmentOp,
+ NotACompoundStatement,
+ NotTwoSubstatements,
+ NotASpecificExpression,
+ NoError
+ } ErrorFound = NoError;
+ SourceLocation ErrorLoc, NoteLoc;
+ SourceRange ErrorRange, NoteRange;
+ if (auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ // If clause is a capture:
+ // v = x++;
+ // v = x--;
+ // v = ++x;
+ // v = --x;
+ // v = x binop= expr;
+ // v = x = x binop expr;
+ // v = x = expr binop x;
+ auto *AtomicBinOp =
+ dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
+ if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
+ V = AtomicBinOp->getLHS();
+ Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
+ OpenMPAtomicUpdateChecker Checker(*this);
+ if (Checker.checkStatement(
+ Body, diag::err_omp_atomic_capture_not_expression_statement,
+ diag::note_omp_atomic_update))
+ return StmtError();
+ E = Checker.getExpr();
+ X = Checker.getX();
+ UE = Checker.getUpdateExpr();
+ IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
+ IsPostfixUpdate = Checker.isPostfixUpdate();
+ } else {
+ ErrorLoc = AtomicBody->getExprLoc();
+ ErrorRange = AtomicBody->getSourceRange();
+ NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
+ : AtomicBody->getExprLoc();
+ NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
+ : AtomicBody->getSourceRange();
+ ErrorFound = NotAnAssignmentOp;
+ }
+ if (ErrorFound != NoError) {
+ Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
+ << ErrorRange;
+ Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
+ return StmtError();
+ } else if (CurContext->isDependentContext()) {
+ UE = V = E = X = nullptr;
+ }
+ } else {
+ // If clause is a capture:
+ // { v = x; x = expr; }
+ // { v = x; x++; }
+ // { v = x; x--; }
+ // { v = x; ++x; }
+ // { v = x; --x; }
+ // { v = x; x binop= expr; }
+ // { v = x; x = x binop expr; }
+ // { v = x; x = expr binop x; }
+ // { x++; v = x; }
+ // { x--; v = x; }
+ // { ++x; v = x; }
+ // { --x; v = x; }
+ // { x binop= expr; v = x; }
+ // { x = x binop expr; v = x; }
+ // { x = expr binop x; v = x; }
+ if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
+ // Check that this is { expr1; expr2; }
+ if (CS->size() == 2) {
+ auto *First = CS->body_front();
+ auto *Second = CS->body_back();
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
+ First = EWC->getSubExpr()->IgnoreParenImpCasts();
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
+ Second = EWC->getSubExpr()->IgnoreParenImpCasts();
+ // Need to find what subexpression is 'v' and what is 'x'.
+ OpenMPAtomicUpdateChecker Checker(*this);
+ bool IsUpdateExprFound = !Checker.checkStatement(Second);
+ BinaryOperator *BinOp = nullptr;
+ if (IsUpdateExprFound) {
+ BinOp = dyn_cast<BinaryOperator>(First);
+ IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
+ }
+ if (IsUpdateExprFound && !CurContext->isDependentContext()) {
+ // { v = x; x++; }
+ // { v = x; x--; }
+ // { v = x; ++x; }
+ // { v = x; --x; }
+ // { v = x; x binop= expr; }
+ // { v = x; x = x binop expr; }
+ // { v = x; x = expr binop x; }
+ // Check that the first expression has form v = x.
+ auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
+ llvm::FoldingSetNodeID XId, PossibleXId;
+ Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
+ PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
+ IsUpdateExprFound = XId == PossibleXId;
+ if (IsUpdateExprFound) {
+ V = BinOp->getLHS();
+ X = Checker.getX();
+ E = Checker.getExpr();
+ UE = Checker.getUpdateExpr();
+ IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
+ IsPostfixUpdate = Checker.isPostfixUpdate();
+ }
+ }
+ if (!IsUpdateExprFound) {
+ IsUpdateExprFound = !Checker.checkStatement(First);
+ BinOp = nullptr;
+ if (IsUpdateExprFound) {
+ BinOp = dyn_cast<BinaryOperator>(Second);
+ IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
+ }
+ if (IsUpdateExprFound && !CurContext->isDependentContext()) {
+ // { x++; v = x; }
+ // { x--; v = x; }
+ // { ++x; v = x; }
+ // { --x; v = x; }
+ // { x binop= expr; v = x; }
+ // { x = x binop expr; v = x; }
+ // { x = expr binop x; v = x; }
+ // Check that the second expression has form v = x.
+ auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
+ llvm::FoldingSetNodeID XId, PossibleXId;
+ Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
+ PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
+ IsUpdateExprFound = XId == PossibleXId;
+ if (IsUpdateExprFound) {
+ V = BinOp->getLHS();
+ X = Checker.getX();
+ E = Checker.getExpr();
+ UE = Checker.getUpdateExpr();
+ IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
+ IsPostfixUpdate = Checker.isPostfixUpdate();
+ }
+ }
+ }
+ if (!IsUpdateExprFound) {
+ // { v = x; x = expr; }
+ auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
+ if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
+ ErrorFound = NotAnAssignmentOp;
+ NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
+ : First->getLocStart();
+ NoteRange = ErrorRange = FirstBinOp
+ ? FirstBinOp->getSourceRange()
+ : SourceRange(ErrorLoc, ErrorLoc);
+ } else {
+ auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
+ if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
+ ErrorFound = NotAnAssignmentOp;
+ NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc()
+ : Second->getLocStart();
+ NoteRange = ErrorRange = SecondBinOp
+ ? SecondBinOp->getSourceRange()
+ : SourceRange(ErrorLoc, ErrorLoc);
+ } else {
+ auto *PossibleXRHSInFirst =
+ FirstBinOp->getRHS()->IgnoreParenImpCasts();
+ auto *PossibleXLHSInSecond =
+ SecondBinOp->getLHS()->IgnoreParenImpCasts();
+ llvm::FoldingSetNodeID X1Id, X2Id;
+ PossibleXRHSInFirst->Profile(X1Id, Context, /*Canonical=*/true);
+ PossibleXLHSInSecond->Profile(X2Id, Context,
+ /*Canonical=*/true);
+ IsUpdateExprFound = X1Id == X2Id;
+ if (IsUpdateExprFound) {
+ V = FirstBinOp->getLHS();
+ X = SecondBinOp->getLHS();
+ E = SecondBinOp->getRHS();
+ UE = nullptr;
+ IsXLHSInRHSPart = false;
+ IsPostfixUpdate = true;
+ } else {
+ ErrorFound = NotASpecificExpression;
+ ErrorLoc = FirstBinOp->getExprLoc();
+ ErrorRange = FirstBinOp->getSourceRange();
+ NoteLoc = SecondBinOp->getLHS()->getExprLoc();
+ NoteRange = SecondBinOp->getRHS()->getSourceRange();
+ }
+ }
+ }
+ }
+ } else {
+ NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteRange = ErrorRange =
+ SourceRange(Body->getLocStart(), Body->getLocStart());
+ ErrorFound = NotTwoSubstatements;
+ }
+ } else {
+ NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteRange = ErrorRange =
+ SourceRange(Body->getLocStart(), Body->getLocStart());
+ ErrorFound = NotACompoundStatement;
+ }
+ if (ErrorFound != NoError) {
+ Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
+ << ErrorRange;
+ Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
+ return StmtError();
+ } else if (CurContext->isDependentContext()) {
+ UE = V = E = X = nullptr;
+ }
}
}
getCurFunction()->setHasBranchProtectedScope();
return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
- OpKind, X, XRVal, V, E);
+ X, V, E, UE, IsXLHSInRHSPart,
+ IsPostfixUpdate);
}
StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
@@ -4542,7 +4819,7 @@
// A variable of class type (or array thereof) that appears in a private
// clause requires an accessible, unambiguous copy constructor for the
// class type.
- Type = Context.getBaseElementType(Type);
+ Type = Context.getBaseElementType(Type).getNonReferenceType();
// If an implicit firstprivate variable found it was checked already.
if (!IsImplicitClause) {
@@ -4632,10 +4909,10 @@
}
}
- Type = Type.getUnqualifiedType();
- auto VDPrivate = VarDecl::Create(Context, CurContext, DE->getLocStart(),
- ELoc, VD->getIdentifier(), VD->getType(),
- VD->getTypeSourceInfo(), /*S*/ SC_Auto);
+ auto VDPrivate =
+ VarDecl::Create(Context, CurContext, DE->getLocStart(), ELoc,
+ VD->getIdentifier(), VD->getType().getUnqualifiedType(),
+ VD->getTypeSourceInfo(), /*S*/ SC_Auto);
// Generate helper private variable and initialize it with the value of the
// original variable. The address of the original variable is replaced by
// the address of the new private variable in the CodeGen. This new variable
@@ -4654,9 +4931,12 @@
/*TemplateKWLoc*/ SourceLocation(), VDInit,
/*RefersToEnclosingVariableOrCapture*/ true, ELoc, Type,
/*VK*/ VK_LValue);
- VDInit->setIsUsed();
auto Init = DefaultLvalueConversion(VDInitRefExpr).get();
- InitializedEntity Entity = InitializedEntity::InitializeVariable(VDInit);
+ auto *VDInitTemp =
+ BuildVarDecl(*this, DE->getLocStart(), Type.getUnqualifiedType(),
+ ".firstprivate.temp");
+ InitializedEntity Entity =
+ InitializedEntity::InitializeVariable(VDInitTemp);
InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
InitializationSequence InitSeq(*this, Entity, Kind, Init);
@@ -4666,15 +4946,13 @@
else
VDPrivate->setInit(Result.getAs<Expr>());
} else {
- AddInitializerToDecl(
- VDPrivate,
- DefaultLvalueConversion(
- DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
- SourceLocation(), DE->getDecl(),
- /*RefersToEnclosingVariableOrCapture=*/true,
- DE->getExprLoc(), DE->getType(),
- /*VK=*/VK_LValue)).get(),
- /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+ auto *VDInit =
+ BuildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp");
+ VDInitRefExpr =
+ BuildDeclRefExpr(VDInit, Type, VK_LValue, DE->getExprLoc()).get();
+ AddInitializerToDecl(VDPrivate,
+ DefaultLvalueConversion(VDInitRefExpr).get(),
+ /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
}
if (VDPrivate->isInvalidDecl()) {
if (IsImplicitClause) {
@@ -4684,12 +4962,11 @@
continue;
}
CurContext->addDecl(VDPrivate);
- auto VDPrivateRefExpr =
- DeclRefExpr::Create(Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
- /*TemplateKWLoc*/ SourceLocation(), VDPrivate,
- /*RefersToEnclosingVariableOrCapture*/ false,
- DE->getLocStart(), DE->getType(),
- /*VK*/ VK_LValue);
+ auto VDPrivateRefExpr = DeclRefExpr::Create(
+ Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
+ /*TemplateKWLoc*/ SourceLocation(), VDPrivate,
+ /*RefersToEnclosingVariableOrCapture*/ false, DE->getLocStart(),
+ DE->getType().getUnqualifiedType(), /*VK*/ VK_LValue);
DSAStack->addDSA(VD, DE, OMPC_firstprivate);
Vars.push_back(DE);
PrivateCopies.push_back(VDPrivateRefExpr);
@@ -4708,11 +4985,17 @@
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> SrcExprs;
+ SmallVector<Expr *, 8> DstExprs;
+ SmallVector<Expr *, 8> AssignmentOps;
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -4734,6 +5017,9 @@
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -4797,65 +5083,39 @@
// A variable of class type (or array thereof) that appears in a
// lastprivate clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- while (Type.getNonReferenceType()->isArrayType())
- Type = cast<ArrayType>(Type.getNonReferenceType().getTypePtr())
- ->getElementType();
- CXXRecordDecl *RD = getLangOpts().CPlusPlus
- ? Type.getNonReferenceType()->getAsCXXRecordDecl()
- : nullptr;
- // FIXME This code must be replaced by actual copying and destructing of the
- // lastprivate variable.
- if (RD) {
- CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
- DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
- if (MD) {
- if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
- MD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_lastprivate) << 2;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, MD);
- DiagnoseUseOfDecl(MD, ELoc);
- }
-
- CXXDestructorDecl *DD = RD->getDestructor();
- if (DD) {
- PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
- DD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_lastprivate) << 4;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, DD);
- DiagnoseUseOfDecl(DD, ELoc);
- }
- }
+ Type = Context.getBaseElementType(Type).getNonReferenceType();
+ auto *SrcVD = BuildVarDecl(*this, DE->getLocStart(),
+ Type.getUnqualifiedType(), ".lastprivate.src");
+ auto *PseudoSrcExpr = BuildDeclRefExpr(SrcVD, Type.getUnqualifiedType(),
+ VK_LValue, DE->getExprLoc()).get();
+ auto *DstVD =
+ BuildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst");
+ auto *PseudoDstExpr =
+ BuildDeclRefExpr(DstVD, Type, VK_LValue, DE->getExprLoc()).get();
+ // For arrays generate assignment operation for single element and replace
+ // it by the original array element in CodeGen.
+ auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
+ PseudoDstExpr, PseudoSrcExpr);
+ if (AssignmentOp.isInvalid())
+ continue;
+ AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
+ /*DiscardedValue=*/true);
+ if (AssignmentOp.isInvalid())
+ continue;
if (DVar.CKind != OMPC_firstprivate)
DSAStack->addDSA(VD, DE, OMPC_lastprivate);
Vars.push_back(DE);
+ SrcExprs.push_back(PseudoSrcExpr);
+ DstExprs.push_back(PseudoDstExpr);
+ AssignmentOps.push_back(AssignmentOp.get());
}
if (Vars.empty())
return nullptr;
return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
- Vars);
+ Vars, SrcExprs, DstExprs, AssignmentOps);
}
OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
@@ -4975,19 +5235,19 @@
switch (OOK) {
case OO_Plus:
case OO_Minus:
- BOK = BO_AddAssign;
+ BOK = BO_Add;
break;
case OO_Star:
- BOK = BO_MulAssign;
+ BOK = BO_Mul;
break;
case OO_Amp:
- BOK = BO_AndAssign;
+ BOK = BO_And;
break;
case OO_Pipe:
- BOK = BO_OrAssign;
+ BOK = BO_Or;
break;
case OO_Caret:
- BOK = BO_XorAssign;
+ BOK = BO_Xor;
break;
case OO_AmpAmp:
BOK = BO_LAnd;
@@ -4995,7 +5255,44 @@
case OO_PipePipe:
BOK = BO_LOr;
break;
- default:
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ case OO_Slash:
+ case OO_Percent:
+ case OO_Tilde:
+ case OO_Exclaim:
+ case OO_Equal:
+ case OO_Less:
+ case OO_Greater:
+ case OO_LessEqual:
+ case OO_GreaterEqual:
+ case OO_PlusEqual:
+ case OO_MinusEqual:
+ case OO_StarEqual:
+ case OO_SlashEqual:
+ case OO_PercentEqual:
+ case OO_CaretEqual:
+ case OO_AmpEqual:
+ case OO_PipeEqual:
+ case OO_LessLess:
+ case OO_GreaterGreater:
+ case OO_LessLessEqual:
+ case OO_GreaterGreaterEqual:
+ case OO_EqualEqual:
+ case OO_ExclaimEqual:
+ case OO_PlusPlus:
+ case OO_MinusMinus:
+ case OO_Comma:
+ case OO_ArrowStar:
+ case OO_Arrow:
+ case OO_Call:
+ case OO_Subscript:
+ case OO_Conditional:
+ case NUM_OVERLOADED_OPERATORS:
+ llvm_unreachable("Unexpected reduction identifier");
+ case OO_None:
if (auto II = DN.getAsIdentifierInfo()) {
if (II->isStr("max"))
BOK = BO_GT;
@@ -5017,11 +5314,17 @@
}
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> LHSs;
+ SmallVector<Expr *, 8> RHSs;
+ SmallVector<Expr *, 8> ReductionOps;
for (auto RefExpr : VarList) {
assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ LHSs.push_back(nullptr);
+ RHSs.push_back(nullptr);
+ ReductionOps.push_back(nullptr);
continue;
}
@@ -5030,6 +5333,9 @@
RefExpr->containsUnexpandedParameterPack()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ LHSs.push_back(nullptr);
+ RHSs.push_back(nullptr);
+ ReductionOps.push_back(nullptr);
continue;
}
@@ -5122,23 +5428,6 @@
<< VD;
continue;
}
- bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
- getDiagnostics().setSuppressAllDiagnostics(true);
- ExprResult ReductionOp =
- BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
- RefExpr, RefExpr);
- getDiagnostics().setSuppressAllDiagnostics(Suppress);
- if (ReductionOp.isInvalid()) {
- Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
- << ReductionIdRange;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- continue;
- }
-
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
// Variables with the predetermined data-sharing attributes may not be
@@ -5181,55 +5470,160 @@
continue;
}
}
-
- CXXRecordDecl *RD = getLangOpts().CPlusPlus
- ? Type.getNonReferenceType()->getAsCXXRecordDecl()
- : nullptr;
- // FIXME This code must be replaced by actual constructing/destructing of
- // the reduction variable.
- if (RD) {
- CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
- PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (!CD ||
- CheckConstructorAccess(ELoc, CD,
- InitializedEntity::InitializeTemporary(Type),
- CD->getAccess(), PD) == AR_inaccessible ||
- CD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_reduction) << 0;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
+ Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
+ auto *LHSVD = BuildVarDecl(*this, ELoc, Type, ".reduction.lhs");
+ auto *RHSVD = BuildVarDecl(*this, ELoc, Type, VD->getName());
+ // Add initializer for private variable.
+ Expr *Init = nullptr;
+ switch (BOK) {
+ case BO_Add:
+ case BO_Xor:
+ case BO_Or:
+ case BO_LOr:
+ // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
+ if (Type->isScalarType() || Type->isAnyComplexType()) {
+ Init = ActOnIntegerConstant(ELoc, /*Val=*/0).get();
}
- MarkFunctionReferenced(ELoc, CD);
- DiagnoseUseOfDecl(CD, ELoc);
-
- CXXDestructorDecl *DD = RD->getDestructor();
- if (DD) {
- if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
- DD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_reduction) << 4;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
+ break;
+ case BO_Mul:
+ case BO_LAnd:
+ if (Type->isScalarType() || Type->isAnyComplexType()) {
+ // '*' and '&&' reduction ops - initializer is '1'.
+ Init = ActOnIntegerConstant(ELoc, /*Val=*/1).get();
+ }
+ break;
+ case BO_And: {
+ // '&' reduction op - initializer is '~0'.
+ QualType OrigType = Type;
+ if (auto *ComplexTy = OrigType->getAs<ComplexType>()) {
+ Type = ComplexTy->getElementType();
+ }
+ if (Type->isRealFloatingType()) {
+ llvm::APFloat InitValue =
+ llvm::APFloat::getAllOnesValue(Context.getTypeSize(Type),
+ /*isIEEE=*/true);
+ Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
+ Type, ELoc);
+ } else if (Type->isScalarType()) {
+ auto Size = Context.getTypeSize(Type);
+ QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
+ llvm::APInt InitValue = llvm::APInt::getAllOnesValue(Size);
+ Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
+ }
+ if (Init && OrigType->isAnyComplexType()) {
+ // Init = 0xFFFF + 0xFFFFi;
+ auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
+ Init = CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
+ }
+ Type = OrigType;
+ break;
+ }
+ case BO_LT:
+ case BO_GT: {
+ // 'min' reduction op - initializer is 'Largest representable number in
+ // the reduction list item type'.
+ // 'max' reduction op - initializer is 'Least representable number in
+ // the reduction list item type'.
+ if (Type->isIntegerType() || Type->isPointerType()) {
+ bool IsSigned = Type->hasSignedIntegerRepresentation();
+ auto Size = Context.getTypeSize(Type);
+ QualType IntTy =
+ Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
+ llvm::APInt InitValue =
+ (BOK != BO_LT)
+ ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
+ : llvm::APInt::getMinValue(Size)
+ : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
+ : llvm::APInt::getMaxValue(Size);
+ Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
+ if (Type->isPointerType()) {
+ // Cast to pointer type.
+ auto CastExpr = BuildCStyleCastExpr(
+ SourceLocation(), Context.getTrivialTypeSourceInfo(Type, ELoc),
+ SourceLocation(), Init);
+ if (CastExpr.isInvalid())
+ continue;
+ Init = CastExpr.get();
}
- MarkFunctionReferenced(ELoc, DD);
- DiagnoseUseOfDecl(DD, ELoc);
+ } else if (Type->isRealFloatingType()) {
+ llvm::APFloat InitValue = llvm::APFloat::getLargest(
+ Context.getFloatTypeSemantics(Type), BOK != BO_LT);
+ Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
+ Type, ELoc);
+ }
+ break;
+ }
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_MulAssign:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
+ case BO_Assign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_Comma:
+ llvm_unreachable("Unexpected reduction operation");
+ }
+ if (Init) {
+ AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false,
+ /*TypeMayContainAuto=*/false);
+ } else {
+ ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false);
+ }
+ if (!RHSVD->hasInit()) {
+ Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
+ << ReductionIdRange;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+ auto *LHSDRE = BuildDeclRefExpr(LHSVD, Type, VK_LValue, ELoc).get();
+ auto *RHSDRE = BuildDeclRefExpr(RHSVD, Type, VK_LValue, ELoc).get();
+ ExprResult ReductionOp =
+ BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
+ LHSDRE, RHSDRE);
+ if (ReductionOp.isUsable()) {
+ if (BOK != BO_LOr && BOK != BO_LAnd) {
+ ReductionOp =
+ BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
+ BO_Assign, LHSDRE, ReductionOp.get());
+ } else {
+ auto *ConditionalOp = new (Context) ConditionalOperator(
+ ReductionOp.get(), SourceLocation(), LHSDRE, SourceLocation(),
+ RHSDRE, Type, VK_LValue, OK_Ordinary);
+ ReductionOp =
+ BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
+ BO_Assign, LHSDRE, ConditionalOp);
+ }
+ if (ReductionOp.isUsable()) {
+ ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
}
}
+ if (ReductionOp.isInvalid())
+ continue;
DSAStack->addDSA(VD, DE, OMPC_reduction);
Vars.push_back(DE);
+ LHSs.push_back(LHSDRE);
+ RHSs.push_back(RHSDRE);
+ ReductionOps.push_back(ReductionOp.get());
}
if (Vars.empty())
@@ -5237,7 +5631,8 @@
return OMPReductionClause::Create(
Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
- ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId);
+ ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, LHSs,
+ RHSs, ReductionOps);
}
OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
@@ -5531,11 +5926,17 @@
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> SrcExprs;
+ SmallVector<Expr *, 8> DstExprs;
+ SmallVector<Expr *, 8> AssignmentOps;
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP copyin clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -5557,6 +5958,9 @@
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -5573,40 +5977,38 @@
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- Type = Context.getBaseElementType(Type);
- CXXRecordDecl *RD =
- getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
- // FIXME This code must be replaced by actual assignment of the
- // threadprivate variable.
- if (RD) {
- CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
- DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
- if (MD) {
- if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
- MD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_copyin) << 2;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, MD);
- DiagnoseUseOfDecl(MD, ELoc);
- }
- }
+ Type = Context.getBaseElementType(Type).getNonReferenceType();
+ auto *SrcVD = BuildVarDecl(*this, DE->getLocStart(),
+ Type.getUnqualifiedType(), ".copyin.src");
+ auto *PseudoSrcExpr = BuildDeclRefExpr(SrcVD, Type.getUnqualifiedType(),
+ VK_LValue, DE->getExprLoc())
+ .get();
+ auto *DstVD = BuildVarDecl(*this, DE->getLocStart(), Type, ".copyin.dst");
+ auto *PseudoDstExpr =
+ BuildDeclRefExpr(DstVD, Type, VK_LValue, DE->getExprLoc()).get();
+ // For arrays generate assignment operation for single element and replace
+ // it by the original array element in CodeGen.
+ auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
+ PseudoDstExpr, PseudoSrcExpr);
+ if (AssignmentOp.isInvalid())
+ continue;
+ AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
+ /*DiscardedValue=*/true);
+ if (AssignmentOp.isInvalid())
+ continue;
DSAStack->addDSA(VD, DE, OMPC_copyin);
Vars.push_back(DE);
+ SrcExprs.push_back(PseudoSrcExpr);
+ DstExprs.push_back(PseudoDstExpr);
+ AssignmentOps.push_back(AssignmentOp.get());
}
if (Vars.empty())
return nullptr;
- return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+ return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
+ SrcExprs, DstExprs, AssignmentOps);
}
OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
@@ -5685,14 +6087,15 @@
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- auto *SrcVD = BuildVarDecl(*this, DE->getLocStart(), VD->getType(),
- ".copyprivate.src");
- auto *PseudoSrcExpr = BuildDeclRefExpr(SrcVD, DE->getType(), VK_LValue,
- DE->getExprLoc()).get();
- auto *DstVD = BuildVarDecl(*this, DE->getLocStart(), VD->getType(),
- ".copyprivate.dst");
- auto *PseudoDstExpr = BuildDeclRefExpr(DstVD, DE->getType(), VK_LValue,
- DE->getExprLoc()).get();
+ Type = Context.getBaseElementType(Type).getUnqualifiedType();
+ auto *SrcVD =
+ BuildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src");
+ auto *PseudoSrcExpr =
+ BuildDeclRefExpr(SrcVD, Type, VK_LValue, DE->getExprLoc()).get();
+ auto *DstVD =
+ BuildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst");
+ auto *PseudoDstExpr =
+ BuildDeclRefExpr(DstVD, Type, VK_LValue, DE->getExprLoc()).get();
auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid())
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index fbf110b..8f9401b 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1752,11 +1752,13 @@
return false;
// We can perform an integral promotion to the underlying type of the enum,
- // even if that's not the promoted type.
+ // even if that's not the promoted type. Note that the check for promoting
+ // the underlying type is based on the type alone, and does not consider
+ // the bitfield-ness of the actual source expression.
if (FromEnumType->getDecl()->isFixed()) {
QualType Underlying = FromEnumType->getDecl()->getIntegerType();
return Context.hasSameUnqualifiedType(Underlying, ToType) ||
- IsIntegralPromotion(From, Underlying, ToType);
+ IsIntegralPromotion(nullptr, Underlying, ToType);
}
// We have already pre-calculated the promotion type, so this is trivial.
@@ -2952,7 +2954,10 @@
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
+ switch (auto Result =
+ CandidateSet.BestViableFunction(S, From->getLocStart(),
+ Best, true)) {
+ case OR_Deleted:
case OR_Success: {
// Record the standard conversion we used and the conversion function.
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
@@ -2965,13 +2970,11 @@
User.After.setAsIdentityConversion();
User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
User.After.setAllToTypes(ToType);
- return OR_Success;
+ return Result;
}
case OR_No_Viable_Function:
return OR_No_Viable_Function;
- case OR_Deleted:
- return OR_Deleted;
case OR_Ambiguous:
return OR_Ambiguous;
}
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index 935128b..3e465af 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -1192,7 +1192,7 @@
AtIndexGetter =
S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
RefExpr->getSourceRange(),
- true, false);
+ true);
}
if (AtIndexGetter) {
@@ -1314,7 +1314,7 @@
AtIndexSetter =
S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
RefExpr->getSourceRange(),
- true, false);
+ true);
}
bool err = false;
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index f923f61..ed5da43 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
@@ -23,12 +24,14 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeOrdering.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -236,7 +239,9 @@
// is written in a macro body, only warn if it has the warn_unused_result
// attribute.
if (const Decl *FD = CE->getCalleeDecl()) {
- if (FD->hasAttr<WarnUnusedResultAttr>()) {
+ const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
+ if (Func ? Func->hasUnusedResultAttr()
+ : FD->hasAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
return;
}
@@ -1133,29 +1138,15 @@
Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default);
// Produce a nice diagnostic if multiple values aren't handled.
- switch (UnhandledNames.size()) {
- case 0: break;
- case 1:
- Diag(CondExpr->getExprLoc(), TheDefaultStmt
- ? diag::warn_def_missing_case1 : diag::warn_missing_case1)
- << UnhandledNames[0];
- break;
- case 2:
- Diag(CondExpr->getExprLoc(), TheDefaultStmt
- ? diag::warn_def_missing_case2 : diag::warn_missing_case2)
- << UnhandledNames[0] << UnhandledNames[1];
- break;
- case 3:
- Diag(CondExpr->getExprLoc(), TheDefaultStmt
- ? diag::warn_def_missing_case3 : diag::warn_missing_case3)
- << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
- break;
- default:
- Diag(CondExpr->getExprLoc(), TheDefaultStmt
- ? diag::warn_def_missing_cases : diag::warn_missing_cases)
- << (unsigned)UnhandledNames.size()
- << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
- break;
+ if (!UnhandledNames.empty()) {
+ DiagnosticBuilder DB = Diag(CondExpr->getExprLoc(),
+ TheDefaultStmt ? diag::warn_def_missing_case
+ : diag::warn_missing_case)
+ << (int)UnhandledNames.size();
+
+ for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3);
+ I != E; ++I)
+ DB << UnhandledNames[I];
}
if (!hasCasesNotInSwitch)
@@ -2373,6 +2364,156 @@
return S;
}
+// Warn when the loop variable is a const reference that creates a copy.
+// Suggest using the non-reference type for copies. If a copy can be prevented
+// suggest the const reference type that would do so.
+// For instance, given "for (const &Foo : Range)", suggest
+// "for (const Foo : Range)" to denote a copy is made for the loop. If
+// possible, also suggest "for (const &Bar : Range)" if this type prevents
+// the copy altogether.
+static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
+ const VarDecl *VD,
+ QualType RangeInitType) {
+ const Expr *InitExpr = VD->getInit();
+ if (!InitExpr)
+ return;
+
+ QualType VariableType = VD->getType();
+
+ const MaterializeTemporaryExpr *MTE =
+ dyn_cast<MaterializeTemporaryExpr>(InitExpr);
+
+ // No copy made.
+ if (!MTE)
+ return;
+
+ const Expr *E = MTE->GetTemporaryExpr()->IgnoreImpCasts();
+
+ // Searching for either UnaryOperator for dereference of a pointer or
+ // CXXOperatorCallExpr for handling iterators.
+ while (!isa<CXXOperatorCallExpr>(E) && !isa<UnaryOperator>(E)) {
+ if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(E)) {
+ E = CCE->getArg(0);
+ } else if (const CXXMemberCallExpr *Call = dyn_cast<CXXMemberCallExpr>(E)) {
+ const MemberExpr *ME = cast<MemberExpr>(Call->getCallee());
+ E = ME->getBase();
+ } else {
+ const MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(E);
+ E = MTE->GetTemporaryExpr();
+ }
+ E = E->IgnoreImpCasts();
+ }
+
+ bool ReturnsReference = false;
+ if (isa<UnaryOperator>(E)) {
+ ReturnsReference = true;
+ } else {
+ const CXXOperatorCallExpr *Call = cast<CXXOperatorCallExpr>(E);
+ const FunctionDecl *FD = Call->getDirectCallee();
+ QualType ReturnType = FD->getReturnType();
+ ReturnsReference = ReturnType->isReferenceType();
+ }
+
+ if (ReturnsReference) {
+ // Loop variable creates a temporary. Suggest either to go with
+ // non-reference loop variable to indiciate a copy is made, or
+ // the correct time to bind a const reference.
+ SemaRef.Diag(VD->getLocation(), diag::warn_for_range_const_reference_copy)
+ << VD << VariableType << E->getType();
+ QualType NonReferenceType = VariableType.getNonReferenceType();
+ NonReferenceType.removeLocalConst();
+ QualType NewReferenceType =
+ SemaRef.Context.getLValueReferenceType(E->getType().withConst());
+ SemaRef.Diag(VD->getLocStart(), diag::note_use_type_or_non_reference)
+ << NonReferenceType << NewReferenceType << VD->getSourceRange();
+ } else {
+ // The range always returns a copy, so a temporary is always created.
+ // Suggest removing the reference from the loop variable.
+ SemaRef.Diag(VD->getLocation(), diag::warn_for_range_variable_always_copy)
+ << VD << RangeInitType;
+ QualType NonReferenceType = VariableType.getNonReferenceType();
+ NonReferenceType.removeLocalConst();
+ SemaRef.Diag(VD->getLocStart(), diag::note_use_non_reference_type)
+ << NonReferenceType << VD->getSourceRange();
+ }
+}
+
+// Warns when the loop variable can be changed to a reference type to
+// prevent a copy. For instance, if given "for (const Foo x : Range)" suggest
+// "for (const Foo &x : Range)" if this form does not make a copy.
+static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
+ const VarDecl *VD) {
+ const Expr *InitExpr = VD->getInit();
+ if (!InitExpr)
+ return;
+
+ QualType VariableType = VD->getType();
+
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitExpr)) {
+ if (!CE->getConstructor()->isCopyConstructor())
+ return;
+ } else if (const CastExpr *CE = dyn_cast<CastExpr>(InitExpr)) {
+ if (CE->getCastKind() != CK_LValueToRValue)
+ return;
+ } else {
+ return;
+ }
+
+ // TODO: Determine a maximum size that a POD type can be before a diagnostic
+ // should be emitted. Also, only ignore POD types with trivial copy
+ // constructors.
+ if (VariableType.isPODType(SemaRef.Context))
+ return;
+
+ // Suggest changing from a const variable to a const reference variable
+ // if doing so will prevent a copy.
+ SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy)
+ << VD << VariableType << InitExpr->getType();
+ SemaRef.Diag(VD->getLocStart(), diag::note_use_reference_type)
+ << SemaRef.Context.getLValueReferenceType(VariableType)
+ << VD->getSourceRange();
+}
+
+/// DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them.
+/// 1) for (const foo &x : foos) where foos only returns a copy. Suggest
+/// using "const foo x" to show that a copy is made
+/// 2) for (const bar &x : foos) where bar is a temporary intialized by bar.
+/// Suggest either "const bar x" to keep the copying or "const foo& x" to
+/// prevent the copy.
+/// 3) for (const foo x : foos) where x is constructed from a reference foo.
+/// Suggest "const foo &x" to prevent the copy.
+static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
+ const CXXForRangeStmt *ForStmt) {
+ if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy,
+ ForStmt->getLocStart()) &&
+ SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy,
+ ForStmt->getLocStart()) &&
+ SemaRef.Diags.isIgnored(diag::warn_for_range_copy,
+ ForStmt->getLocStart())) {
+ return;
+ }
+
+ const VarDecl *VD = ForStmt->getLoopVariable();
+ if (!VD)
+ return;
+
+ QualType VariableType = VD->getType();
+
+ if (VariableType->isIncompleteType())
+ return;
+
+ const Expr *InitExpr = VD->getInit();
+ if (!InitExpr)
+ return;
+
+ if (VariableType->isReferenceType()) {
+ DiagnoseForRangeReferenceVariableCopies(SemaRef, VD,
+ ForStmt->getRangeInit()->getType());
+ } else if (VariableType.isConstQualified()) {
+ DiagnoseForRangeConstVariableCopies(SemaRef, VD);
+ }
+}
+
/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement.
/// This is a separate step from ActOnCXXForRangeStmt because analysis of the
/// body cannot be performed until after the type of the range variable is
@@ -2390,6 +2531,8 @@
DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B,
diag::warn_empty_range_based_for_body);
+ DiagnoseForRangeVariableCopies(*this, ForStmt);
+
return S;
}
@@ -3267,36 +3410,111 @@
return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
}
-namespace {
+class CatchHandlerType {
+ QualType QT;
+ unsigned IsPointer : 1;
-class TypeWithHandler {
- QualType t;
- CXXCatchStmt *stmt;
+ // This is a special constructor to be used only with DenseMapInfo's
+ // getEmptyKey() and getTombstoneKey() functions.
+ friend struct llvm::DenseMapInfo<CatchHandlerType>;
+ enum Unique { ForDenseMap };
+ CatchHandlerType(QualType QT, Unique) : QT(QT), IsPointer(false) {}
+
public:
- TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
- : t(type), stmt(statement) {}
+ /// Used when creating a CatchHandlerType from a handler type; will determine
+ /// whether the type is a pointer or reference and will strip off the the top
+ /// level pointer and cv-qualifiers.
+ CatchHandlerType(QualType Q) : QT(Q), IsPointer(false) {
+ if (QT->isPointerType())
+ IsPointer = true;
- // An arbitrary order is fine as long as it places identical
- // types next to each other.
- bool operator<(const TypeWithHandler &y) const {
- if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr())
- return true;
- if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr())
+ if (IsPointer || QT->isReferenceType())
+ QT = QT->getPointeeType();
+ QT = QT.getUnqualifiedType();
+ }
+
+ /// Used when creating a CatchHandlerType from a base class type; pretends the
+ /// type passed in had the pointer qualifier, does not need to get an
+ /// unqualified type.
+ CatchHandlerType(QualType QT, bool IsPointer)
+ : QT(QT), IsPointer(IsPointer) {}
+
+ QualType underlying() const { return QT; }
+ bool isPointer() const { return IsPointer; }
+
+ friend bool operator==(const CatchHandlerType &LHS,
+ const CatchHandlerType &RHS) {
+ // If the pointer qualification does not match, we can return early.
+ if (LHS.IsPointer != RHS.IsPointer)
return false;
- else
- return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
- }
-
- bool operator==(const TypeWithHandler& other) const {
- return t == other.t;
- }
-
- CXXCatchStmt *getCatchStmt() const { return stmt; }
- SourceLocation getTypeSpecStartLoc() const {
- return stmt->getExceptionDecl()->getTypeSpecStartLoc();
+ // Otherwise, check the underlying type without cv-qualifiers.
+ return LHS.QT == RHS.QT;
}
};
+namespace llvm {
+template <> struct DenseMapInfo<CatchHandlerType> {
+ static CatchHandlerType getEmptyKey() {
+ return CatchHandlerType(DenseMapInfo<QualType>::getEmptyKey(),
+ CatchHandlerType::ForDenseMap);
+ }
+
+ static CatchHandlerType getTombstoneKey() {
+ return CatchHandlerType(DenseMapInfo<QualType>::getTombstoneKey(),
+ CatchHandlerType::ForDenseMap);
+ }
+
+ static unsigned getHashValue(const CatchHandlerType &Base) {
+ return DenseMapInfo<QualType>::getHashValue(Base.underlying());
+ }
+
+ static bool isEqual(const CatchHandlerType &LHS,
+ const CatchHandlerType &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// It's OK to treat CatchHandlerType as a POD type.
+template <> struct isPodLike<CatchHandlerType> {
+ static const bool value = true;
+};
+}
+
+namespace {
+class CatchTypePublicBases {
+ ASTContext &Ctx;
+ const llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> &TypesToCheck;
+ const bool CheckAgainstPointer;
+
+ CXXCatchStmt *FoundHandler;
+ CanQualType FoundHandlerType;
+
+public:
+ CatchTypePublicBases(
+ ASTContext &Ctx,
+ const llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> &T, bool C)
+ : Ctx(Ctx), TypesToCheck(T), CheckAgainstPointer(C),
+ FoundHandler(nullptr) {}
+
+ CXXCatchStmt *getFoundHandler() const { return FoundHandler; }
+ CanQualType getFoundHandlerType() const { return FoundHandlerType; }
+
+ static bool FindPublicBasesOfType(const CXXBaseSpecifier *S, CXXBasePath &,
+ void *User) {
+ auto &PBOT = *reinterpret_cast<CatchTypePublicBases *>(User);
+ if (S->getAccessSpecifier() == AccessSpecifier::AS_public) {
+ CatchHandlerType Check(S->getType(), PBOT.CheckAgainstPointer);
+ auto M = PBOT.TypesToCheck;
+ auto I = M.find(Check);
+ if (I != M.end()) {
+ PBOT.FoundHandler = I->second;
+ PBOT.FoundHandlerType = PBOT.Ctx.getCanonicalType(S->getType());
+ return true;
+ }
+ }
+ return false;
+ }
+};
}
/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
@@ -3306,7 +3524,7 @@
// Don't report an error if 'try' is used in system headers.
if (!getLangOpts().CXXExceptions &&
!getSourceManager().isInSystemHeader(TryLoc))
- Diag(TryLoc, diag::err_exceptions_disabled) << "try";
+ Diag(TryLoc, diag::err_exceptions_disabled) << "try";
if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";
@@ -3320,55 +3538,74 @@
}
const unsigned NumHandlers = Handlers.size();
- assert(NumHandlers > 0 &&
+ assert(!Handlers.empty() &&
"The parser shouldn't call this if there are no handlers.");
- SmallVector<TypeWithHandler, 8> TypesWithHandlers;
-
+ llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> HandledTypes;
for (unsigned i = 0; i < NumHandlers; ++i) {
- CXXCatchStmt *Handler = cast<CXXCatchStmt>(Handlers[i]);
- if (!Handler->getExceptionDecl()) {
- if (i < NumHandlers - 1)
- return StmtError(Diag(Handler->getLocStart(),
- diag::err_early_catch_all));
+ CXXCatchStmt *H = cast<CXXCatchStmt>(Handlers[i]);
+ // Diagnose when the handler is a catch-all handler, but it isn't the last
+ // handler for the try block. [except.handle]p5. Also, skip exception
+ // declarations that are invalid, since we can't usefully report on them.
+ if (!H->getExceptionDecl()) {
+ if (i < NumHandlers - 1)
+ return StmtError(Diag(H->getLocStart(), diag::err_early_catch_all));
continue;
+ } else if (H->getExceptionDecl()->isInvalidDecl())
+ continue;
+
+ // Walk the type hierarchy to diagnose when this type has already been
+ // handled (duplication), or cannot be handled (derivation inversion). We
+ // ignore top-level cv-qualifiers, per [except.handle]p3
+ CatchHandlerType HandlerCHT =
+ (QualType)Context.getCanonicalType(H->getCaughtType());
+
+ // We can ignore whether the type is a reference or a pointer; we need the
+ // underlying declaration type in order to get at the underlying record
+ // decl, if there is one.
+ QualType Underlying = HandlerCHT.underlying();
+ if (auto *RD = Underlying->getAsCXXRecordDecl()) {
+ if (!RD->hasDefinition())
+ continue;
+ // Check that none of the public, unambiguous base classes are in the
+ // map ([except.handle]p1). Give the base classes the same pointer
+ // qualification as the original type we are basing off of. This allows
+ // comparison against the handler type using the same top-level pointer
+ // as the original type.
+ CXXBasePaths Paths;
+ Paths.setOrigin(RD);
+ CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer());
+ if (RD->lookupInBases(CatchTypePublicBases::FindPublicBasesOfType, &CTPB,
+ Paths)) {
+ const CXXCatchStmt *Problem = CTPB.getFoundHandler();
+ if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) {
+ Diag(H->getExceptionDecl()->getTypeSpecStartLoc(),
+ diag::warn_exception_caught_by_earlier_handler)
+ << H->getCaughtType();
+ Diag(Problem->getExceptionDecl()->getTypeSpecStartLoc(),
+ diag::note_previous_exception_handler)
+ << Problem->getCaughtType();
+ }
+ }
}
- const QualType CaughtType = Handler->getCaughtType();
- const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType);
- TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler));
- }
-
- // Detect handlers for the same type as an earlier one.
- if (NumHandlers > 1) {
- llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end());
-
- TypeWithHandler prev = TypesWithHandlers[0];
- for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) {
- TypeWithHandler curr = TypesWithHandlers[i];
-
- if (curr == prev) {
- Diag(curr.getTypeSpecStartLoc(),
- diag::warn_exception_caught_by_earlier_handler)
- << curr.getCatchStmt()->getCaughtType().getAsString();
- Diag(prev.getTypeSpecStartLoc(),
- diag::note_previous_exception_handler)
- << prev.getCatchStmt()->getCaughtType().getAsString();
- }
-
- prev = curr;
+ // Add the type the list of ones we have handled; diagnose if we've already
+ // handled it.
+ auto R = HandledTypes.insert(std::make_pair(H->getCaughtType(), H));
+ if (!R.second) {
+ const CXXCatchStmt *Problem = R.first->second;
+ Diag(H->getExceptionDecl()->getTypeSpecStartLoc(),
+ diag::warn_exception_caught_by_earlier_handler)
+ << H->getCaughtType();
+ Diag(Problem->getExceptionDecl()->getTypeSpecStartLoc(),
+ diag::note_previous_exception_handler)
+ << Problem->getCaughtType();
}
}
FSI->setHasCXXTry(TryLoc);
- // FIXME: We should detect handlers that cannot catch anything because an
- // earlier handler catches a superclass. Need to find a method that is not
- // quadratic for this.
- // Neither of these are explicitly forbidden, but every compiler detects them
- // and warns.
-
return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers);
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 8e4fe85..f93a848 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1747,7 +1747,7 @@
const MultiLevelTemplateArgumentList &TemplateArgs) {
bool Invalid = false;
SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
- for (const auto Base : Pattern->bases()) {
+ for (const auto &Base : Pattern->bases()) {
if (!Base.getType()->isDependentType()) {
if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) {
if (RD->isInvalidDecl())
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index e4fab71..fd3ba35 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -251,15 +251,10 @@
Locations.push_back(Unexpanded[I].second);
}
- DiagnosticBuilder DB
- = Names.size() == 0? Diag(Loc, diag::err_unexpanded_parameter_pack_0)
- << (int)UPPC
- : Names.size() == 1? Diag(Loc, diag::err_unexpanded_parameter_pack_1)
- << (int)UPPC << Names[0]
- : Names.size() == 2? Diag(Loc, diag::err_unexpanded_parameter_pack_2)
- << (int)UPPC << Names[0] << Names[1]
- : Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
- << (int)UPPC << Names[0] << Names[1];
+ DiagnosticBuilder DB = Diag(Loc, diag::err_unexpanded_parameter_pack)
+ << (int)UPPC << (int)Names.size();
+ for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I)
+ DB << Names[I];
for (unsigned I = 0, N = Locations.size(); I != N; ++I)
DB << SourceRange(Locations[I]);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 485b70a..5a6cc2e 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2483,6 +2483,10 @@
// in a member pointer.
IsCXXInstanceMethod =
D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
+ } else if (D.getContext() == Declarator::LambdaExprContext) {
+ // This can only be a call operator for a lambda, which is an instance
+ // method.
+ IsCXXInstanceMethod = true;
} else {
// We're the innermost decl chunk, so must be a function declarator.
assert(D.isFunctionDeclarator());
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 1b0080a..df0e4b3 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2623,6 +2623,31 @@
RBracLoc, Args);
}
+ /// \brief Build a new Objective-C instance/class message to 'super'.
+ ExprResult RebuildObjCMessageExpr(SourceLocation SuperLoc,
+ Selector Sel,
+ ArrayRef<SourceLocation> SelectorLocs,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ MultiExprArg Args,
+ SourceLocation RBracLoc) {
+ ObjCInterfaceDecl *Class = Method->getClassInterface();
+ QualType ReceiverTy = SemaRef.Context.getObjCInterfaceType(Class);
+
+ return Method->isInstanceMethod() ? SemaRef.BuildInstanceMessage(nullptr,
+ ReceiverTy,
+ SuperLoc,
+ Sel, Method, LBracLoc, SelectorLocs,
+ RBracLoc, Args)
+ : SemaRef.BuildClassMessage(nullptr,
+ ReceiverTy,
+ SuperLoc,
+ Sel, Method, LBracLoc, SelectorLocs,
+ RBracLoc, Args);
+
+
+ }
+
/// \brief Build a new Objective-C ivar reference expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -6645,7 +6670,16 @@
if (!D->getAssociatedStmt()) {
return StmtError();
}
- AssociatedStmt = getDerived().TransformStmt(D->getAssociatedStmt());
+ getDerived().getSema().ActOnOpenMPRegionStart(D->getDirectiveKind(),
+ /*CurScope=*/nullptr);
+ StmtResult Body;
+ {
+ Sema::CompoundScopeRAII CompoundScope(getSema());
+ Body = getDerived().TransformStmt(
+ cast<CapturedStmt>(D->getAssociatedStmt())->getCapturedStmt());
+ }
+ AssociatedStmt =
+ getDerived().getSema().ActOnOpenMPRegionEnd(Body, TClauses);
if (AssociatedStmt.isInvalid()) {
return StmtError();
}
@@ -10047,6 +10081,19 @@
Args,
E->getRightLoc());
}
+ else if (E->getReceiverKind() == ObjCMessageExpr::SuperClass ||
+ E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
+ // Build a new class message send to 'super'.
+ SmallVector<SourceLocation, 16> SelLocs;
+ E->getSelectorLocs(SelLocs);
+ return getDerived().RebuildObjCMessageExpr(E->getSuperLoc(),
+ E->getSelector(),
+ SelLocs,
+ E->getMethodDecl(),
+ E->getLeftLoc(),
+ Args,
+ E->getRightLoc());
+ }
// Instance message: transform the receiver
assert(E->getReceiverKind() == ObjCMessageExpr::Instance &&
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 4d5141b..d26ed222 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -3354,11 +3354,6 @@
break;
}
- case MACRO_TABLE: {
- // FIXME: Not used yet.
- break;
- }
-
case LATE_PARSED_TEMPLATE: {
LateParsedTemplates.append(Record.begin(), Record.end());
break;
@@ -6730,20 +6725,14 @@
// individually, because finding an entity in one of them doesn't imply that
// we can't find a different entity in another one.
if (isa<CXXRecordDecl>(DC)) {
- auto Kind = Name.getNameKind();
- if (Kind == DeclarationName::CXXConstructorName ||
- Kind == DeclarationName::CXXDestructorName ||
- (Kind == DeclarationName::CXXOperatorName &&
- Name.getCXXOverloadedOperator() == OO_Equal)) {
- auto Merged = MergedLookups.find(DC);
- if (Merged != MergedLookups.end()) {
- for (unsigned I = 0; I != Merged->second.size(); ++I) {
- const DeclContext *Context = Merged->second[I];
- LookUpInContexts(Context);
- // We might have just added some more merged lookups. If so, our
- // iterator is now invalid, so grab a fresh one before continuing.
- Merged = MergedLookups.find(DC);
- }
+ auto Merged = MergedLookups.find(DC);
+ if (Merged != MergedLookups.end()) {
+ for (unsigned I = 0; I != Merged->second.size(); ++I) {
+ const DeclContext *Context = Merged->second[I];
+ LookUpInContexts(Context);
+ // We might have just added some more merged lookups. If so, our
+ // iterator is now invalid, so grab a fresh one before continuing.
+ Merged = MergedLookups.find(DC);
}
}
}
@@ -8679,7 +8668,10 @@
if (It != PendingFakeLookupResults.end()) {
for (auto *ND : PendingFakeLookupResults[II])
SemaObj->IdResolver.RemoveDecl(ND);
- PendingFakeLookupResults.erase(It);
+ // FIXME: this works around module+PCH performance issue.
+ // Rather than erase the result from the map, which is O(n), just clear
+ // the vector of NamedDecls.
+ It->second.clear();
}
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index de2c625..5e911b4 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1385,6 +1385,29 @@
"merging class definition into non-definition");
auto &DD = *D->DefinitionData.getNotUpdated();
+ // If the new definition has new special members, let the name lookup
+ // code know that it needs to look in the new definition too.
+ //
+ // FIXME: We only need to do this if the merged definition declares members
+ // that this definition did not declare, or if it defines members that this
+ // definition did not define.
+ if (DD.Definition != MergeDD.Definition) {
+ Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
+ DD.Definition->setHasExternalVisibleStorage();
+
+ if (DD.Definition->isHidden()) {
+ // If MergeDD is visible or becomes visible, make the definition visible.
+ if (!MergeDD.Definition->isHidden())
+ DD.Definition->Hidden = false;
+ else {
+ auto SubmoduleID = MergeDD.Definition->getOwningModuleID();
+ assert(SubmoduleID && "hidden definition in no module");
+ Reader.HiddenNamesMap[Reader.getSubmodule(SubmoduleID)]
+ .HiddenDecls.push_back(DD.Definition);
+ }
+ }
+ }
+
auto PFDI = Reader.PendingFakeDefinitionData.find(&DD);
if (PFDI != Reader.PendingFakeDefinitionData.end() &&
PFDI->second == ASTReader::PendingFakeDefinitionKind::Fake) {
@@ -1401,17 +1424,6 @@
return;
}
- // If the new definition has new special members, let the name lookup
- // code know that it needs to look in the new definition too.
- //
- // FIXME: We only need to do this if the merged definition declares members
- // that this definition did not declare, or if it defines members that this
- // definition did not define.
- if (MergeDD.DeclaredSpecialMembers && DD.Definition != MergeDD.Definition) {
- Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
- DD.Definition->setHasExternalVisibleStorage();
- }
-
// FIXME: Move this out into a .def file?
bool DetectedOdrViolation = false;
#define OR_FIELD(Field) DD.Field |= MergeDD.Field;
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index c7b49de..57728c1 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -1889,6 +1889,22 @@
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setPrivateCopies(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setSourceExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setDestinationExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setAssignmentOps(Vars);
}
void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
@@ -1917,6 +1933,18 @@
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setLHSExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setRHSExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setReductionOps(Vars);
}
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
@@ -1959,11 +1987,23 @@
void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
+ SmallVector<Expr *, 16> Exprs;
+ Exprs.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
- C->setVarRefs(Vars);
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setSourceExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setDestinationExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setAssignmentOps(Exprs);
}
void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
@@ -2157,11 +2197,12 @@
// The NumClauses field was read in ReadStmtFromStream.
++Idx;
VisitOMPExecutableDirective(D);
- D->setOpKind(static_cast<BinaryOperatorKind>(Record[Idx++]));
D->setX(Reader.ReadSubExpr());
- D->setXRVal(Reader.ReadSubExpr());
D->setV(Reader.ReadSubExpr());
D->setExpr(Reader.ReadSubExpr());
+ D->setUpdateExpr(Reader.ReadSubExpr());
+ D->IsXLHSInRHSPart = Record[Idx++] != 0;
+ D->IsPostfixUpdate = Record[Idx++] != 0;
}
void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) {
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index eccff9d..df05f04 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -927,7 +927,6 @@
RECORD(LOCAL_REDECLARATIONS);
RECORD(OBJC_CATEGORIES);
RECORD(MACRO_OFFSET);
- RECORD(MACRO_TABLE);
RECORD(LATE_PARSED_TEMPLATE);
RECORD(OPTIMIZE_PRAGMA_OPTIONS);
@@ -2083,13 +2082,10 @@
llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(),
&compareMacroDirectives);
- llvm::OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator;
-
// Emit the macro directives as a list and associate the offset with the
// identifier they belong to.
for (unsigned I = 0, N = MacroDirectives.size(); I != N; ++I) {
const IdentifierInfo *Name = MacroDirectives[I].first;
- uint64_t MacroDirectiveOffset = Stream.GetCurrentBitNo();
MacroDirective *MD = MacroDirectives[I].second;
// If the macro or identifier need no updates, don't write the macro history
@@ -2127,15 +2123,9 @@
if (Record.empty())
continue;
+ IdentMacroDirectivesOffsetMap[Name] = Stream.GetCurrentBitNo();
Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record);
Record.clear();
-
- IdentMacroDirectivesOffsetMap[Name] = MacroDirectiveOffset;
-
- IdentID NameID = getIdentifierRef(Name);
- ASTMacroTableTrait::Data data;
- data.MacroDirectivesOffset = MacroDirectiveOffset;
- Generator.insert(NameID, data);
}
/// \brief Offsets of each of the macros into the bitstream, indexed by
@@ -2211,33 +2201,9 @@
Stream.ExitBlock();
- // Create the on-disk hash table in a buffer.
- SmallString<4096> MacroTable;
- uint32_t BucketOffset;
- {
- using namespace llvm::support;
- llvm::raw_svector_ostream Out(MacroTable);
- // Make sure that no bucket is at offset 0
- endian::Writer<little>(Out).write<uint32_t>(0);
- BucketOffset = Generator.Emit(Out);
- }
-
- // Write the macro table
- using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(MACRO_TABLE));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
- unsigned MacroTableAbbrev = Stream.EmitAbbrev(Abbrev);
-
- Record.push_back(MACRO_TABLE);
- Record.push_back(BucketOffset);
- Stream.EmitRecordWithBlob(MacroTableAbbrev, Record, MacroTable);
- Record.clear();
-
// Write the offsets table for macro IDs.
using namespace llvm;
- Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 3632672..608aa59 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -994,13 +994,16 @@
std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
for (auto &NameAndResult : LookupResults) {
DeclarationName Name = NameAndResult.first;
- (void)Name;
- assert(Name.getNameKind() != DeclarationName::CXXConstructorName &&
- "Cannot have a constructor name in a namespace!");
- assert(Name.getNameKind() != DeclarationName::CXXConversionFunctionName &&
- "Cannot have a conversion function name in a namespace!");
-
DeclContext::lookup_result Result = NameAndResult.second;
+ if (Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+ // We have to work around a name lookup bug here where negative lookup
+ // results for these names get cached in namespace lookup tables.
+ assert(Result.empty() && "Cannot have a constructor or conversion "
+ "function name in a namespace!");
+ continue;
+ }
+
for (NamedDecl *ND : Result)
Writer.GetDeclRef(ND);
}
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 6e647c3..f15f76c 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -1798,6 +1798,14 @@
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
for (auto *VE : C->varlists())
Writer->Writer.AddStmt(VE);
+ for (auto *E : C->private_copies())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->source_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->destination_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->assignment_ops())
+ Writer->Writer.AddStmt(E);
}
void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
@@ -1815,6 +1823,12 @@
Writer->Writer.AddDeclarationNameInfo(C->getNameInfo(), Record);
for (auto *VE : C->varlists())
Writer->Writer.AddStmt(VE);
+ for (auto *E : C->lhs_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->rhs_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->reduction_ops())
+ Writer->Writer.AddStmt(E);
}
void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
@@ -1851,6 +1865,12 @@
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
for (auto *VE : C->varlists())
Writer->Writer.AddStmt(VE);
+ for (auto *E : C->source_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->destination_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->assignment_ops())
+ Writer->Writer.AddStmt(E);
}
void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
@@ -2005,11 +2025,12 @@
VisitStmt(D);
Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
- Record.push_back(D->getOpKind());
Writer.AddStmt(D->getX());
- Writer.AddStmt(D->getXRVal());
Writer.AddStmt(D->getV());
Writer.AddStmt(D->getExpr());
+ Writer.AddStmt(D->getUpdateExpr());
+ Record.push_back(D->isXLHSInRHSPart() ? 1 : 0);
+ Record.push_back(D->isPostfixUpdate() ? 1 : 0);
Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE;
}
diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index c1ea767..f4be5b3 100644
--- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -142,7 +142,7 @@
: cfg(cfg), Ctx(ctx), BR(br), Checker(checker), AC(ac), Parents(parents),
Escaped(escaped), currentBlock(nullptr) {}
- virtual ~DeadStoreObs() {}
+ ~DeadStoreObs() override {}
bool isLive(const LiveVariables::LivenessValues &Live, const VarDecl *D) {
if (Live.isLive(D))
diff --git a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index 0d73160..52e2936 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -137,7 +137,7 @@
public:
SecKeychainBugVisitor(SymbolRef S) : Sym(S) {}
- virtual ~SecKeychainBugVisitor() {}
+ ~SecKeychainBugVisitor() override {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int X = 0;
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 4155998..0cf0094 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -50,6 +50,8 @@
class RefState {
enum Kind { // Reference to allocated memory.
Allocated,
+ // Reference to zero-allocated memory.
+ AllocatedOfSizeZero,
// Reference to released/freed memory.
Released,
// The responsibility for freeing resources has transferred from
@@ -62,8 +64,8 @@
};
const Stmt *S;
- unsigned K : 2; // Kind enum, but stored as a bitfield.
- unsigned Family : 30; // Rest of 32-bit word, currently just an allocation
+ unsigned K : 3; // Kind enum, but stored as a bitfield.
+ unsigned Family : 29; // Rest of 32-bit word, currently just an allocation
// family.
RefState(Kind k, const Stmt *s, unsigned family)
@@ -72,6 +74,7 @@
}
public:
bool isAllocated() const { return K == Allocated; }
+ bool isAllocatedOfSizeZero() const { return K == AllocatedOfSizeZero; }
bool isReleased() const { return K == Released; }
bool isRelinquished() const { return K == Relinquished; }
bool isEscaped() const { return K == Escaped; }
@@ -87,6 +90,10 @@
static RefState getAllocated(unsigned family, const Stmt *s) {
return RefState(Allocated, s, family);
}
+ static RefState getAllocatedOfSizeZero(const RefState *RS) {
+ return RefState(AllocatedOfSizeZero, RS->getStmt(),
+ RS->getAllocationFamily());
+ }
static RefState getReleased(unsigned family, const Stmt *s) {
return RefState(Released, s, family);
}
@@ -107,6 +114,7 @@
switch (static_cast<Kind>(K)) {
#define CASE(ID) case ID: OS << #ID; break;
CASE(Allocated)
+ CASE(AllocatedOfSizeZero)
CASE(Released)
CASE(Relinquished)
CASE(Escaped)
@@ -222,6 +230,7 @@
mutable std::unique_ptr<BugType> BT_FreeAlloca[CK_NumCheckKinds];
mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
+ mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
mutable IdentifierInfo *II_alloca, *II_malloc, *II_free, *II_realloc,
*II_calloc, *II_valloc, *II_reallocf, *II_strndup,
*II_strdup, *II_kmalloc, *II_if_nameindex,
@@ -257,6 +266,12 @@
MemoryOperationKind MemKind) const;
bool isStandardNewDelete(const FunctionDecl *FD, ASTContext &C) const;
///@}
+
+ /// \brief Perform a zero-allocation check.
+ ProgramStateRef ProcessZeroAllocation(CheckerContext &C, const Expr *E,
+ const unsigned AllocationSizeArg,
+ ProgramStateRef State) const;
+
ProgramStateRef MallocMemReturnsAttr(CheckerContext &C,
const CallExpr *CE,
const OwnershipAttr* Att,
@@ -307,6 +322,9 @@
bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
+ void checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
+ const Stmt *S) const;
+
bool checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const;
/// Check if the function is known free memory, or if it is
@@ -361,6 +379,9 @@
void ReportDoubleDelete(CheckerContext &C, SymbolRef Sym) const;
+ void ReportUseZeroAllocated(CheckerContext &C, SourceRange Range,
+ SymbolRef Sym) const;
+
/// Find the location of the allocation for Sym on the path leading to the
/// exploded node N.
LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
@@ -393,7 +414,7 @@
MallocBugVisitor(SymbolRef S, bool isLeak = false)
: Sym(S), Mode(Normal), FailedReallocSymbol(nullptr), IsLeak(isLeak) {}
- virtual ~MallocBugVisitor() {}
+ ~MallocBugVisitor() override {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int X = 0;
@@ -405,7 +426,9 @@
const Stmt *Stmt) {
// Did not track -> allocated. Other state (released) -> allocated.
return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
- (S && S->isAllocated()) && (!SPrev || !SPrev->isAllocated()));
+ (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
+ (!SPrev || !(SPrev->isAllocated() ||
+ SPrev->isAllocatedOfSizeZero())));
}
inline bool isReleased(const RefState *S, const RefState *SPrev,
@@ -431,7 +454,9 @@
// check. If we have to handle more cases here, it might be cleaner just
// to track this extra bit in the state itself.
return ((!Stmt || !isa<CallExpr>(Stmt)) &&
- (S && S->isAllocated()) && (SPrev && !SPrev->isAllocated()));
+ (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
+ (SPrev && !(SPrev->isAllocated() ||
+ SPrev->isAllocatedOfSizeZero())));
}
PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
@@ -730,6 +755,8 @@
return;
if (CE->getNumArgs() < 3) {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
+ if (CE->getNumArgs() == 1)
+ State = ProcessZeroAllocation(C, CE, 0, State);
} else if (CE->getNumArgs() == 3) {
llvm::Optional<ProgramStateRef> MaybeState =
performKernelMalloc(CE, C, State);
@@ -749,12 +776,17 @@
if (CE->getNumArgs() < 1)
return;
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
+ State = ProcessZeroAllocation(C, CE, 0, State);
} else if (FunI == II_realloc) {
State = ReallocMem(C, CE, false, State);
+ State = ProcessZeroAllocation(C, CE, 1, State);
} else if (FunI == II_reallocf) {
State = ReallocMem(C, CE, true, State);
+ State = ProcessZeroAllocation(C, CE, 1, State);
} else if (FunI == II_calloc) {
State = CallocMem(C, CE, State);
+ State = ProcessZeroAllocation(C, CE, 0, State);
+ State = ProcessZeroAllocation(C, CE, 1, State);
} else if (FunI == II_free) {
State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
} else if (FunI == II_strdup) {
@@ -764,18 +796,23 @@
} else if (FunI == II_alloca) {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
AF_Alloca);
+ State = ProcessZeroAllocation(C, CE, 0, State);
} else if (isStandardNewDelete(FD, C.getASTContext())) {
// Process direct calls to operator new/new[]/delete/delete[] functions
// as distinct from new/new[]/delete/delete[] expressions that are
// processed by the checkPostStmt callbacks for CXXNewExpr and
// CXXDeleteExpr.
OverloadedOperatorKind K = FD->getOverloadedOperator();
- if (K == OO_New)
+ if (K == OO_New) {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
AF_CXXNew);
- else if (K == OO_Array_New)
+ State = ProcessZeroAllocation(C, CE, 0, State);
+ }
+ else if (K == OO_Array_New) {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
AF_CXXNewArray);
+ State = ProcessZeroAllocation(C, CE, 0, State);
+ }
else if (K == OO_Delete || K == OO_Array_Delete)
State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
else
@@ -809,6 +846,68 @@
C.addTransition(State);
}
+// Performs a 0-sized allocations check.
+ProgramStateRef MallocChecker::ProcessZeroAllocation(CheckerContext &C,
+ const Expr *E,
+ const unsigned AllocationSizeArg,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
+ const Expr *Arg = nullptr;
+
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+ Arg = CE->getArg(AllocationSizeArg);
+ }
+ else if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
+ if (NE->isArray())
+ Arg = NE->getArraySize();
+ else
+ return State;
+ }
+ else
+ llvm_unreachable("not a CallExpr or CXXNewExpr");
+
+ assert(Arg);
+
+ Optional<DefinedSVal> DefArgVal =
+ State->getSVal(Arg, C.getLocationContext()).getAs<DefinedSVal>();
+
+ if (!DefArgVal)
+ return State;
+
+ // Check if the allocation size is 0.
+ ProgramStateRef TrueState, FalseState;
+ SValBuilder &SvalBuilder = C.getSValBuilder();
+ DefinedSVal Zero =
+ SvalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
+
+ std::tie(TrueState, FalseState) =
+ State->assume(SvalBuilder.evalEQ(State, *DefArgVal, Zero));
+
+ if (TrueState && !FalseState) {
+ SVal retVal = State->getSVal(E, C.getLocationContext());
+ SymbolRef Sym = retVal.getAsLocSymbol();
+ if (!Sym)
+ return State;
+
+ const RefState *RS = State->get<RegionState>(Sym);
+ if (!RS)
+ return State; // TODO: change to assert(RS); after realloc() will
+ // guarantee have a RegionState attached.
+
+ if (!RS->isAllocated())
+ return State;
+
+ return TrueState->set<RegionState>(Sym,
+ RefState::getAllocatedOfSizeZero(RS));
+ }
+
+ // Assume the value is non-zero going forward.
+ assert(FalseState);
+ return FalseState;
+}
+
static QualType getDeepPointeeType(QualType T) {
QualType Result = T, PointeeType = T->getPointeeType();
while (!PointeeType.isNull()) {
@@ -868,6 +967,7 @@
// existing binding.
State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray
: AF_CXXNew);
+ State = ProcessZeroAllocation(C, NE, 0, State);
C.addTransition(State);
}
@@ -1291,7 +1391,8 @@
// If the pointer is allocated or escaped, but we are now trying to free it,
// check that the call to free is proper.
- } else if (RsBase->isAllocated() || RsBase->isEscaped()) {
+ } else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
+ RsBase->isEscaped()) {
// Check if an expected deallocation function matches the real one.
bool DeallocMatchesAlloc =
@@ -1316,7 +1417,8 @@
}
}
- ReleasedAllocated = (RsBase != nullptr) && RsBase->isAllocated();
+ ReleasedAllocated = (RsBase != nullptr) && (RsBase->isAllocated() ||
+ RsBase->isAllocatedOfSizeZero());
// Clean out the info on previous call to free return info.
State = State->remove<FreeReturnValue>(SymBase);
@@ -1741,6 +1843,36 @@
}
}
+void MallocChecker::ReportUseZeroAllocated(CheckerContext &C,
+ SourceRange Range,
+ SymbolRef Sym) const {
+
+ if (!ChecksEnabled[CK_MallocChecker] &&
+ !ChecksEnabled[CK_NewDeleteChecker])
+ return;
+
+ Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
+
+ if (!CheckKind.hasValue())
+ return;
+
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT_UseZerroAllocated[*CheckKind])
+ BT_UseZerroAllocated[*CheckKind].reset(new BugType(
+ CheckNames[*CheckKind], "Use of zero allocated", "Memory Error"));
+
+ BugReport *R = new BugReport(*BT_UseZerroAllocated[*CheckKind],
+ "Use of zero-allocated memory", N);
+
+ R->addRange(Range);
+ if (Sym) {
+ R->markInteresting(Sym);
+ R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
+ }
+ C.emitReport(R);
+ }
+}
+
ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
const CallExpr *CE,
bool FreesOnFail,
@@ -1988,7 +2120,7 @@
SmallVector<SymbolRef, 2> Errors;
for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
if (SymReaper.isDead(I->first)) {
- if (I->second.isAllocated())
+ if (I->second.isAllocated() || I->second.isAllocatedOfSizeZero())
Errors.push_back(I->first);
// Remove the dead symbol from the map.
RS = F.remove(RS, I->first);
@@ -2156,6 +2288,15 @@
return false;
}
+void MallocChecker::checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
+ const Stmt *S) const {
+ assert(Sym);
+ const RefState *RS = C.getState()->get<RegionState>(Sym);
+
+ if (RS && RS->isAllocatedOfSizeZero())
+ ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
+}
+
bool MallocChecker::checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const {
if (isReleased(Sym, C)) {
@@ -2169,8 +2310,10 @@
void MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S,
CheckerContext &C) const {
SymbolRef Sym = l.getLocSymbolInBase();
- if (Sym)
+ if (Sym) {
checkUseAfterFree(Sym, C, S);
+ checkUseZeroAllocated(Sym, C, S);
+ }
}
// If a symbolic region is assumed to NULL (or another constant), stop tracking
@@ -2414,7 +2557,8 @@
continue;
if (const RefState *RS = State->get<RegionState>(sym)) {
- if (RS->isAllocated() && CheckRefState(RS)) {
+ if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) &&
+ CheckRefState(RS)) {
State = State->remove<RegionState>(sym);
State = State->set<RegionState>(sym, RefState::getEscaped(RS));
}
diff --git a/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
index f38ce77..e913479 100644
--- a/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
@@ -142,13 +142,13 @@
}
}
}
- else if (isa<MemberExpr>(E)) {
+ else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
// No points-to analysis, just look at the member
- const Decl * EmeMD = dyn_cast<MemberExpr>(E)->getMemberDecl();
+ const Decl *EmeMD = ME->getMemberDecl();
while (i != e) {
--i;
- if (isa<MemberExpr>(i->variable)) {
- if (dyn_cast<MemberExpr>(i->variable)->getMemberDecl() == EmeMD)
+ if (const auto *ME_i = dyn_cast<MemberExpr>(i->variable)) {
+ if (ME_i->getMemberDecl() == EmeMD)
i = toScanFor.erase (i);
}
}
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 6b8596e..58c27d4 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -2475,9 +2475,7 @@
: ShouldResetSummaryLog(false),
IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {}
- virtual ~RetainCountChecker() {
- DeleteContainerSeconds(DeadSymbolTags);
- }
+ ~RetainCountChecker() override { DeleteContainerSeconds(DeadSymbolTags); }
void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
ExprEngine &Eng) const {
@@ -2821,63 +2819,6 @@
return false;
}
-/// Returns the property that claims this instance variable, if any.
-static const ObjCPropertyDecl *findPropForIvar(const ObjCIvarDecl *Ivar) {
- auto IsPropertyForIvar = [Ivar](const ObjCPropertyDecl *Prop) -> bool {
- return Prop->getPropertyIvarDecl() == Ivar;
- };
-
- const ObjCInterfaceDecl *Interface = Ivar->getContainingInterface();
- auto PropIter = std::find_if(Interface->prop_begin(), Interface->prop_end(),
- IsPropertyForIvar);
- if (PropIter != Interface->prop_end()) {
- return *PropIter;
- }
-
- for (auto Extension : Interface->visible_extensions()) {
- PropIter = std::find_if(Extension->prop_begin(), Extension->prop_end(),
- IsPropertyForIvar);
- if (PropIter != Extension->prop_end())
- return *PropIter;
- }
-
- return nullptr;
-}
-
-namespace {
- enum Retaining_t {
- NonRetaining,
- Retaining
- };
-}
-
-static Optional<Retaining_t> getRetainSemantics(const ObjCPropertyDecl *Prop) {
- assert(Prop->getPropertyIvarDecl() &&
- "should only be used for properties with synthesized implementations");
-
- if (!Prop->hasWrittenStorageAttribute()) {
- // Don't assume anything about the retain semantics of readonly properties.
- if (Prop->isReadOnly())
- return None;
-
- // Don't assume anything about readwrite properties with manually-supplied
- // setters.
- const ObjCMethodDecl *Setter = Prop->getSetterMethodDecl();
- bool HasManualSetter = std::any_of(Setter->redecls_begin(),
- Setter->redecls_end(),
- [](const Decl *SetterRedecl) -> bool {
- return cast<ObjCMethodDecl>(SetterRedecl)->hasBody();
- });
- if (HasManualSetter)
- return None;
-
- // If the setter /is/ synthesized, we're already relying on the retain
- // semantics of the property. Continue as normal.
- }
-
- return Prop->isRetaining() ? Retaining : NonRetaining;
-}
-
void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
CheckerContext &C) const {
Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>();
@@ -2914,14 +2855,6 @@
return;
}
- // Also don't do anything if the ivar is unretained. If so, we know that
- // there's no outstanding retain count for the value.
- if (Kind == RetEffect::ObjC)
- if (const ObjCPropertyDecl *Prop = findPropForIvar(IRE->getDecl()))
- if (auto retainSemantics = getRetainSemantics(Prop))
- if (retainSemantics.getValue() == NonRetaining)
- return;
-
// Note that this value has been loaded from an ivar.
C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
return;
@@ -2935,23 +2868,7 @@
return;
}
- bool didUpdateState = false;
- if (Kind == RetEffect::ObjC) {
- // Check if the ivar is known to be unretained. If so, we know that
- // there's no outstanding retain count for the value.
- if (const ObjCPropertyDecl *Prop = findPropForIvar(IRE->getDecl())) {
- if (auto retainSemantics = getRetainSemantics(Prop)) {
- if (retainSemantics.getValue() == NonRetaining) {
- State = setRefBinding(State, Sym, PlusZero);
- didUpdateState = true;
- }
- }
- }
- }
-
- if (!didUpdateState)
- State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
-
+ State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
C.addTransition(State);
}
@@ -3318,6 +3235,16 @@
RefVal::Kind ErrorKind,
SymbolRef Sym,
CheckerContext &C) const {
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (const RefVal *RV = getRefBinding(St, Sym))
+ if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return;
+
ExplodedNode *N = C.generateSink(St);
if (!N)
return;
@@ -3544,6 +3471,15 @@
RetEffect RE, RefVal X,
SymbolRef Sym,
ProgramStateRef state) const {
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return;
+
// Any leaks or other errors?
if (X.isReturnedOwned() && X.getCount() == 0) {
if (RE.getKind() != RetEffect::NoRet) {
@@ -3781,6 +3717,15 @@
return setRefBinding(state, Sym, V);
}
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return state;
+
// Woah! More autorelease counts then retain counts left.
// Emit hard error.
V = V ^ RefVal::ErrorOverAutorelease;
@@ -3814,11 +3759,22 @@
RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
SymbolRef sid, RefVal V,
SmallVectorImpl<SymbolRef> &Leaked) const {
- bool hasLeak = false;
- if (V.isOwned())
+ bool hasLeak;
+
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ hasLeak = false;
+ else if (V.isOwned())
hasLeak = true;
else if (V.isNotOwned() || V.isReturnedOwned())
hasLeak = (V.getCount() > 0);
+ else
+ hasLeak = false;
if (!hasLeak)
return removeRefBinding(state, sid);
diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 026cc02..3c1a3b4 100644
--- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -45,7 +45,7 @@
public:
HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& prefix, const Preprocessor &pp);
- virtual ~HTMLDiagnostics() { FlushDiagnostics(nullptr); }
+ ~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) override;
diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 76026aa..e0aff58 100644
--- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -37,7 +37,7 @@
const LangOptions &LangOpts,
bool supportsMultipleFiles);
- virtual ~PlistDiagnostics() {}
+ ~PlistDiagnostics() override {}
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) override;
diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.h b/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
index a72d1d4..135cd4e 100644
--- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
+++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
@@ -27,7 +27,7 @@
public:
SimpleConstraintManager(SubEngine *subengine, SValBuilder &SB)
: SU(subengine), SVB(SB) {}
- virtual ~SimpleConstraintManager();
+ ~SimpleConstraintManager() override;
//===------------------------------------------------------------------===//
// Common implementation for the interface provided by ConstraintManager.
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index df9e4d6..b3cab87 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -29,7 +29,7 @@
SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
ProgramStateManager &stateMgr)
: SValBuilder(alloc, context, stateMgr) {}
- virtual ~SimpleSValBuilder() {}
+ ~SimpleSValBuilder() override {}
SVal evalMinus(NonLoc val) override;
SVal evalComplement(NonLoc val) override;
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 621718e..fbeffb8 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -92,7 +92,7 @@
public:
ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag)
: Diag(Diag), IncludePath(false) {}
- virtual ~ClangDiagPathDiagConsumer() {}
+ ~ClangDiagPathDiagConsumer() override {}
StringRef getName() const override { return "ClangDiags"; }
bool supportsLogicalOpControlFlow() const override { return true; }
@@ -199,7 +199,7 @@
}
}
- ~AnalysisConsumer() {
+ ~AnalysisConsumer() override {
if (Opts->PrintStats)
delete TUTotalTimer;
}
@@ -373,8 +373,7 @@
return true;
}
- virtual void
- AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
+ void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
PathConsumers.push_back(Consumer);
}
@@ -724,7 +723,7 @@
public:
UbigraphViz(std::unique_ptr<raw_ostream> Out, StringRef Filename);
- ~UbigraphViz();
+ ~UbigraphViz() override;
void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) override;
};
diff --git a/lib/StaticAnalyzer/Frontend/ModelInjector.h b/lib/StaticAnalyzer/Frontend/ModelInjector.h
index fd24e32..e23bf8a 100644
--- a/lib/StaticAnalyzer/Frontend/ModelInjector.h
+++ b/lib/StaticAnalyzer/Frontend/ModelInjector.h
@@ -43,8 +43,8 @@
class ModelInjector : public CodeInjector {
public:
ModelInjector(CompilerInstance &CI);
- Stmt *getBody(const FunctionDecl *D);
- Stmt *getBody(const ObjCMethodDecl *D);
+ Stmt *getBody(const FunctionDecl *D) override;
+ Stmt *getBody(const ObjCMethodDecl *D) override;
private:
/// \brief Synthesize a body for a declaration
diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp
index 383fb1a..2514f02 100644
--- a/lib/Tooling/CompilationDatabase.cpp
+++ b/lib/Tooling/CompilationDatabase.cpp
@@ -156,8 +156,8 @@
// recording for our own purposes.
UnusedInputDiagConsumer(DiagnosticConsumer *Other) : Other(Other) {}
- virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info) override {
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override {
if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
// Arg 1 for this diagnostic is the option that didn't get used.
UnusedInputs.push_back(Info.getArgStdStr(0));
@@ -283,11 +283,9 @@
return true;
}
-FixedCompilationDatabase *
-FixedCompilationDatabase::loadFromCommandLine(int &Argc,
- const char **Argv,
- Twine Directory) {
- const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
+FixedCompilationDatabase *FixedCompilationDatabase::loadFromCommandLine(
+ int &Argc, const char *const *Argv, Twine Directory) {
+ const char *const *DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
if (DoubleDash == Argv + Argc)
return nullptr;
std::vector<const char *> CommandLine(DoubleDash + 1, Argv + Argc);
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index 60371fb..e100003 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -90,7 +90,7 @@
}
/// \brief Returns a clang build invocation initialized from the CC1 flags.
-static clang::CompilerInvocation *newInvocation(
+clang::CompilerInvocation *newInvocation(
clang::DiagnosticsEngine *Diagnostics,
const llvm::opt::ArgStringList &CC1Args) {
assert(!CC1Args.empty() && "Must at least contain the program name!");