Update Clang for 3.5 rebase (r209713).
Change-Id: I8c9133b0f8f776dc915f270b60f94962e771bc83
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index 178ec84..617bb68 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -311,10 +311,9 @@
MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
ARCMTMacroLocs);
pass.setNoFinalizeRemoval(NoFinalizeRemoval);
- Diags->setDiagnosticMapping(diag::err_arcmt_nsalloc_realloc,
- NoNSAllocReallocError ? diag::MAP_WARNING
- : diag::MAP_ERROR,
- SourceLocation());
+ if (!NoNSAllocReallocError)
+ Diags->setDiagnosticMapping(diag::warn_arcmt_nsalloc_realloc,
+ diag::MAP_ERROR, SourceLocation());
for (unsigned i=0, e = transforms.size(); i != e; ++i)
transforms[i](pass);
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index 3ae6724..a52c32f 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -109,7 +109,7 @@
ArrayRef<std::string> WhiteList)
: MigrateDir(migrateDir),
ASTMigrateActions(astMigrateActions),
- NSIntegerTypedefed(0), NSUIntegerTypedefed(0),
+ NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
IsOutputFile(isOutputFile) {
@@ -124,7 +124,7 @@
NSAPIObj.reset(new NSAPI(Context));
Editor.reset(new edit::EditedSource(Context.getSourceManager(),
Context.getLangOpts(),
- PPRec, false));
+ PPRec));
}
bool HandleTopLevelDecl(DeclGroupRef DG) override {
@@ -180,7 +180,7 @@
unsigned migrateAction)
: WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
ObjCMigAction(migrateAction),
- CompInst(0) {
+ CompInst(nullptr) {
if (MigrateDir.empty())
MigrateDir = "."; // user current directory if none is given.
}
@@ -344,7 +344,7 @@
return "weak";
else if (RetainableObject)
return ArgType->isBlockPointerType() ? "copy" : "strong";
- return 0;
+ return nullptr;
}
static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
@@ -773,11 +773,11 @@
if (!TypedefDcl) {
if (NSIntegerTypedefed) {
TypedefDcl = NSIntegerTypedefed;
- NSIntegerTypedefed = 0;
+ NSIntegerTypedefed = nullptr;
}
else if (NSUIntegerTypedefed) {
TypedefDcl = NSUIntegerTypedefed;
- NSUIntegerTypedefed = 0;
+ NSUIntegerTypedefed = nullptr;
}
else
return false;
@@ -830,8 +830,12 @@
return Res;
}
-static void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC,
+static void ReplaceWithInstancetype(ASTContext &Ctx,
+ const ObjCMigrateASTConsumer &ASTC,
ObjCMethodDecl *OM) {
+ if (OM->getReturnType() == Ctx.getObjCInstanceType())
+ return; // already has instancetype.
+
SourceRange R;
std::string ClassString;
if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
@@ -893,7 +897,7 @@
return;
case OIT_Init:
if (OM->getReturnType()->isObjCIdType())
- ReplaceWithInstancetype(*this, OM);
+ ReplaceWithInstancetype(Ctx, *this, OM);
return;
case OIT_ReturnsSelf:
migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf);
@@ -914,7 +918,7 @@
migrateFactoryMethod(Ctx, CDecl, OM);
return;
}
- ReplaceWithInstancetype(*this, OM);
+ ReplaceWithInstancetype(Ctx, *this, OM);
}
static bool TypeIsInnerPointer(QualType T) {
@@ -1108,7 +1112,7 @@
// Try a non-void method with no argument (and no setter or property of same name
// as a 'readonly' property.
edit::Commit commit(*Editor);
- rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit,
+ rewriteToObjCProperty(Method, nullptr /*SetterMethod*/, *NSAPIObj, commit,
LengthOfPrefix,
(ASTMigrateActions &
FrontendOptions::ObjCMT_AtomicProperty) != 0,
@@ -1224,7 +1228,7 @@
if (OIT_Family == OIT_ReturnsSelf)
ReplaceWithClasstype(*this, OM);
else
- ReplaceWithInstancetype(*this, OM);
+ ReplaceWithInstancetype(Ctx, *this, OM);
}
static bool IsVoidStarType(QualType Ty) {
@@ -1334,7 +1338,7 @@
// Annotate function.
if (!ResultAnnotated) {
RetEffect Ret = CE.getReturnValue();
- const char *AnnotationString = 0;
+ const char *AnnotationString = nullptr;
if (Ret.getObjKind() == RetEffect::CF) {
if (Ret.isOwned() &&
Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
@@ -1451,7 +1455,7 @@
// Annotate function.
if (!ResultAnnotated) {
RetEffect Ret = CE.getReturnValue();
- const char *AnnotationString = 0;
+ const char *AnnotationString = nullptr;
if (Ret.getObjKind() == RetEffect::CF) {
if (Ret.isOwned() &&
Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
@@ -1698,34 +1702,6 @@
}
-static bool
-IsReallyASystemHeader(ASTContext &Ctx, const FileEntry *file, FileID FID) {
- bool Invalid = false;
- const SrcMgr::SLocEntry &SEntry =
- Ctx.getSourceManager().getSLocEntry(FID, &Invalid);
- if (!Invalid && SEntry.isFile()) {
- const SrcMgr::FileInfo &FI = SEntry.getFile();
- if (!FI.hasLineDirectives()) {
- if (FI.getFileCharacteristic() == SrcMgr::C_ExternCSystem)
- return true;
- if (FI.getFileCharacteristic() == SrcMgr::C_System) {
- // This file is in a system header directory. Continue committing
- // change only if it's a user-specified system directory because user
- // put a .system_framework file in the framework directory.
- StringRef Directory(file->getDir()->getName());
- size_t Ix = Directory.rfind(".framework");
- if (Ix == StringRef::npos)
- return true;
- std::string PatchToSystemFramework = Directory.slice(0, Ix+sizeof(".framework"));
- PatchToSystemFramework += ".system_framework";
- if (!llvm::sys::fs::exists(PatchToSystemFramework.data()))
- return true;
- }
- }
- }
- return false;
-}
-
void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
@@ -1766,7 +1742,7 @@
D++;
}
else
- migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */0);
+ migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr);
}
else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
@@ -1847,8 +1823,6 @@
RewriteBuffer &buf = I->second;
const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
assert(file);
- if (IsReallyASystemHeader(Ctx, file, FID))
- continue;
SmallString<512> newText;
llvm::raw_svector_ostream vecOS(newText);
buf.write(vecOS);
diff --git a/lib/ARCMigrate/TransAutoreleasePool.cpp b/lib/ARCMigrate/TransAutoreleasePool.cpp
index a2990e7..a8a99fa 100644
--- a/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ b/lib/ARCMigrate/TransAutoreleasePool.cpp
@@ -70,7 +70,7 @@
: public RecursiveASTVisitor<AutoreleasePoolRewriter> {
public:
AutoreleasePoolRewriter(MigrationPass &pass)
- : Body(0), Pass(pass) {
+ : Body(nullptr), Pass(pass) {
PoolII = &pass.Ctx.Idents.get("NSAutoreleasePool");
DrainSel = pass.Ctx.Selectors.getNullarySelector(
&pass.Ctx.Idents.get("drain"));
@@ -230,7 +230,7 @@
bool IsFollowedBySimpleReturnStmt;
SmallVector<ObjCMessageExpr *, 4> Releases;
- PoolScope() : PoolVar(0), CompoundParent(0), Begin(), End(),
+ PoolScope() : PoolVar(nullptr), CompoundParent(nullptr), Begin(), End(),
IsFollowedBySimpleReturnStmt(false) { }
SourceRange getIndentedRange() const {
@@ -305,7 +305,7 @@
// statement, in which case we will include the return in the scope.
if (SI != SE)
if (ReturnStmt *retS = dyn_cast<ReturnStmt>(*SI))
- if ((retS->getRetValue() == 0 ||
+ if ((retS->getRetValue() == nullptr ||
isa<DeclRefExpr>(retS->getRetValue()->IgnoreParenCasts())) &&
findLocationAfterSemi(retS->getLocEnd(), Pass.Ctx).isValid()) {
scope.IsFollowedBySimpleReturnStmt = true;
@@ -421,7 +421,7 @@
ExprSet Refs;
SmallVector<PoolScope, 2> Scopes;
- PoolVarInfo() : Dcl(0) { }
+ PoolVarInfo() : Dcl(nullptr) { }
};
std::map<VarDecl *, PoolVarInfo> PoolVars;
diff --git a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index 31f19ce..9689f40 100644
--- a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -205,8 +205,8 @@
impl_iterator;
for (impl_iterator I = impl_iterator(DC->decls_begin()),
E = impl_iterator(DC->decls_end()); I != E; ++I) {
- ObjCMethodDecl *DeallocM = 0;
- ObjCMethodDecl *FinalizeM = 0;
+ ObjCMethodDecl *DeallocM = nullptr;
+ ObjCMethodDecl *FinalizeM = nullptr;
for (auto *MD : I->instance_methods()) {
if (!MD->hasBody())
continue;
diff --git a/lib/ARCMigrate/TransGCAttrs.cpp b/lib/ARCMigrate/TransGCAttrs.cpp
index cbb3d12..10fce19 100644
--- a/lib/ARCMigrate/TransGCAttrs.cpp
+++ b/lib/ARCMigrate/TransGCAttrs.cpp
@@ -80,7 +80,7 @@
}
}
- bool handleAttr(AttributedTypeLoc TL, Decl *D = 0) {
+ bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {
if (TL.getAttrKind() != AttributedType::attr_objc_ownership)
return false;
@@ -149,9 +149,9 @@
return false;
if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) {
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD))
- return ID->getImplementation() != 0;
+ return ID->getImplementation() != nullptr;
if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD))
- return CD->getImplementation() != 0;
+ return CD->getImplementation() != nullptr;
if (isa<ObjCImplDecl>(ContD))
return true;
return false;
diff --git a/lib/ARCMigrate/TransGCCalls.cpp b/lib/ARCMigrate/TransGCCalls.cpp
index 401e788..3a236d3 100644
--- a/lib/ARCMigrate/TransGCCalls.cpp
+++ b/lib/ARCMigrate/TransGCCalls.cpp
@@ -38,7 +38,7 @@
TransformActions &TA = MigrateCtx.Pass.TA;
if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
- TA.report(E->getLocStart(), diag::err_arcmt_nsalloc_realloc,
+ TA.report(E->getLocStart(), diag::warn_arcmt_nsalloc_realloc,
E->getSourceRange());
return true;
}
diff --git a/lib/ARCMigrate/TransProperties.cpp b/lib/ARCMigrate/TransProperties.cpp
index e18da97..ab12884 100644
--- a/lib/ARCMigrate/TransProperties.cpp
+++ b/lib/ARCMigrate/TransProperties.cpp
@@ -61,7 +61,8 @@
ObjCIvarDecl *IvarD;
ObjCPropertyImplDecl *ImplD;
- PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
+ PropData(ObjCPropertyDecl *propD)
+ : PropD(propD), IvarD(nullptr), ImplD(nullptr) {}
};
typedef SmallVector<PropData, 2> PropsTy;
@@ -74,7 +75,7 @@
: MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
- AtPropDeclsTy *PrevAtProps = 0) {
+ AtPropDeclsTy *PrevAtProps = nullptr) {
for (auto *Prop : D->properties()) {
if (Prop->getAtLoc().isInvalid())
continue;
diff --git a/lib/ARCMigrate/TransProtectedScope.cpp b/lib/ARCMigrate/TransProtectedScope.cpp
index 237aa42..0fcbcbe 100644
--- a/lib/ARCMigrate/TransProtectedScope.cpp
+++ b/lib/ARCMigrate/TransProtectedScope.cpp
@@ -47,7 +47,7 @@
St_Fixed
} State;
- CaseInfo() : SC(0), State(St_Unchecked) {}
+ CaseInfo() : SC(nullptr), State(St_Unchecked) {}
CaseInfo(SwitchCase *S, SourceRange Range)
: SC(S), Range(Range), State(St_Unchecked) {}
};
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index 5db5fa0..bcbc9e9 100644
--- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -44,7 +44,7 @@
public:
RetainReleaseDeallocRemover(MigrationPass &pass)
- : Body(0), Pass(pass) {
+ : Body(nullptr), Pass(pass) {
DelegateSel =
Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("delegate"));
FinalizeSel =
@@ -70,7 +70,7 @@
// An unused autorelease is badness. If we remove it the receiver
// will likely die immediately while previously it was kept alive
// by the autorelease pool. This is bad practice in general, leave it
- // and emit an error to force the user to restructure his code.
+ // and emit an error to force the user to restructure their code.
Pass.TA.reportError("it is not safe to remove an unused 'autorelease' "
"message; its receiver may be destroyed immediately",
E->getLocStart(), E->getSourceRange());
@@ -248,7 +248,7 @@
}
std::pair<Stmt *, Stmt *> getPreviousAndNextStmt(Expr *E) {
- Stmt *prevStmt = 0, *nextStmt = 0;
+ Stmt *prevStmt = nullptr, *nextStmt = nullptr;
if (!E)
return std::make_pair(prevStmt, nextStmt);
@@ -294,7 +294,7 @@
Decl *getReferencedDecl(Expr *E) {
if (!E)
- return 0;
+ return nullptr;
E = E->IgnoreParenCasts();
if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
@@ -305,7 +305,7 @@
case OMF_retain:
return getReferencedDecl(ME->getInstanceReceiver());
default:
- return 0;
+ return nullptr;
}
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
@@ -315,7 +315,7 @@
if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(E))
return IRE->getDecl();
- return 0;
+ return nullptr;
}
/// \brief Check if the retain/release is due to a GCD/XPC macro that are
@@ -345,7 +345,7 @@
if (!isGCDOrXPC)
return;
- StmtExpr *StmtE = 0;
+ StmtExpr *StmtE = nullptr;
Stmt *S = Msg;
while (S) {
if (StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp
index 0aa0c89..7ca4955 100644
--- a/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -66,7 +66,8 @@
mutable std::unique_ptr<ExprSet> Removables;
public:
- UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass), ParentD(0), Body(0) {
+ UnbridgedCastRewriter(MigrationPass &pass)
+ : Pass(pass), ParentD(nullptr), Body(nullptr) {
SelfII = &Pass.Ctx.Idents.get("self");
}
diff --git a/lib/ARCMigrate/TransUnusedInitDelegate.cpp b/lib/ARCMigrate/TransUnusedInitDelegate.cpp
index e316c73..98571c0 100644
--- a/lib/ARCMigrate/TransUnusedInitDelegate.cpp
+++ b/lib/ARCMigrate/TransUnusedInitDelegate.cpp
@@ -39,7 +39,7 @@
public:
UnusedInitRewriter(MigrationPass &pass)
- : Body(0), Pass(pass) { }
+ : Body(nullptr), Pass(pass) { }
void transformBody(Stmt *body, Decl *ParentD) {
Body = body;
diff --git a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
index 3be9fb2..76ce0ec 100644
--- a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
+++ b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
@@ -35,7 +35,7 @@
Selector FinalizeSel;
public:
- ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(0) {
+ ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(nullptr) {
FinalizeSel =
Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
}
@@ -135,7 +135,7 @@
// clear out for next method.
SynthesizedProperties.clear();
- SelfD = 0;
+ SelfD = nullptr;
Removables.clear();
return true;
}
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index c349cb5..6ff7b6b 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -413,8 +413,7 @@
if (tok.isNot(tok::at)) return false;
lexer.LexFromRawLexer(tok);
if (tok.isNot(tok::raw_identifier)) return false;
- if (StringRef(tok.getRawIdentifierData(), tok.getLength())
- != "property")
+ if (tok.getRawIdentifier() != "property")
return false;
lexer.LexFromRawLexer(tok);
if (tok.isNot(tok::l_paren)) return false;
@@ -430,8 +429,7 @@
while (1) {
if (tok.isNot(tok::raw_identifier)) return false;
- StringRef ident(tok.getRawIdentifierData(), tok.getLength());
- if (ident == fromAttr) {
+ if (tok.getRawIdentifier() == fromAttr) {
if (!toAttr.empty()) {
Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
return true;
@@ -496,8 +494,7 @@
if (tok.isNot(tok::at)) return false;
lexer.LexFromRawLexer(tok);
if (tok.isNot(tok::raw_identifier)) return false;
- if (StringRef(tok.getRawIdentifierData(), tok.getLength())
- != "property")
+ if (tok.getRawIdentifier() != "property")
return false;
lexer.LexFromRawLexer(tok);
diff --git a/lib/ARCMigrate/Transforms.h b/lib/ARCMigrate/Transforms.h
index 54be5b5..12551d2 100644
--- a/lib/ARCMigrate/Transforms.h
+++ b/lib/ARCMigrate/Transforms.h
@@ -189,7 +189,7 @@
typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
public:
- BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(0) { }
+ BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
bool TraverseStmt(Stmt *rootS) {
if (rootS)
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index 049518e..e7b5a6b 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -117,7 +117,7 @@
delete [] Elts;
}
-APValue::UnionData::UnionData() : Field(0), Value(new APValue) {}
+APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {}
APValue::UnionData::~UnionData () {
delete Value;
}
@@ -404,7 +404,8 @@
if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
Out << *VD;
else
- Base.get<const Expr*>()->printPretty(Out, 0, Ctx.getPrintingPolicy());
+ Base.get<const Expr*>()->printPretty(Out, nullptr,
+ Ctx.getPrintingPolicy());
if (!O.isZero()) {
Out << " + " << (O / S);
if (IsReference)
@@ -425,12 +426,12 @@
ElemTy = VD->getType();
} else {
const Expr *E = Base.get<const Expr*>();
- E->printPretty(Out, 0, Ctx.getPrintingPolicy());
+ E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
ElemTy = E->getType();
}
ArrayRef<LValuePathEntry> Path = getLValuePath();
- const CXXRecordDecl *CastToBase = 0;
+ const CXXRecordDecl *CastToBase = nullptr;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
if (ElemTy->getAs<RecordType>()) {
// The lvalue refers to a class type, so the next path entry is a base
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 3ed2a9f..2ea93ba 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -77,23 +77,23 @@
// User can not attach documentation to implicit declarations.
if (D->isImplicit())
- return NULL;
+ return nullptr;
// User can not attach documentation to implicit instantiations.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
- return NULL;
+ return nullptr;
}
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->isStaticDataMember() &&
VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
- return NULL;
+ return nullptr;
}
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
if (CRD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
- return NULL;
+ return nullptr;
}
if (const ClassTemplateSpecializationDecl *CTSD =
@@ -101,35 +101,35 @@
TemplateSpecializationKind TSK = CTSD->getSpecializationKind();
if (TSK == TSK_ImplicitInstantiation ||
TSK == TSK_Undeclared)
- return NULL;
+ return nullptr;
}
if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
- return NULL;
+ return nullptr;
}
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
// When tag declaration (but not definition!) is part of the
// decl-specifier-seq of some other declaration, it doesn't get comment
if (TD->isEmbeddedInDeclarator() && !TD->isCompleteDefinition())
- return NULL;
+ return nullptr;
}
// TODO: handle comments for function parameters properly.
if (isa<ParmVarDecl>(D))
- return NULL;
+ return nullptr;
// TODO: we could look up template parameter documentation in the template
// documentation.
if (isa<TemplateTypeParmDecl>(D) ||
isa<NonTypeTemplateParmDecl>(D) ||
isa<TemplateTemplateParmDecl>(D))
- return NULL;
+ return nullptr;
ArrayRef<RawComment *> RawComments = Comments.getComments();
// If there are no comments anywhere, we won't find anything.
if (RawComments.empty())
- return NULL;
+ return nullptr;
// Find declaration location.
// For Objective-C declarations we generally don't expect to have multiple
@@ -167,7 +167,7 @@
// If the declaration doesn't map directly to a location in a file, we
// can't find the comment.
if (DeclLoc.isInvalid() || !DeclLoc.isFileID())
- return NULL;
+ return nullptr;
// Find the comment that occurs just after this declaration.
ArrayRef<RawComment *>::iterator Comment;
@@ -221,12 +221,12 @@
// The comment just after the declaration was not a trailing comment.
// Let's look at the previous comment.
if (Comment == RawComments.begin())
- return NULL;
+ return nullptr;
--Comment;
// Check that we actually have a non-member Doxygen comment.
if (!(*Comment)->isDocumentation() || (*Comment)->isTrailingComment())
- return NULL;
+ return nullptr;
// Decompose the end of the comment.
std::pair<FileID, unsigned> CommentEndDecomp
@@ -235,14 +235,14 @@
// If the comment and the declaration aren't in the same file, then they
// aren't related.
if (DeclLocDecomp.first != CommentEndDecomp.first)
- return NULL;
+ return nullptr;
// Get the corresponding buffer.
bool Invalid = false;
const char *Buffer = SourceMgr.getBufferData(DeclLocDecomp.first,
&Invalid).data();
if (Invalid)
- return NULL;
+ return nullptr;
// Extract text between the comment and declaration.
StringRef Text(Buffer + CommentEndDecomp.second,
@@ -251,7 +251,7 @@
// There should be no other declarations or preprocessor directives between
// comment and declaration.
if (Text.find_first_of(";{}#@") != StringRef::npos)
- return NULL;
+ return nullptr;
return *Comment;
}
@@ -349,8 +349,8 @@
}
// Search for comments attached to declarations in the redeclaration chain.
- const RawComment *RC = NULL;
- const Decl *OriginalDeclForRC = NULL;
+ const RawComment *RC = nullptr;
+ const Decl *OriginalDeclForRC = nullptr;
for (auto I : D->redecls()) {
llvm::DenseMap<const Decl *, RawCommentAndCacheFlags>::iterator Pos =
RedeclComments.find(I);
@@ -422,6 +422,8 @@
ThisDeclInfo->IsFilled = false;
ThisDeclInfo->fill();
ThisDeclInfo->CommentDecl = FC->getDecl();
+ if (!ThisDeclInfo->TemplateParameters)
+ ThisDeclInfo->TemplateParameters = FC->getDeclInfo()->TemplateParameters;
comments::FullComment *CFC =
new (*this) comments::FullComment(FC->getBlocks(),
ThisDeclInfo);
@@ -431,14 +433,14 @@
comments::FullComment *ASTContext::getLocalCommentForDeclUncached(const Decl *D) const {
const RawComment *RC = getRawCommentForDeclNoCache(D);
- return RC ? RC->parse(*this, 0, D) : 0;
+ return RC ? RC->parse(*this, nullptr, D) : nullptr;
}
comments::FullComment *ASTContext::getCommentForDecl(
const Decl *D,
const Preprocessor *PP) const {
if (D->isInvalidDecl())
- return NULL;
+ return nullptr;
D = adjustDeclToTemplate(D);
const Decl *Canonical = D->getCanonicalDecl();
@@ -495,7 +497,7 @@
}
else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
if (!(RD = RD->getDefinition()))
- return NULL;
+ return nullptr;
// Check non-virtual bases.
for (const auto &I : RD->bases()) {
if (I.isVirtual() || (I.getAccessSpecifier() != AS_public))
@@ -526,7 +528,7 @@
}
}
}
- return NULL;
+ return nullptr;
}
// If the RawComment was attached to other redeclaration of this Decl, we
@@ -587,7 +589,7 @@
// Check if we already have a canonical template template parameter.
llvm::FoldingSetNodeID ID;
CanonicalTemplateTemplateParm::Profile(ID, TTP);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
CanonicalTemplateTemplateParm *Canonical
= CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
if (Canonical)
@@ -606,7 +608,7 @@
SourceLocation(),
SourceLocation(),
TTP->getDepth(),
- TTP->getIndex(), 0, false,
+ TTP->getIndex(), nullptr, false,
TTP->isParameterPack()));
else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*P)) {
@@ -626,7 +628,7 @@
SourceLocation(),
SourceLocation(),
NTTP->getDepth(),
- NTTP->getPosition(), 0,
+ NTTP->getPosition(), nullptr,
T,
TInfo,
ExpandedTypes.data(),
@@ -637,7 +639,7 @@
SourceLocation(),
SourceLocation(),
NTTP->getDepth(),
- NTTP->getPosition(), 0,
+ NTTP->getPosition(), nullptr,
T,
NTTP->isParameterPack(),
TInfo);
@@ -654,7 +656,7 @@
SourceLocation(), TTP->getDepth(),
TTP->getPosition(),
TTP->isParameterPack(),
- 0,
+ nullptr,
TemplateParameterList::Create(*this, SourceLocation(),
SourceLocation(),
CanonParams.data(),
@@ -663,7 +665,7 @@
// Get the new insert position for the node we care about.
Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
- assert(Canonical == 0 && "Shouldn't be in the map!");
+ assert(!Canonical && "Shouldn't be in the map!");
(void)Canonical;
// Create the canonical template template parameter entry.
@@ -673,14 +675,13 @@
}
CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
- if (!LangOpts.CPlusPlus) return 0;
+ if (!LangOpts.CPlusPlus) return nullptr;
switch (T.getCXXABI().getKind()) {
- case TargetCXXABI::GenericARM:
+ case TargetCXXABI::GenericARM: // Same as Itanium at this level
case TargetCXXABI::iOS:
case TargetCXXABI::iOS64:
- return CreateARMCXXABI(*this);
- case TargetCXXABI::GenericAArch64: // Same as Itanium at this level
+ case TargetCXXABI::GenericAArch64:
case TargetCXXABI::GenericItanium:
return CreateItaniumCXXABI(*this);
case TargetCXXABI::Microsoft:
@@ -722,47 +723,40 @@
}
ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
- const TargetInfo *t,
IdentifierTable &idents, SelectorTable &sels,
- Builtin::Context &builtins,
- unsigned size_reserve,
- bool DelayInitialization)
+ Builtin::Context &builtins)
: FunctionProtoTypes(this_()),
TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()),
SubstTemplateTemplateParmPacks(this_()),
- GlobalNestedNameSpecifier(0),
- Int128Decl(0), UInt128Decl(0), Float128StubDecl(0),
- BuiltinVaListDecl(0),
- ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0),
- BOOLDecl(0),
- CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0),
- FILEDecl(0),
- jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0),
- BlockDescriptorType(0), BlockDescriptorExtendedType(0),
- cudaConfigureCallDecl(0),
+ GlobalNestedNameSpecifier(nullptr),
+ Int128Decl(nullptr), UInt128Decl(nullptr), Float128StubDecl(nullptr),
+ BuiltinVaListDecl(nullptr),
+ ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr),
+ ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
+ CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr),
+ FILEDecl(nullptr),
+ jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr),
+ BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr),
+ cudaConfigureCallDecl(nullptr),
NullTypeSourceInfo(QualType()),
FirstLocalImport(), LastLocalImport(),
SourceMgr(SM), LangOpts(LOpts),
- AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts),
+ AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins),
DeclarationNames(*this),
- ExternalSource(0), Listener(0),
+ ExternalSource(nullptr), Listener(nullptr),
Comments(SM), CommentsLoaded(false),
CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
- LastSDM(0, 0)
+ LastSDM(nullptr, 0)
{
- if (size_reserve > 0) Types.reserve(size_reserve);
TUDecl = TranslationUnitDecl::Create(*this);
-
- if (!DelayInitialization) {
- assert(t && "No target supplied for ASTContext initialization");
- InitBuiltinTypes(*t);
- }
}
ASTContext::~ASTContext() {
+ ReleaseParentMapEntries();
+
// Release the DenseMaps associated with DeclContext objects.
// FIXME: Is this the ideal solution?
ReleaseDeclContextMaps();
@@ -797,6 +791,18 @@
llvm::DeleteContainerSeconds(MangleNumberingContexts);
}
+void ASTContext::ReleaseParentMapEntries() {
+ if (!AllParents) return;
+ for (const auto &Entry : *AllParents) {
+ if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
+ delete Entry.second.get<ast_type_traits::DynTypedNode *>();
+ } else {
+ assert(Entry.second.is<ParentVector *>());
+ delete Entry.second.get<ParentVector *>();
+ }
+ }
+}
+
void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
Deallocations[Callback].push_back(Data);
}
@@ -1116,7 +1122,7 @@
llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos
= ClassScopeSpecializationPattern.find(FD);
if (Pos == ClassScopeSpecializationPattern.end())
- return 0;
+ return nullptr;
return Pos->second;
}
@@ -1133,7 +1139,7 @@
llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
= InstantiatedFromUsingDecl.find(UUD);
if (Pos == InstantiatedFromUsingDecl.end())
- return 0;
+ return nullptr;
return Pos->second;
}
@@ -1153,7 +1159,7 @@
llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos
= InstantiatedFromUsingShadowDecl.find(Inst);
if (Pos == InstantiatedFromUsingShadowDecl.end())
- return 0;
+ return nullptr;
return Pos->second;
}
@@ -1169,7 +1175,7 @@
llvm::DenseMap<FieldDecl *, FieldDecl *>::iterator Pos
= InstantiatedFromUnnamedFieldDecl.find(Field);
if (Pos == InstantiatedFromUnnamedFieldDecl.end())
- return 0;
+ return nullptr;
return Pos->second;
}
@@ -1189,7 +1195,7 @@
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
= OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
- return 0;
+ return nullptr;
return Pos->second.begin();
}
@@ -1199,7 +1205,7 @@
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
= OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
- return 0;
+ return nullptr;
return Pos->second.end();
}
@@ -1322,7 +1328,9 @@
Align = std::max(Align, Target->getLargeArrayAlign());
}
- // Walk through any array types while we're at it.
+ // Keep track of extra alignment requirements on the array itself, then
+ // work with the element type.
+ Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
T = getBaseElementType(arrayType);
}
Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
@@ -1899,7 +1907,7 @@
I = ObjCImpls.find(D);
if (I != ObjCImpls.end())
return cast<ObjCImplementationDecl>(I->second);
- return 0;
+ return nullptr;
}
/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) {
@@ -1907,7 +1915,7 @@
I = ObjCImpls.find(D);
if (I != ObjCImpls.end())
return cast<ObjCCategoryImplDecl>(I->second);
- return 0;
+ return nullptr;
}
/// \brief Set the implementation of ObjCInterfaceDecl.
@@ -1935,7 +1943,7 @@
dyn_cast<ObjCImplDecl>(ND->getDeclContext()))
return IMD->getClassInterface();
- return 0;
+ return nullptr;
}
/// \brief Get the copy initialization expression of VarDecl,or NULL if
@@ -1946,7 +1954,7 @@
"getBlockVarCopyInits - not __block var");
llvm::DenseMap<const VarDecl*, Expr*>::iterator
I = BlockVarCopyInits.find(VD);
- return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : 0;
+ return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : nullptr;
}
/// \brief Set the copy inialization expression of a block var decl.
@@ -1980,7 +1988,7 @@
const ASTRecordLayout &
ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const {
- return getObjCLayout(D, 0);
+ return getObjCLayout(D, nullptr);
}
const ASTRecordLayout &
@@ -2001,7 +2009,7 @@
// Check if we've already instantiated this type.
llvm::FoldingSetNodeID ID;
ExtQuals::Profile(ID, baseType, quals);
- void *insertPos = 0;
+ void *insertPos = nullptr;
if (ExtQuals *eq = ExtQualNodes.FindNodeOrInsertPos(ID, insertPos)) {
assert(eq->getQualifiers() == quals);
return QualType(eq, fastQuals);
@@ -2113,7 +2121,7 @@
llvm::FoldingSetNodeID ID;
ComplexType::Profile(ID, T);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (ComplexType *CT = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(CT, 0);
@@ -2125,7 +2133,7 @@
// Get the new insert position for the node we care about.
ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
ComplexType *New = new (*this, TypeAlignment) ComplexType(T, Canonical);
Types.push_back(New);
@@ -2141,7 +2149,7 @@
llvm::FoldingSetNodeID ID;
PointerType::Profile(ID, T);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (PointerType *PT = PointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
@@ -2153,7 +2161,7 @@
// Get the new insert position for the node we care about.
PointerType *NewIP = PointerTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
PointerType *New = new (*this, TypeAlignment) PointerType(T, Canonical);
Types.push_back(New);
@@ -2164,7 +2172,7 @@
QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const {
llvm::FoldingSetNodeID ID;
AdjustedType::Profile(ID, Orig, New);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
if (AT)
return QualType(AT, 0);
@@ -2173,7 +2181,7 @@
// Get the new insert position for the node we care about.
AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(AT == 0 && "Shouldn't be in the map!");
+ assert(!AT && "Shouldn't be in the map!");
AT = new (*this, TypeAlignment)
AdjustedType(Type::Adjusted, Orig, New, Canonical);
@@ -2204,7 +2212,7 @@
llvm::FoldingSetNodeID ID;
AdjustedType::Profile(ID, T, Decayed);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
if (AT)
return QualType(AT, 0);
@@ -2213,7 +2221,7 @@
// Get the new insert position for the node we care about.
AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(AT == 0 && "Shouldn't be in the map!");
+ assert(!AT && "Shouldn't be in the map!");
AT = new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical);
Types.push_back(AT);
@@ -2230,7 +2238,7 @@
llvm::FoldingSetNodeID ID;
BlockPointerType::Profile(ID, T);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (BlockPointerType *PT =
BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
@@ -2244,7 +2252,7 @@
// Get the new insert position for the node we care about.
BlockPointerType *NewIP =
BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
BlockPointerType *New
= new (*this, TypeAlignment) BlockPointerType(T, Canonical);
@@ -2265,7 +2273,7 @@
llvm::FoldingSetNodeID ID;
ReferenceType::Profile(ID, T, SpelledAsLValue);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (LValueReferenceType *RT =
LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(RT, 0);
@@ -2282,7 +2290,7 @@
// Get the new insert position for the node we care about.
LValueReferenceType *NewIP =
LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
LValueReferenceType *New
@@ -2302,7 +2310,7 @@
llvm::FoldingSetNodeID ID;
ReferenceType::Profile(ID, T, false);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (RValueReferenceType *RT =
RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(RT, 0);
@@ -2319,7 +2327,7 @@
// Get the new insert position for the node we care about.
RValueReferenceType *NewIP =
RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
RValueReferenceType *New
@@ -2337,7 +2345,7 @@
llvm::FoldingSetNodeID ID;
MemberPointerType::Profile(ID, T, Cls);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (MemberPointerType *PT =
MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
@@ -2351,7 +2359,7 @@
// Get the new insert position for the node we care about.
MemberPointerType *NewIP =
MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
MemberPointerType *New
= new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical);
@@ -2379,7 +2387,7 @@
llvm::FoldingSetNodeID ID;
ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (ConstantArrayType *ATP =
ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(ATP, 0);
@@ -2396,7 +2404,7 @@
// Get the new insert position for the node we care about.
ConstantArrayType *NewIP =
ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
ConstantArrayType *New = new(*this,TypeAlignment)
@@ -2514,7 +2522,7 @@
const IncompleteArrayType *iat = cast<IncompleteArrayType>(ty);
result = getVariableArrayType(
getVariableArrayDecayedType(iat->getElementType()),
- /*size*/ 0,
+ /*size*/ nullptr,
ArrayType::Normal,
iat->getIndexTypeCVRQualifiers(),
SourceRange());
@@ -2526,7 +2534,7 @@
const VariableArrayType *vat = cast<VariableArrayType>(ty);
result = getVariableArrayType(
getVariableArrayDecayedType(vat->getElementType()),
- /*size*/ 0,
+ /*size*/ nullptr,
ArrayType::Star,
vat->getIndexTypeCVRQualifiers(),
vat->getBracketsRange());
@@ -2596,7 +2604,7 @@
SplitQualType canonElementType = getCanonicalType(elementType).split();
- void *insertPos = 0;
+ void *insertPos = nullptr;
llvm::FoldingSetNodeID ID;
DependentSizedArrayType::Profile(ID, *this,
QualType(canonElementType.Ty, 0),
@@ -2641,7 +2649,7 @@
llvm::FoldingSetNodeID ID;
IncompleteArrayType::Profile(ID, elementType, ASM, elementTypeQuals);
- void *insertPos = 0;
+ void *insertPos = nullptr;
if (IncompleteArrayType *iat =
IncompleteArrayTypes.FindNodeOrInsertPos(ID, insertPos))
return QualType(iat, 0);
@@ -2681,7 +2689,7 @@
llvm::FoldingSetNodeID ID;
VectorType::Profile(ID, vecType, NumElts, Type::Vector, VecKind);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(VTP, 0);
@@ -2693,7 +2701,7 @@
// Get the new insert position for the node we care about.
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
VectorType *New = new (*this, TypeAlignment)
VectorType(vecType, NumElts, Canonical, VecKind);
@@ -2712,7 +2720,7 @@
llvm::FoldingSetNodeID ID;
VectorType::Profile(ID, vecType, NumElts, Type::ExtVector,
VectorType::GenericVector);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(VTP, 0);
@@ -2724,7 +2732,7 @@
// Get the new insert position for the node we care about.
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
ExtVectorType *New = new (*this, TypeAlignment)
ExtVectorType(vecType, NumElts, Canonical);
@@ -2741,7 +2749,7 @@
DependentSizedExtVectorType::Profile(ID, *this, getCanonicalType(vecType),
SizeExpr);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
DependentSizedExtVectorType *Canon
= DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
DependentSizedExtVectorType *New;
@@ -2787,7 +2795,7 @@
llvm::FoldingSetNodeID ID;
FunctionNoProtoType::Profile(ID, ResultTy, Info);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (FunctionNoProtoType *FT =
FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(FT, 0);
@@ -2799,7 +2807,7 @@
// Get the new insert position for the node we care about.
FunctionNoProtoType *NewIP =
FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
FunctionProtoType::ExtInfo newInfo = Info.withCallingConv(CallConv);
@@ -2828,7 +2836,7 @@
FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI,
*this);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (FunctionProtoType *FTP =
FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(FTP, 0);
@@ -2868,7 +2876,7 @@
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
// FunctionProtoType objects are allocated with extra bytes after
@@ -3012,7 +3020,7 @@
llvm::FoldingSetNodeID id;
AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
- void *insertPos = 0;
+ void *insertPos = nullptr;
AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos);
if (type) return QualType(type, 0);
@@ -3036,7 +3044,7 @@
llvm::FoldingSetNodeID ID;
SubstTemplateTypeParmType::Profile(ID, Parm, Replacement);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
SubstTemplateTypeParmType *SubstParm
= SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -3065,7 +3073,7 @@
llvm::FoldingSetNodeID ID;
SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (SubstTemplateTypeParmPackType *SubstParm
= SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(SubstParm, 0);
@@ -3094,7 +3102,7 @@
TemplateTypeParmDecl *TTPDecl) const {
llvm::FoldingSetNodeID ID;
TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, TTPDecl);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
TemplateTypeParmType *TypeParm
= TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -3235,7 +3243,7 @@
TemplateSpecializationType::Profile(ID, CanonTemplate,
CanonArgs.data(), NumArgs, *this);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
TemplateSpecializationType *Spec
= TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -3263,7 +3271,7 @@
llvm::FoldingSetNodeID ID;
ElaboratedType::Profile(ID, Keyword, NNS, NamedType);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
return QualType(T, 0);
@@ -3287,7 +3295,7 @@
llvm::FoldingSetNodeID ID;
ParenType::Profile(ID, InnerType);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ParenType *T = ParenTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
return QualType(T, 0);
@@ -3325,7 +3333,7 @@
llvm::FoldingSetNodeID ID;
DependentNameType::Profile(ID, Keyword, NNS, Name);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
DependentNameType *T
= DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
@@ -3366,7 +3374,7 @@
DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS,
Name, NumArgs, Args);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
DependentTemplateSpecializationType *T
= DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
@@ -3412,7 +3420,7 @@
assert(Pattern->containsUnexpandedParameterPack() &&
"Pack expansions must expand one or more parameter packs");
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
PackExpansionType *T
= PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
@@ -3487,7 +3495,7 @@
// Look in the folding set for an existing type.
llvm::FoldingSetNodeID ID;
ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
@@ -3559,12 +3567,28 @@
CollectInheritedProtocols(IDecl, InheritedProtocols);
if (InheritedProtocols.empty())
return false;
-
+ // Check that if every protocol in list of id<plist> conforms to a protcol
+ // of IDecl's, then bridge casting is ok.
+ bool Conforms = false;
+ for (auto *Proto : OPT->quals()) {
+ Conforms = false;
+ for (auto *PI : InheritedProtocols) {
+ if (ProtocolCompatibleWithProtocol(Proto, PI)) {
+ Conforms = true;
+ break;
+ }
+ }
+ if (!Conforms)
+ break;
+ }
+ if (Conforms)
+ return true;
+
for (auto *PI : InheritedProtocols) {
// If both the right and left sides have qualifiers.
bool Adopts = false;
for (auto *Proto : OPT->quals()) {
- // return 'true' if '*PI' is in the inheritance hierarchy of Proto
+ // return 'true' if 'PI' is in the inheritance hierarchy of Proto
if ((Adopts = ProtocolCompatibleWithProtocol(PI, Proto)))
break;
}
@@ -3580,7 +3604,7 @@
llvm::FoldingSetNodeID ID;
ObjCObjectPointerType::Profile(ID, ObjectT);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (ObjCObjectPointerType *QT =
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
@@ -3639,7 +3663,7 @@
llvm::FoldingSetNodeID ID;
DependentTypeOfExprType::Profile(ID, *this, tofExpr);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
DependentTypeOfExprType *Canon
= DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos);
if (Canon) {
@@ -3691,7 +3715,7 @@
llvm::FoldingSetNodeID ID;
DependentDecltypeType::Profile(ID, *this, e);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
DependentDecltypeType *Canon
= DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos);
if (Canon) {
@@ -3737,7 +3761,7 @@
return getAutoDeductType();
// Look in the folding set for an existing type.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent);
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
@@ -3760,7 +3784,7 @@
llvm::FoldingSetNodeID ID;
AtomicType::Profile(ID, T);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (AtomicType *AT = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(AT, 0);
@@ -3772,7 +3796,7 @@
// Get the new insert position for the node we care about.
AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical);
Types.push_back(New);
@@ -4131,7 +4155,7 @@
NestedNameSpecifier *
ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
if (!NNS)
- return 0;
+ return nullptr;
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
@@ -4143,13 +4167,13 @@
case NestedNameSpecifier::Namespace:
// A namespace is canonical; build a nested-name-specifier with
// this namespace and no prefix.
- return NestedNameSpecifier::Create(*this, 0,
+ return NestedNameSpecifier::Create(*this, nullptr,
NNS->getAsNamespace()->getOriginalNamespace());
case NestedNameSpecifier::NamespaceAlias:
// A namespace is canonical; build a nested-name-specifier with
// this namespace and no prefix.
- return NestedNameSpecifier::Create(*this, 0,
+ return NestedNameSpecifier::Create(*this, nullptr,
NNS->getAsNamespaceAlias()->getNamespace()
->getOriginalNamespace());
@@ -4171,8 +4195,8 @@
// Otherwise, just canonicalize the type, and force it to be a TypeSpec.
// FIXME: Why are TypeSpec and TypeSpecWithTemplate distinct in the
// first place?
- return NestedNameSpecifier::Create(*this, 0, false,
- const_cast<Type*>(T.getTypePtr()));
+ return NestedNameSpecifier::Create(*this, nullptr, false,
+ const_cast<Type *>(T.getTypePtr()));
}
case NestedNameSpecifier::Global:
@@ -4194,7 +4218,7 @@
// Handle the common negative case fast.
if (!isa<ArrayType>(T.getCanonicalType()))
- return 0;
+ return nullptr;
// Apply any qualifiers from the array type to the element type. This
// implements C99 6.7.3p8: "If the specification of an array type includes
@@ -4209,7 +4233,7 @@
// If we have a simple case, just return now.
const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty);
- if (ATy == 0 || qs.empty())
+ if (!ATy || qs.empty())
return ATy;
// Otherwise, we have an array and we have qualifiers on it. Push the
@@ -4495,7 +4519,7 @@
// FIXME: In C++, enum types are never integer types.
if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped())
return ET->getDecl()->getIntegerType().getTypePtr();
- return NULL;
+ return nullptr;
}
/// getIntegerTypeOrder - Returns the highest ranked integer type:
@@ -4567,9 +4591,9 @@
for (unsigned i = 0; i < 4; ++i) {
FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl,
SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
+ SourceLocation(), nullptr,
+ FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit);
Field->setAccess(AS_public);
@@ -4619,8 +4643,8 @@
for (size_t i = 0; i < 2; ++i) {
FieldDecl *Field = FieldDecl::Create(
*this, RD, SourceLocation(), SourceLocation(),
- &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0, /*Mutable=*/false, ICIS_NoInit);
+ &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit);
Field->setAccess(AS_public);
RD->addDecl(Field);
}
@@ -4658,8 +4682,8 @@
for (size_t i = 0; i < 4; ++i) {
FieldDecl *Field = FieldDecl::Create(
*this, RD, SourceLocation(), SourceLocation(),
- &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
+ &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false, ICIS_NoInit);
Field->setAccess(AS_public);
RD->addDecl(Field);
@@ -4879,7 +4903,7 @@
// Encode type qualifer, 'in', 'inout', etc. for the parameter.
getObjCEncodingForTypeQualifier(QT, S);
// Encode parameter type.
- getObjCEncodingForTypeImpl(T, S, true, true, 0,
+ getObjCEncodingForTypeImpl(T, S, true, true, nullptr,
true /*OutermostType*/,
false /*EncodingProperty*/,
false /*StructField*/,
@@ -4947,19 +4971,19 @@
const ObjCPropertyDecl *PD,
const Decl *Container) const {
if (!Container)
- return 0;
+ return nullptr;
if (const ObjCCategoryImplDecl *CID =
dyn_cast<ObjCCategoryImplDecl>(Container)) {
for (auto *PID : CID->property_impls())
if (PID->getPropertyDecl() == PD)
return PID;
- } else {
- const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container);
- for (auto *PID : OID->property_impls())
- if (PID->getPropertyDecl() == PD)
- return PID;
- }
- return 0;
+ } else {
+ const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container);
+ for (auto *PID : OID->property_impls())
+ if (PID->getPropertyDecl() == PD)
+ return PID;
+ }
+ return nullptr;
}
/// getObjCEncodingForPropertyDecl - Return the encoded type for this
@@ -4992,7 +5016,7 @@
std::string& S) const {
// Collect information from the property implementation decl(s).
bool Dynamic = false;
- ObjCPropertyImplDecl *SynthesizePID = 0;
+ ObjCPropertyImplDecl *SynthesizePID = nullptr;
if (ObjCPropertyImplDecl *PropertyImpDecl =
getObjCPropertyImplDeclForPropertyDecl(PD, Container)) {
@@ -5008,7 +5032,7 @@
// Encode result type.
// GCC has some special rules regarding encoding of properties which
// closely resembles encoding of ivars.
- getObjCEncodingForTypeImpl(PD->getType(), S, true, true, 0,
+ getObjCEncodingForTypeImpl(PD->getType(), S, true, true, nullptr,
true /* outermost type */,
true /* encoding for property */);
@@ -5212,15 +5236,15 @@
case Type::Complex: {
const ComplexType *CT = T->castAs<ComplexType>();
S += 'j';
- getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false,
- false);
+ getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr,
+ false, false);
return;
}
case Type::Atomic: {
const AtomicType *AT = T->castAs<AtomicType>();
S += 'A';
- getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, 0,
+ getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr,
false, false);
return;
}
@@ -5292,7 +5316,7 @@
getLegacyIntegralTypeEncoding(PointeeTy);
getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures,
- NULL);
+ nullptr);
return;
}
@@ -5505,7 +5529,7 @@
}
getObjCEncodingForTypeImpl(PointeeTy, S,
false, ExpandPointedToStructures,
- NULL,
+ nullptr,
false, false, false, false, false,
/*EncodePointerToObjCTypedef*/true);
return;
@@ -5637,7 +5661,7 @@
// Mark the end of the structure.
uint64_t offs = toBits(size);
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
- std::make_pair(offs, (NamedDecl*)0));
+ std::make_pair(offs, nullptr));
}
for (; CurLayObj != FieldOrBaseOffsets.end(); ++CurLayObj) {
@@ -5657,7 +5681,7 @@
#endif
NamedDecl *dcl = CurLayObj->second;
- if (dcl == 0)
+ if (!dcl)
break; // reached end of structure.
if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) {
@@ -5716,7 +5740,7 @@
TypedefDecl *ASTContext::getObjCIdDecl() const {
if (!ObjCIdDecl) {
- QualType T = getObjCObjectType(ObjCBuiltinIdTy, 0, 0);
+ QualType T = getObjCObjectType(ObjCBuiltinIdTy, nullptr, 0);
T = getObjCObjectPointerType(T);
ObjCIdDecl = buildImplicitTypedef(T, "id");
}
@@ -5733,7 +5757,7 @@
TypedefDecl *ASTContext::getObjCClassDecl() const {
if (!ObjCClassDecl) {
- QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0);
+ QualType T = getObjCObjectType(ObjCBuiltinClassTy, nullptr, 0);
T = getObjCObjectPointerType(T);
ObjCClassDecl = buildImplicitTypedef(T, "Class");
}
@@ -5746,7 +5770,7 @@
= ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(),
&Idents.get("Protocol"),
- /*PrevDecl=*/0,
+ /*PrevDecl=*/nullptr,
SourceLocation(), true);
}
@@ -5778,9 +5802,9 @@
NamespaceDecl *NS;
NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
Context->getTranslationUnitDecl(),
- /*Inline*/false, SourceLocation(),
+ /*Inline*/ false, SourceLocation(),
SourceLocation(), &Context->Idents.get("std"),
- /*PrevDecl*/0);
+ /*PrevDecl*/ nullptr);
NS->setImplicit();
VaListTagDecl->setDeclContext(NS);
}
@@ -5818,8 +5842,8 @@
SourceLocation(),
SourceLocation(),
&Context->Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
+ FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit);
Field->setAccess(AS_public);
@@ -5870,8 +5894,8 @@
SourceLocation(),
SourceLocation(),
&Context->Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
+ FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit);
Field->setAccess(AS_public);
@@ -5930,8 +5954,8 @@
SourceLocation(),
SourceLocation(),
&Context->Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
+ FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit);
Field->setAccess(AS_public);
@@ -5976,7 +6000,7 @@
Context->getTranslationUnitDecl(),
/*Inline*/false, SourceLocation(),
SourceLocation(), &Context->Idents.get("std"),
- /*PrevDecl*/0);
+ /*PrevDecl*/ nullptr);
NS->setImplicit();
VaListDecl->setDeclContext(NS);
}
@@ -5990,8 +6014,8 @@
SourceLocation(),
&Context->Idents.get("__ap"),
Context->getPointerType(Context->VoidTy),
- /*TInfo=*/0,
- /*BitWidth=*/0,
+ /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit);
Field->setAccess(AS_public);
@@ -6039,8 +6063,8 @@
SourceLocation(),
SourceLocation(),
&Context->Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
+ FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit);
Field->setAccess(AS_public);
@@ -6150,7 +6174,7 @@
llvm::FoldingSetNodeID ID;
QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
QualifiedTemplateName *QTN =
QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
if (!QTN) {
@@ -6173,7 +6197,7 @@
llvm::FoldingSetNodeID ID;
DependentTemplateName::Profile(ID, NNS, Name);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
DependentTemplateName *QTN =
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
@@ -6208,8 +6232,8 @@
llvm::FoldingSetNodeID ID;
DependentTemplateName::Profile(ID, NNS, Operator);
-
- void *InsertPos = 0;
+
+ void *InsertPos = nullptr;
DependentTemplateName *QTN
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
@@ -6240,8 +6264,8 @@
TemplateName replacement) const {
llvm::FoldingSetNodeID ID;
SubstTemplateTemplateParmStorage::Profile(ID, param, replacement);
-
- void *insertPos = 0;
+
+ void *insertPos = nullptr;
SubstTemplateTemplateParmStorage *subst
= SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos);
@@ -6259,8 +6283,8 @@
ASTContext &Self = const_cast<ASTContext &>(*this);
llvm::FoldingSetNodeID ID;
SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack);
-
- void *InsertPos = 0;
+
+ void *InsertPos = nullptr;
SubstTemplateTemplateParmPackStorage *Subst
= SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos);
@@ -7732,7 +7756,8 @@
return getFunctionType(ResType, ArgTypes, EPI);
}
-GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
+static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
+ const FunctionDecl *FD) {
if (!FD->isExternallyVisible())
return GVA_Internal;
@@ -7746,72 +7771,126 @@
case TSK_ExplicitInstantiationDefinition:
return GVA_StrongODR;
+ // C++11 [temp.explicit]p10:
+ // [ Note: The intent is that an inline function that is the subject of
+ // an explicit instantiation declaration will still be implicitly
+ // instantiated when used so that the body can be considered for
+ // inlining, but that no out-of-line copy of the inline function would be
+ // generated in the translation unit. -- end note ]
case TSK_ExplicitInstantiationDeclaration:
+ return GVA_AvailableExternally;
+
case TSK_ImplicitInstantiation:
- External = GVA_TemplateInstantiation;
+ External = GVA_DiscardableODR;
break;
}
if (!FD->isInlined())
return External;
- if ((!getLangOpts().CPlusPlus && !getLangOpts().MSVCCompat) ||
+ if ((!Context.getLangOpts().CPlusPlus && !Context.getLangOpts().MSVCCompat &&
+ !FD->hasAttr<DLLExportAttr>()) ||
FD->hasAttr<GNUInlineAttr>()) {
+ // FIXME: This doesn't match gcc's behavior for dllexport inline functions.
+
// GNU or C99 inline semantics. Determine whether this symbol should be
// externally visible.
if (FD->isInlineDefinitionExternallyVisible())
return External;
// C99 inline semantics, where the symbol is not externally visible.
- return GVA_C99Inline;
+ return GVA_AvailableExternally;
}
- // C++0x [temp.explicit]p9:
- // [ Note: The intent is that an inline function that is the subject of
- // an explicit instantiation declaration will still be implicitly
- // instantiated when used so that the body can be considered for
- // inlining, but that no out-of-line copy of the inline function would be
- // generated in the translation unit. -- end note ]
- if (FD->getTemplateSpecializationKind()
- == TSK_ExplicitInstantiationDeclaration)
- return GVA_C99Inline;
-
// Functions specified with extern and inline in -fms-compatibility mode
// forcibly get emitted. While the body of the function cannot be later
// replaced, the function definition cannot be discarded.
if (FD->getMostRecentDecl()->isMSExternInline())
return GVA_StrongODR;
- return GVA_CXXInline;
+ return GVA_DiscardableODR;
}
-GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+static GVALinkage adjustGVALinkageForDLLAttribute(GVALinkage L, const Decl *D) {
+ // See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx
+ // dllexport/dllimport on inline functions.
+ if (D->hasAttr<DLLImportAttr>()) {
+ if (L == GVA_DiscardableODR || L == GVA_StrongODR)
+ return GVA_AvailableExternally;
+ } else if (D->hasAttr<DLLExportAttr>()) {
+ if (L == GVA_DiscardableODR)
+ return GVA_StrongODR;
+ }
+ return L;
+}
+
+GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
+ return adjustGVALinkageForDLLAttribute(basicGVALinkageForFunction(*this, FD),
+ FD);
+}
+
+static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
+ const VarDecl *VD) {
if (!VD->isExternallyVisible())
return GVA_Internal;
+ if (VD->isStaticLocal()) {
+ GVALinkage StaticLocalLinkage = GVA_DiscardableODR;
+ const DeclContext *LexicalContext = VD->getParentFunctionOrMethod();
+ while (LexicalContext && !isa<FunctionDecl>(LexicalContext))
+ LexicalContext = LexicalContext->getLexicalParent();
+
+ // Let the static local variable inherit it's linkage from the nearest
+ // enclosing function.
+ if (LexicalContext)
+ StaticLocalLinkage =
+ Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext));
+
+ // GVA_StrongODR function linkage is stronger than what we need,
+ // downgrade to GVA_DiscardableODR.
+ // This allows us to discard the variable if we never end up needing it.
+ return StaticLocalLinkage == GVA_StrongODR ? GVA_DiscardableODR
+ : StaticLocalLinkage;
+ }
+
+ // On Darwin, the backing variable for a C++11 thread_local variable always
+ // has internal linkage; all accesses should just be calls to the
+ // Itanium-specified entry point, which has the normal linkage of the
+ // variable.
+ if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
+ Context.getTargetInfo().getTriple().isMacOSX())
+ return GVA_Internal;
+
switch (VD->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
return GVA_StrongExternal;
- case TSK_ExplicitInstantiationDeclaration:
- llvm_unreachable("Variable should not be instantiated");
- // Fall through to treat this like any other instantiation.
-
case TSK_ExplicitInstantiationDefinition:
return GVA_StrongODR;
+ case TSK_ExplicitInstantiationDeclaration:
+ return GVA_AvailableExternally;
+
case TSK_ImplicitInstantiation:
- return GVA_TemplateInstantiation;
+ return GVA_DiscardableODR;
}
llvm_unreachable("Invalid Linkage!");
}
+GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+ return adjustGVALinkageForDLLAttribute(basicGVALinkageForVariable(*this, VD),
+ VD);
+}
+
bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (!VD->isFileVarDecl())
return false;
+ // Global named register variables (GNU extension) are never emitted.
+ if (VD->getStorageClass() == SC_Register)
+ return false;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// We never need to emit an uninstantiated function template.
if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
@@ -7858,8 +7937,8 @@
// static, static inline, always_inline, and extern inline functions can
// always be deferred. Normal inline functions can be deferred in C99/C++.
// Implicit template instantiations can also be deferred in C++.
- if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
- Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
+ if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally ||
+ Linkage == GVA_DiscardableODR)
return false;
return true;
}
@@ -7872,7 +7951,8 @@
// Variables that can be needed in other TUs are required.
GVALinkage L = GetGVALinkageForVariable(VD);
- if (L != GVA_Internal && L != GVA_TemplateInstantiation)
+ if (L != GVA_Internal && L != GVA_AvailableExternally &&
+ L != GVA_DiscardableODR)
return true;
// Variables that have destruction with side-effects are required.
@@ -8031,7 +8111,7 @@
llvm::DenseMap<const MaterializeTemporaryExpr *, APValue>::iterator I =
MaterializedTemporaryValues.find(E);
- return I == MaterializedTemporaryValues.end() ? 0 : &I->second;
+ return I == MaterializedTemporaryValues.end() ? nullptr : &I->second;
}
bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
@@ -8094,9 +8174,9 @@
template <typename T>
bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) {
- if (Node == NULL)
+ if (!Node)
return true;
- if (ParentStack.size() > 0)
+ if (ParentStack.size() > 0) {
// FIXME: Currently we add the same parent multiple times, for example
// when we visit all subexpressions of template instantiations; this is
// suboptimal, bug benign: the only way to visit those is with
@@ -8105,7 +8185,23 @@
// map. The main problem there is to implement hash functions /
// comparison operators for all types that DynTypedNode supports that
// do not have pointer identity.
- (*Parents)[Node].push_back(ParentStack.back());
+ auto &NodeOrVector = (*Parents)[Node];
+ if (NodeOrVector.isNull()) {
+ NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back());
+ } else if (NodeOrVector
+ .template is<ast_type_traits::DynTypedNode *>()) {
+ auto *Node =
+ NodeOrVector.template get<ast_type_traits::DynTypedNode *>();
+ auto *Vector = new ASTContext::ParentVector(1, *Node);
+ Vector->push_back(ParentStack.back());
+ NodeOrVector = Vector;
+ delete Node;
+ } else {
+ assert(NodeOrVector.template is<ASTContext::ParentVector *>());
+ NodeOrVector.template get<ASTContext::ParentVector *>()->push_back(
+ ParentStack.back());
+ }
+ }
ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node));
bool Result = (this ->* traverse) (Node);
ParentStack.pop_back();
@@ -8143,7 +8239,11 @@
if (I == AllParents->end()) {
return ParentVector();
}
- return I->second;
+ if (I->second.is<ast_type_traits::DynTypedNode *>()) {
+ return ParentVector(1, *I->second.get<ast_type_traits::DynTypedNode *>());
+ }
+ const auto &Parents = *I->second.get<ParentVector *>();
+ return ParentVector(Parents.begin(), Parents.end());
}
bool
@@ -8176,3 +8276,12 @@
return (MethodDecl->isVariadic() == MethodImpl->isVariadic());
}
+
+// Explicitly instantiate this in case a Redeclarable<T> is used from a TU that
+// doesn't include ASTContext.h
+template
+clang::LazyGenerationalUpdatePtr<
+ const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::ValueType
+clang::LazyGenerationalUpdatePtr<
+ const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::makeValue(
+ const clang::ASTContext &Ctx, Decl *Value);
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 7c6bec4..bd5c209 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -228,6 +228,20 @@
return S;
}
}
+
+ // Give some additional info on vector types. These are either not desugared
+ // or displaying complex __attribute__ expressions so add details of the
+ // type and element count.
+ if (Ty->isVectorType()) {
+ const VectorType *VTy = Ty->getAs<VectorType>();
+ std::string DecoratedString;
+ llvm::raw_string_ostream OS(DecoratedString);
+ const char *Values = VTy->getNumElements() > 1 ? "values" : "value";
+ OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '"
+ << VTy->getElementType().getAsString(Context.getPrintingPolicy())
+ << "' " << Values << ")";
+ return OS.str();
+ }
}
S = "'" + S + "'";
@@ -484,10 +498,11 @@
DiffNode(unsigned ParentNode = 0)
: Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode),
- FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0),
- IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0),
- ToValueDecl(0), FromAddressOf(false), ToAddressOf(false),
- FromDefault(false), ToDefault(false), Same(false) { }
+ FromType(), ToType(), FromExpr(nullptr), ToExpr(nullptr),
+ FromTD(nullptr), ToTD(nullptr), IsValidFromInt(false),
+ IsValidToInt(false), FromValueDecl(nullptr), ToValueDecl(nullptr),
+ FromAddressOf(false), ToAddressOf(false), FromDefault(false),
+ ToDefault(false), Same(false) {}
};
/// FlatTree - A flattened tree used to store the DiffNodes.
@@ -732,7 +747,7 @@
TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
: TST(TST),
DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())),
- Index(0), CurrentTA(0), EndTA(0) {
+ Index(0), CurrentTA(nullptr), EndTA(nullptr) {
if (isEnd()) return;
// Set to first template argument. If not a parameter pack, done.
@@ -823,13 +838,13 @@
const RecordType *RT = Ty->getAs<RecordType>();
if (!RT)
- return 0;
+ return nullptr;
const ClassTemplateSpecializationDecl *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
if (!CTSD)
- return 0;
+ return nullptr;
Ty = Context.getTemplateSpecializationType(
TemplateName(CTSD->getSpecializedTemplate()),
@@ -901,9 +916,9 @@
// Handle Expressions
if (NonTypeTemplateParmDecl *DefaultNTTPD =
dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {
- Expr *FromExpr = 0, *ToExpr = 0;
+ Expr *FromExpr = nullptr, *ToExpr = nullptr;
llvm::APSInt FromInt, ToInt;
- ValueDecl *FromValueDecl = 0, *ToValueDecl = 0;
+ ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
unsigned ParamWidth = 128; // Safe default
if (DefaultNTTPD->getType()->isIntegralOrEnumerationType())
ParamWidth = Context.getIntWidth(DefaultNTTPD->getType());
@@ -1086,7 +1101,7 @@
/// GetExpr - Retrieves the template expression argument, including default
/// arguments.
Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) {
- Expr *ArgExpr = 0;
+ Expr *ArgExpr = nullptr;
bool isVariadic = DefaultNTTPD->isParameterPack();
if (!Iter.isEnd())
@@ -1150,7 +1165,7 @@
bool isVariadic = DefaultTTPD->isParameterPack();
TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument();
- TemplateDecl *DefaultTD = 0;
+ TemplateDecl *DefaultTD = nullptr;
if (TA.getKind() != TemplateArgument::Null)
DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
@@ -1159,7 +1174,7 @@
if (!isVariadic)
return DefaultTD;
- return 0;
+ return nullptr;
}
/// IsSameConvertedInt - Returns true if both integers are equal when
@@ -1430,7 +1445,7 @@
if (!E)
OS << "(no argument)";
else
- E->printPretty(OS, 0, Policy); return;
+ E->printPretty(OS, nullptr, Policy);
}
/// PrintTemplateTemplate - Handles printing of template template arguments,
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index dcfba3e..14e0e01 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -155,11 +155,11 @@
const Decl *Prev;
bool PrevRef;
public:
- ChildDumper(ASTDumper &Dumper) : Dumper(Dumper), Prev(0) {}
+ ChildDumper(ASTDumper &Dumper) : Dumper(Dumper), Prev(nullptr) {}
~ChildDumper() {
if (Prev) {
Dumper.lastChild();
- dump(0);
+ dump(nullptr);
}
}
@@ -178,14 +178,14 @@
// Give up ownership of the children of the node. By calling this,
// the caller takes back responsibility for calling lastChild().
- void release() { dump(0); }
+ void release() { dump(nullptr); }
};
public:
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
const SourceManager *SM)
: OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false),
- LastLocFilename(""), LastLocLine(~0U), FC(0),
+ LastLocFilename(""), LastLocLine(~0U), FC(nullptr),
ShowColors(SM && SM->getDiagnostics().getShowColors()) { }
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
@@ -216,7 +216,7 @@
void dumpBareType(QualType T);
void dumpType(QualType T);
void dumpBareDeclRef(const Decl *Node);
- void dumpDeclRef(const Decl *Node, const char *Label = 0);
+ void dumpDeclRef(const Decl *Node, const char *Label = nullptr);
void dumpName(const NamedDecl *D);
bool hasNodes(const DeclContext *DC);
void dumpDeclContext(const DeclContext *DC);
@@ -444,6 +444,9 @@
}
void ASTDumper::dumpLocation(SourceLocation Loc) {
+ if (!SM)
+ return;
+
ColorScope Color(*this, LocationColor);
SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
@@ -799,6 +802,8 @@
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
if (ND->isHidden())
OS << " hidden";
+ if (D->isImplicit())
+ OS << " implicit";
bool HasAttrs = D->hasAttrs();
const FullComment *Comment =
@@ -1684,6 +1689,7 @@
case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break;
case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break;
case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
+ case PredefinedExpr::FuncSig: OS << " __FUNCSIG__"; break;
}
}
@@ -1987,7 +1993,7 @@
FC = C;
dumpComment(C);
- FC = 0;
+ FC = nullptr;
}
void ASTDumper::dumpComment(const Comment *C) {
@@ -2154,17 +2160,17 @@
}
LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
- ASTDumper P(OS, 0, &SM);
+ ASTDumper P(OS, nullptr, &SM);
P.dumpStmt(this);
}
LLVM_DUMP_METHOD void Stmt::dump() const {
- ASTDumper P(llvm::errs(), 0, 0);
+ ASTDumper P(llvm::errs(), nullptr, nullptr);
P.dumpStmt(this);
}
LLVM_DUMP_METHOD void Stmt::dumpColor() const {
- ASTDumper P(llvm::errs(), 0, 0, /*ShowColors*/true);
+ ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
P.dumpStmt(this);
}
@@ -2172,7 +2178,9 @@
// Comment method implementations
//===----------------------------------------------------------------------===//
-LLVM_DUMP_METHOD void Comment::dump() const { dump(llvm::errs(), 0, 0); }
+LLVM_DUMP_METHOD void Comment::dump() const {
+ dump(llvm::errs(), nullptr, nullptr);
+}
LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const {
dump(llvm::errs(), &Context.getCommentCommandTraits(),
@@ -2188,6 +2196,6 @@
LLVM_DUMP_METHOD void Comment::dumpColor() const {
const FullComment *FC = dyn_cast<FullComment>(this);
- ASTDumper D(llvm::errs(), 0, 0, /*ShowColors*/true);
+ ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
D.dumpFullComment(FC);
}
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index ace526e..b180326 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -81,7 +81,7 @@
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
SourceLocation &Loc);
- void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = 0);
+ void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
@@ -1749,7 +1749,7 @@
}
QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
- NestedNameSpecifier *ToQualifier = 0;
+ NestedNameSpecifier *ToQualifier = nullptr;
// Note: the qualifier in an ElaboratedType is optional.
if (T->getQualifier()) {
ToQualifier = Importer.Import(T->getQualifier());
@@ -2060,8 +2060,8 @@
P != PEnd; ++P) {
Decl *To = Importer.Import(*P);
if (!To)
- return 0;
-
+ return nullptr;
+
ToParams.push_back(cast<NamedDecl>(To));
}
@@ -2221,7 +2221,7 @@
Decl *ASTNodeImporter::VisitDecl(Decl *D) {
Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
<< D->getDeclKindName();
- return 0;
+ return nullptr;
}
Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
@@ -2239,9 +2239,9 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
- NamespaceDecl *MergeWithNamespace = 0;
+ return nullptr;
+
+ NamespaceDecl *MergeWithNamespace = nullptr;
if (!Name) {
// This is an anonymous namespace. Adopt an existing anonymous
// namespace if we can.
@@ -2281,7 +2281,7 @@
D->isInline(),
Importer.Import(D->getLocStart()),
Loc, Name.getAsIdentifierInfo(),
- /*PrevDecl=*/0);
+ /*PrevDecl=*/nullptr);
ToNamespace->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToNamespace);
@@ -2307,8 +2307,8 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
// If this typedef is not in block scope, determine whether we've
// seen a typedef with the same name (that we can merge with) or any
// other entity by that name (which name lookup could conflict with).
@@ -2335,15 +2335,15 @@
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return 0;
+ return nullptr;
}
}
// Import the underlying type of this typedef;
QualType T = Importer.Import(D->getUnderlyingType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
// Create the new typedef node.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
SourceLocation StartL = Importer.Import(D->getLocStart());
@@ -2381,8 +2381,8 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
// Figure out what enum name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
DeclarationName SearchName = Name;
@@ -2425,7 +2425,7 @@
// Create the enum declaration.
EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getLocStart()),
- Loc, Name.getAsIdentifierInfo(), 0,
+ Loc, Name.getAsIdentifierInfo(), nullptr,
D->isScoped(), D->isScopedUsingClassTag(),
D->isFixed());
// Import the qualifier, if any.
@@ -2438,12 +2438,12 @@
// Import the integer type.
QualType ToIntegerType = Importer.Import(D->getIntegerType());
if (ToIntegerType.isNull())
- return 0;
+ return nullptr;
D2->setIntegerType(ToIntegerType);
// Import the definition
if (D->isCompleteDefinition() && ImportDefinition(D, D2))
- return 0;
+ return nullptr;
return D2;
}
@@ -2456,8 +2456,8 @@
if (Definition && Definition != D) {
Decl *ImportedDef = Importer.Import(Definition);
if (!ImportedDef)
- return 0;
-
+ return nullptr;
+
return Importer.Imported(D, ImportedDef);
}
@@ -2466,8 +2466,8 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
// Figure out what structure name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
DeclarationName SearchName = Name;
@@ -2478,7 +2478,7 @@
IDNS |= Decl::IDNS_Ordinary;
// We may already have a record of the same name; try to find and match it.
- RecordDecl *AdoptDecl = 0;
+ RecordDecl *AdoptDecl = nullptr;
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -2581,8 +2581,8 @@
Importer.Imported(D, D2);
if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default))
- return 0;
-
+ return nullptr;
+
return D2;
}
@@ -2592,11 +2592,11 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
+ return nullptr;
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
+ return nullptr;
// Determine whether there are any other declarations with the same name and
// in the same context.
@@ -2623,14 +2623,14 @@
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return 0;
+ return nullptr;
}
}
Expr *Init = Importer.Import(D->getInitExpr());
if (D->getInitExpr() && !Init)
- return 0;
-
+ return nullptr;
+
EnumConstantDecl *ToEnumerator
= EnumConstantDecl::Create(Importer.getToContext(), cast<EnumDecl>(DC), Loc,
Name.getAsIdentifierInfo(), T,
@@ -2648,7 +2648,7 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
+ return nullptr;
// Try to find a function in our own ("to") context with the same name, same
// type, and in the same context as the function we're importing.
@@ -2694,7 +2694,7 @@
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return 0;
+ return nullptr;
}
}
@@ -2724,21 +2724,21 @@
// Import the type.
QualType T = Importer.Import(FromTy);
if (T.isNull())
- return 0;
-
+ return nullptr;
+
// Import the function parameters.
SmallVector<ParmVarDecl *, 8> Parameters;
for (auto P : D->params()) {
ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P));
if (!ToP)
- return 0;
-
+ return nullptr;
+
Parameters.push_back(ToP);
}
// Create the imported function.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- FunctionDecl *ToFunction = 0;
+ FunctionDecl *ToFunction = nullptr;
if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
@@ -2803,7 +2803,7 @@
// Update FunctionProtoType::ExtProtoInfo.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
+ return nullptr;
ToFunction->setType(T);
}
@@ -2854,8 +2854,8 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
DC->localUncachedLookup(Name, FoundDecls);
@@ -2875,20 +2875,20 @@
<< Name << D->getType() << FoundField->getType();
Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
<< FoundField->getType();
- return 0;
+ return nullptr;
}
}
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
Expr *BitWidth = Importer.Import(D->getBitWidth());
if (!BitWidth && D->getBitWidth())
- return 0;
-
+ return nullptr;
+
FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getInnerLocStart()),
Loc, Name.getAsIdentifierInfo(),
@@ -2910,7 +2910,7 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
+ return nullptr;
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -2937,14 +2937,14 @@
<< Name << D->getType() << FoundField->getType();
Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
<< FoundField->getType();
- return 0;
+ return nullptr;
}
}
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
+ return nullptr;
NamedDecl **NamedChain =
new (Importer.getToContext())NamedDecl*[D->getChainingSize()];
@@ -2953,7 +2953,7 @@
for (auto *PI : D->chain()) {
Decl *D = Importer.Import(PI);
if (!D)
- return 0;
+ return nullptr;
NamedChain[i++] = cast<NamedDecl>(D);
}
@@ -2974,8 +2974,8 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
// Determine whether we've already imported this ivar
SmallVector<NamedDecl *, 2> FoundDecls;
DC->localUncachedLookup(Name, FoundDecls);
@@ -2991,20 +2991,20 @@
<< Name << D->getType() << FoundIvar->getType();
Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here)
<< FoundIvar->getType();
- return 0;
+ return nullptr;
}
}
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
Expr *BitWidth = Importer.Import(D->getBitWidth());
if (!BitWidth && D->getBitWidth())
- return 0;
-
+ return nullptr;
+
ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(),
cast<ObjCContainerDecl>(DC),
Importer.Import(D->getInnerLocStart()),
@@ -3024,12 +3024,12 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
// Try to find a variable in our own ("to") context with the same name and
// in the same context as the variable we're importing.
if (D->isFileVarDecl()) {
- VarDecl *MergeWithVar = 0;
+ VarDecl *MergeWithVar = nullptr;
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -3058,8 +3058,8 @@
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
FoundVar->setType(T);
MergeWithVar = FoundVar;
break;
@@ -3110,15 +3110,15 @@
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return 0;
+ return nullptr;
}
}
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
// Create the imported variable.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC,
@@ -3134,7 +3134,7 @@
// Merge the initializer.
if (ImportDefinition(D, ToVar))
- return 0;
+ return nullptr;
return ToVar;
}
@@ -3147,16 +3147,16 @@
// Import the name of this declaration.
DeclarationName Name = Importer.Import(D->getDeclName());
if (D->getDeclName() && !Name)
- return 0;
-
+ return nullptr;
+
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
// Import the parameter's type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
// Create the imported parameter.
ImplicitParamDecl *ToParm
= ImplicitParamDecl::Create(Importer.getToContext(), DC,
@@ -3173,23 +3173,23 @@
// Import the name of this declaration.
DeclarationName Name = Importer.Import(D->getDeclName());
if (D->getDeclName() && !Name)
- return 0;
-
+ return nullptr;
+
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
// Import the parameter's type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
// Create the imported parameter.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getInnerLocStart()),
Loc, Name.getAsIdentifierInfo(),
T, TInfo, D->getStorageClass(),
- /*FIXME: Default argument*/ 0);
+ /*FIXME: Default argument*/nullptr);
ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
return Importer.Imported(D, ToParm);
}
@@ -3200,8 +3200,8 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
SmallVector<NamedDecl *, 2> FoundDecls;
DC->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
@@ -3218,7 +3218,7 @@
Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
- return 0;
+ return nullptr;
}
// Check the number of parameters.
@@ -3229,7 +3229,7 @@
Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
- return 0;
+ return nullptr;
}
// Check parameter types.
@@ -3244,7 +3244,7 @@
<< (*P)->getType() << (*FoundP)->getType();
Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here)
<< (*FoundP)->getType();
- return 0;
+ return nullptr;
}
}
@@ -3256,7 +3256,7 @@
Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
- return 0;
+ return nullptr;
}
// FIXME: Any other bits we need to merge?
@@ -3267,7 +3267,7 @@
// Import the result type.
QualType ResultTy = Importer.Import(D->getReturnType());
if (ResultTy.isNull())
- return 0;
+ return nullptr;
TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo());
@@ -3285,8 +3285,8 @@
for (auto *FromP : D->params()) {
ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP));
if (!ToP)
- return 0;
-
+ return nullptr;
+
ToParams.push_back(ToP);
}
@@ -3311,13 +3311,13 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
ObjCInterfaceDecl *ToInterface
= cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface()));
if (!ToInterface)
- return 0;
-
+ return nullptr;
+
// Determine if we've already encountered this category.
ObjCCategoryDecl *MergeWithCategory
= ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo());
@@ -3347,7 +3347,7 @@
ObjCProtocolDecl *ToProto
= cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
if (!ToProto)
- return 0;
+ return nullptr;
Protocols.push_back(ToProto);
ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
}
@@ -3369,8 +3369,8 @@
= cast_or_null<ObjCCategoryImplDecl>(
Importer.Import(D->getImplementation()));
if (!Impl)
- return 0;
-
+ return nullptr;
+
ToCategory->setImplementation(Impl);
}
@@ -3425,8 +3425,8 @@
if (Definition && Definition != D) {
Decl *ImportedDef = Importer.Import(Definition);
if (!ImportedDef)
- return 0;
-
+ return nullptr;
+
return Importer.Imported(D, ImportedDef);
}
@@ -3435,9 +3435,9 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
+ return nullptr;
- ObjCProtocolDecl *MergeWithProtocol = 0;
+ ObjCProtocolDecl *MergeWithProtocol = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
@@ -3453,7 +3453,7 @@
ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC,
Name.getAsIdentifierInfo(), Loc,
Importer.Import(D->getAtStartLoc()),
- /*PrevDecl=*/0);
+ /*PrevDecl=*/nullptr);
ToProto->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToProto);
}
@@ -3461,8 +3461,8 @@
Importer.Imported(D, ToProto);
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto))
- return 0;
-
+ return nullptr;
+
return ToProto;
}
@@ -3570,8 +3570,8 @@
if (Definition && Definition != D) {
Decl *ImportedDef = Importer.Import(Definition);
if (!ImportedDef)
- return 0;
-
+ return nullptr;
+
return Importer.Imported(D, ImportedDef);
}
@@ -3580,10 +3580,10 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
+ return nullptr;
// Look for an existing interface with the same name.
- ObjCInterfaceDecl *MergeWithIface = 0;
+ ObjCInterfaceDecl *MergeWithIface = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
@@ -3600,7 +3600,7 @@
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getAtStartLoc()),
Name.getAsIdentifierInfo(),
- /*PrevDecl=*/0,Loc,
+ /*PrevDecl=*/nullptr, Loc,
D->isImplicitInterfaceDecl());
ToIface->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToIface);
@@ -3608,8 +3608,8 @@
Importer.Imported(D, ToIface);
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface))
- return 0;
-
+ return nullptr;
+
return ToIface;
}
@@ -3617,14 +3617,14 @@
ObjCCategoryDecl *Category = cast_or_null<ObjCCategoryDecl>(
Importer.Import(D->getCategoryDecl()));
if (!Category)
- return 0;
-
+ return nullptr;
+
ObjCCategoryImplDecl *ToImpl = Category->getImplementation();
if (!ToImpl) {
DeclContext *DC = Importer.ImportContext(D->getDeclContext());
if (!DC)
- return 0;
-
+ return nullptr;
+
SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc());
ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getIdentifier()),
@@ -3637,8 +3637,8 @@
if (D->getDeclContext() != D->getLexicalDeclContext()) {
LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
if (!LexicalDC)
- return 0;
-
+ return nullptr;
+
ToImpl->setLexicalDeclContext(LexicalDC);
}
@@ -3656,15 +3656,15 @@
ObjCInterfaceDecl *Iface = cast_or_null<ObjCInterfaceDecl>(
Importer.Import(D->getClassInterface()));
if (!Iface)
- return 0;
+ return nullptr;
// Import the superclass, if any.
- ObjCInterfaceDecl *Super = 0;
+ ObjCInterfaceDecl *Super = nullptr;
if (D->getSuperClass()) {
Super = cast_or_null<ObjCInterfaceDecl>(
Importer.Import(D->getSuperClass()));
if (!Super)
- return 0;
+ return nullptr;
}
ObjCImplementationDecl *Impl = Iface->getImplementation();
@@ -3684,7 +3684,7 @@
DeclContext *LexicalDC
= Importer.ImportContext(D->getLexicalDeclContext());
if (!LexicalDC)
- return 0;
+ return nullptr;
Impl->setLexicalDeclContext(LexicalDC);
}
@@ -3697,28 +3697,29 @@
// Verify that the existing @implementation has the same superclass.
if ((Super && !Impl->getSuperClass()) ||
(!Super && Impl->getSuperClass()) ||
- (Super && Impl->getSuperClass() &&
- !declaresSameEntity(Super->getCanonicalDecl(), Impl->getSuperClass()))) {
- Importer.ToDiag(Impl->getLocation(),
- diag::err_odr_objc_superclass_inconsistent)
- << Iface->getDeclName();
- // FIXME: It would be nice to have the location of the superclass
- // below.
- if (Impl->getSuperClass())
- Importer.ToDiag(Impl->getLocation(),
+ (Super && Impl->getSuperClass() &&
+ !declaresSameEntity(Super->getCanonicalDecl(),
+ Impl->getSuperClass()))) {
+ Importer.ToDiag(Impl->getLocation(),
+ diag::err_odr_objc_superclass_inconsistent)
+ << Iface->getDeclName();
+ // FIXME: It would be nice to have the location of the superclass
+ // below.
+ if (Impl->getSuperClass())
+ Importer.ToDiag(Impl->getLocation(),
+ diag::note_odr_objc_superclass)
+ << Impl->getSuperClass()->getDeclName();
+ else
+ Importer.ToDiag(Impl->getLocation(),
+ diag::note_odr_objc_missing_superclass);
+ if (D->getSuperClass())
+ Importer.FromDiag(D->getLocation(),
diag::note_odr_objc_superclass)
- << Impl->getSuperClass()->getDeclName();
- else
- Importer.ToDiag(Impl->getLocation(),
+ << D->getSuperClass()->getDeclName();
+ else
+ Importer.FromDiag(D->getLocation(),
diag::note_odr_objc_missing_superclass);
- if (D->getSuperClass())
- Importer.FromDiag(D->getLocation(),
- diag::note_odr_objc_superclass)
- << D->getSuperClass()->getDeclName();
- else
- Importer.FromDiag(D->getLocation(),
- diag::note_odr_objc_missing_superclass);
- return 0;
+ return nullptr;
}
}
@@ -3734,7 +3735,7 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
+ return nullptr;
// Check whether we have already imported this property.
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -3749,7 +3750,7 @@
<< Name << D->getType() << FoundProp->getType();
Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here)
<< FoundProp->getType();
- return 0;
+ return nullptr;
}
// FIXME: Check property attributes, getters, setters, etc.?
@@ -3763,7 +3764,7 @@
// Import the type.
TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo());
if (!T)
- return 0;
+ return nullptr;
// Create the new property.
ObjCPropertyDecl *ToProperty
@@ -3795,31 +3796,31 @@
ObjCPropertyDecl *Property = cast_or_null<ObjCPropertyDecl>(
Importer.Import(D->getPropertyDecl()));
if (!Property)
- return 0;
+ return nullptr;
DeclContext *DC = Importer.ImportContext(D->getDeclContext());
if (!DC)
- return 0;
-
+ return nullptr;
+
// Import the lexical declaration context.
DeclContext *LexicalDC = DC;
if (D->getDeclContext() != D->getLexicalDeclContext()) {
LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
if (!LexicalDC)
- return 0;
+ return nullptr;
}
ObjCImplDecl *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC);
if (!InImpl)
- return 0;
+ return nullptr;
// Import the ivar (for an @synthesize).
- ObjCIvarDecl *Ivar = 0;
+ ObjCIvarDecl *Ivar = nullptr;
if (D->getPropertyIvarDecl()) {
Ivar = cast_or_null<ObjCIvarDecl>(
Importer.Import(D->getPropertyIvarDecl()));
if (!Ivar)
- return 0;
+ return nullptr;
}
ObjCPropertyImplDecl *ToImpl
@@ -3848,7 +3849,7 @@
diag::note_odr_objc_property_impl_kind)
<< D->getPropertyDecl()->getDeclName()
<< (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic);
- return 0;
+ return nullptr;
}
// For @synthesize, check that we have the same
@@ -3862,7 +3863,7 @@
Importer.FromDiag(D->getPropertyIvarDeclLoc(),
diag::note_odr_objc_synthesize_ivar_here)
<< D->getPropertyIvarDecl()->getDeclName();
- return 0;
+ return nullptr;
}
// Merge the existing implementation with the new implementation.
@@ -3894,21 +3895,21 @@
// Import the name of this declaration.
DeclarationName Name = Importer.Import(D->getDeclName());
if (D->getDeclName() && !Name)
- return 0;
-
+ return nullptr;
+
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
// Import the type of this declaration.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
// Import type-source information.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
if (D->getTypeSourceInfo() && !TInfo)
- return 0;
-
+ return nullptr;
+
// FIXME: Import default argument.
return NonTypeTemplateParmDecl::Create(Importer.getToContext(),
@@ -3924,8 +3925,8 @@
// Import the name of this declaration.
DeclarationName Name = Importer.Import(D->getDeclName());
if (D->getDeclName() && !Name)
- return 0;
-
+ return nullptr;
+
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
@@ -3933,8 +3934,8 @@
TemplateParameterList *TemplateParams
= ImportTemplateParameterList(D->getTemplateParameters());
if (!TemplateParams)
- return 0;
-
+ return nullptr;
+
// FIXME: Import default argument.
return TemplateTemplateParmDecl::Create(Importer.getToContext(),
@@ -3955,8 +3956,8 @@
Decl *ImportedDef
= Importer.Import(Definition->getDescribedClassTemplate());
if (!ImportedDef)
- return 0;
-
+ return nullptr;
+
return Importer.Imported(D, ImportedDef);
}
@@ -3965,8 +3966,8 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
-
+ return nullptr;
+
// We may already have a template of the same name; try to find and match it.
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
@@ -3999,7 +4000,7 @@
}
if (!Name)
- return 0;
+ return nullptr;
}
CXXRecordDecl *DTemplated = D->getTemplatedDecl();
@@ -4019,12 +4020,12 @@
TemplateParameterList *TemplateParams
= ImportTemplateParameterList(D->getTemplateParameters());
if (!TemplateParams)
- return 0;
-
+ return nullptr;
+
ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC,
Loc, Name, TemplateParams,
D2Templated,
- /*PrevDecl=*/0);
+ /*PrevDecl=*/nullptr);
D2Templated->setDescribedClassTemplate(D2);
D2->setAccess(D->getAccess());
@@ -4052,8 +4053,8 @@
if (Definition && Definition != D) {
Decl *ImportedDef = Importer.Import(Definition);
if (!ImportedDef)
- return 0;
-
+ return nullptr;
+
return Importer.Imported(D, ImportedDef);
}
@@ -4061,18 +4062,18 @@
= cast_or_null<ClassTemplateDecl>(Importer.Import(
D->getSpecializedTemplate()));
if (!ClassTemplate)
- return 0;
-
+ return nullptr;
+
// Import the context of this declaration.
DeclContext *DC = ClassTemplate->getDeclContext();
if (!DC)
- return 0;
-
+ return nullptr;
+
DeclContext *LexicalDC = DC;
if (D->getDeclContext() != D->getLexicalDeclContext()) {
LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
if (!LexicalDC)
- return 0;
+ return nullptr;
}
// Import the location of this declaration.
@@ -4084,10 +4085,10 @@
if (ImportTemplateArguments(D->getTemplateArgs().data(),
D->getTemplateArgs().size(),
TemplateArgs))
- return 0;
-
+ return nullptr;
+
// Try to find an existing specialization with these template arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *D2
= ClassTemplate->findSpecialization(TemplateArgs.data(),
TemplateArgs.size(), InsertPos);
@@ -4113,7 +4114,7 @@
ClassTemplate,
TemplateArgs.data(),
TemplateArgs.size(),
- /*PrevDecl=*/0);
+ /*PrevDecl=*/nullptr);
D2->setSpecializationKind(D->getSpecializationKind());
// Add this specialization to the class template.
@@ -4129,8 +4130,8 @@
Importer.Imported(D, D2);
if (D->isCompleteDefinition() && ImportDefinition(D, D2))
- return 0;
-
+ return nullptr;
+
return D2;
}
@@ -4144,7 +4145,7 @@
if (Definition && Definition != D->getTemplatedDecl()) {
Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate());
if (!ImportedDef)
- return 0;
+ return nullptr;
return Importer.Imported(D, ImportedDef);
}
@@ -4154,7 +4155,7 @@
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
- return 0;
+ return nullptr;
// We may already have a template of the same name; try to find and match it.
assert(!DC->isFunctionOrMethod() &&
@@ -4186,14 +4187,14 @@
}
if (!Name)
- return 0;
+ return nullptr;
VarDecl *DTemplated = D->getTemplatedDecl();
// Import the type.
QualType T = Importer.Import(DTemplated->getType());
if (T.isNull())
- return 0;
+ return nullptr;
// Create the declaration that is being templated.
SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart());
@@ -4211,13 +4212,13 @@
// Merge the initializer.
if (ImportDefinition(DTemplated, D2Templated))
- return 0;
+ return nullptr;
// Create the variable template declaration itself.
TemplateParameterList *TemplateParams =
ImportTemplateParameterList(D->getTemplateParameters());
if (!TemplateParams)
- return 0;
+ return nullptr;
VarTemplateDecl *D2 = VarTemplateDecl::Create(
Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated);
@@ -4248,7 +4249,7 @@
if (Definition && Definition != D) {
Decl *ImportedDef = Importer.Import(Definition);
if (!ImportedDef)
- return 0;
+ return nullptr;
return Importer.Imported(D, ImportedDef);
}
@@ -4256,18 +4257,18 @@
VarTemplateDecl *VarTemplate = cast_or_null<VarTemplateDecl>(
Importer.Import(D->getSpecializedTemplate()));
if (!VarTemplate)
- return 0;
+ return nullptr;
// Import the context of this declaration.
DeclContext *DC = VarTemplate->getDeclContext();
if (!DC)
- return 0;
+ return nullptr;
DeclContext *LexicalDC = DC;
if (D->getDeclContext() != D->getLexicalDeclContext()) {
LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
if (!LexicalDC)
- return 0;
+ return nullptr;
}
// Import the location of this declaration.
@@ -4278,10 +4279,10 @@
SmallVector<TemplateArgument, 2> TemplateArgs;
if (ImportTemplateArguments(D->getTemplateArgs().data(),
D->getTemplateArgs().size(), TemplateArgs))
- return 0;
+ return nullptr;
// Try to find an existing specialization with these template arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization(
TemplateArgs.data(), TemplateArgs.size(), InsertPos);
if (D2) {
@@ -4304,7 +4305,7 @@
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
- return 0;
+ return nullptr;
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
// Create a new specialization.
@@ -4327,7 +4328,7 @@
Importer.Imported(D, D2);
if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2))
- return 0;
+ return nullptr;
return D2;
}
@@ -4339,7 +4340,7 @@
Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
<< S->getStmtClassName();
- return 0;
+ return nullptr;
}
//----------------------------------------------------------------------------
@@ -4348,24 +4349,24 @@
Expr *ASTNodeImporter::VisitExpr(Expr *E) {
Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node)
<< E->getStmtClassName();
- return 0;
+ return nullptr;
}
Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl()));
if (!ToD)
- return 0;
+ return nullptr;
- NamedDecl *FoundD = 0;
+ NamedDecl *FoundD = nullptr;
if (E->getDecl() != E->getFoundDecl()) {
FoundD = cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl()));
if (!FoundD)
- return 0;
+ return nullptr;
}
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return 0;
+ return nullptr;
DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
Importer.Import(E->getQualifierLoc()),
@@ -4375,7 +4376,7 @@
Importer.Import(E->getLocation()),
T, E->getValueKind(),
FoundD,
- /*FIXME:TemplateArgs=*/0);
+ /*FIXME:TemplateArgs=*/nullptr);
if (E->hadMultipleCandidates())
DRE->setHadMultipleCandidates(true);
return DRE;
@@ -4384,7 +4385,7 @@
Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return 0;
+ return nullptr;
return IntegerLiteral::Create(Importer.getToContext(),
E->getValue(), T,
@@ -4394,8 +4395,8 @@
Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
return new (Importer.getToContext()) CharacterLiteral(E->getValue(),
E->getKind(), T,
Importer.Import(E->getLocation()));
@@ -4404,8 +4405,8 @@
Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr)
- return 0;
-
+ return nullptr;
+
return new (Importer.getToContext())
ParenExpr(Importer.Import(E->getLParen()),
Importer.Import(E->getRParen()),
@@ -4415,12 +4416,12 @@
Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return 0;
+ return nullptr;
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr)
- return 0;
-
+ return nullptr;
+
return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(),
T, E->getValueKind(),
E->getObjectKind(),
@@ -4434,8 +4435,8 @@
if (E->isArgumentType()) {
TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo());
if (!TInfo)
- return 0;
-
+ return nullptr;
+
return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
TInfo, ResultType,
Importer.Import(E->getOperatorLoc()),
@@ -4444,8 +4445,8 @@
Expr *SubExpr = Importer.Import(E->getArgumentExpr());
if (!SubExpr)
- return 0;
-
+ return nullptr;
+
return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
SubExpr, ResultType,
Importer.Import(E->getOperatorLoc()),
@@ -4455,16 +4456,16 @@
Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return 0;
+ return nullptr;
Expr *LHS = Importer.Import(E->getLHS());
if (!LHS)
- return 0;
-
+ return nullptr;
+
Expr *RHS = Importer.Import(E->getRHS());
if (!RHS)
- return 0;
-
+ return nullptr;
+
return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(),
T, E->getValueKind(),
E->getObjectKind(),
@@ -4475,24 +4476,24 @@
Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
QualType CompLHSType = Importer.Import(E->getComputationLHSType());
if (CompLHSType.isNull())
- return 0;
-
+ return nullptr;
+
QualType CompResultType = Importer.Import(E->getComputationResultType());
if (CompResultType.isNull())
- return 0;
-
+ return nullptr;
+
Expr *LHS = Importer.Import(E->getLHS());
if (!LHS)
- return 0;
-
+ return nullptr;
+
Expr *RHS = Importer.Import(E->getRHS());
if (!RHS)
- return 0;
-
+ return nullptr;
+
return new (Importer.getToContext())
CompoundAssignOperator(LHS, RHS, E->getOpcode(),
T, E->getValueKind(),
@@ -4512,15 +4513,15 @@
Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return 0;
+ return nullptr;
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr)
- return 0;
+ return nullptr;
CXXCastPath BasePath;
if (ImportCastPath(E, BasePath))
- return 0;
+ return nullptr;
return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
SubExpr, &BasePath, E->getValueKind());
@@ -4529,19 +4530,19 @@
Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return 0;
-
+ return nullptr;
+
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr)
- return 0;
+ return nullptr;
TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten());
if (!TInfo && E->getTypeInfoAsWritten())
- return 0;
-
+ return nullptr;
+
CXXCastPath BasePath;
if (ImportCastPath(E, BasePath))
- return 0;
+ return nullptr;
return CStyleCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), E->getCastKind(),
@@ -4595,7 +4596,7 @@
// on the type and a single location. Implement a real version of this.
QualType T = Import(FromTSI->getType());
if (T.isNull())
- return 0;
+ return nullptr;
return ToContext.getTrivialTypeSourceInfo(T,
FromTSI->getTypeLoc().getLocStart());
@@ -4603,7 +4604,7 @@
Decl *ASTImporter::Import(Decl *FromD) {
if (!FromD)
- return 0;
+ return nullptr;
ASTNodeImporter Importer(*this);
@@ -4618,8 +4619,8 @@
// Import the type
Decl *ToD = Importer.Visit(FromD);
if (!ToD)
- return 0;
-
+ return nullptr;
+
// Record the imported declaration.
ImportedDecls[FromD] = ToD;
@@ -4654,8 +4655,8 @@
DeclContext *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC)));
if (!ToDC)
- return 0;
-
+ return nullptr;
+
// When we're using a record/enum/Objective-C class/protocol as a context, we
// need it to have a definition.
if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(ToDC)) {
@@ -4705,14 +4706,14 @@
Expr *ASTImporter::Import(Expr *FromE) {
if (!FromE)
- return 0;
+ return nullptr;
return cast_or_null<Expr>(Import(cast<Stmt>(FromE)));
}
Stmt *ASTImporter::Import(Stmt *FromS) {
if (!FromS)
- return 0;
+ return nullptr;
// Check whether we've already imported this declaration.
llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS);
@@ -4723,8 +4724,8 @@
ASTNodeImporter Importer(*this);
Stmt *ToS = Importer.Visit(FromS);
if (!ToS)
- return 0;
-
+ return nullptr;
+
// Record the imported declaration.
ImportedStmts[FromS] = ToS;
return ToS;
@@ -4732,7 +4733,7 @@
NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
if (!FromNNS)
- return 0;
+ return nullptr;
NestedNameSpecifier *prefix = Import(FromNNS->getPrefix());
@@ -4741,21 +4742,21 @@
if (IdentifierInfo *II = Import(FromNNS->getAsIdentifier())) {
return NestedNameSpecifier::Create(ToContext, prefix, II);
}
- return 0;
+ return nullptr;
case NestedNameSpecifier::Namespace:
if (NamespaceDecl *NS =
cast<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) {
return NestedNameSpecifier::Create(ToContext, prefix, NS);
}
- return 0;
+ return nullptr;
case NestedNameSpecifier::NamespaceAlias:
if (NamespaceAliasDecl *NSAD =
cast<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) {
return NestedNameSpecifier::Create(ToContext, prefix, NSAD);
}
- return 0;
+ return nullptr;
case NestedNameSpecifier::Global:
return NestedNameSpecifier::GlobalSpecifier(ToContext);
@@ -4770,7 +4771,7 @@
bTemplate, T.getTypePtr());
}
}
- return 0;
+ return nullptr;
}
llvm_unreachable("Invalid nested name specifier kind");
@@ -4922,8 +4923,7 @@
llvm::MemoryBuffer *ToBuf
= llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
FromBuf->getBufferIdentifier());
- ToID = ToSM.createFileIDForMemBuffer(ToBuf,
- FromSLoc.getFile().getFileCharacteristic());
+ ToID = ToSM.createFileID(ToBuf, FromSLoc.getFile().getFileCharacteristic());
}
@@ -5033,7 +5033,7 @@
IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) {
if (!FromId)
- return 0;
+ return nullptr;
return &ToContext.Idents.get(FromId->getName());
}
diff --git a/lib/AST/ASTTypeTraits.cpp b/lib/AST/ASTTypeTraits.cpp
index 02d82d8..baa8e48 100644
--- a/lib/AST/ASTTypeTraits.cpp
+++ b/lib/AST/ASTTypeTraits.cpp
@@ -77,7 +77,7 @@
else if (const Decl *D = get<Decl>())
D->print(OS, PP);
else if (const Stmt *S = get<Stmt>())
- S->printPretty(OS, 0, PP);
+ S->printPretty(OS, nullptr, PP);
else if (const Type *T = get<Type>())
QualType(T, 0).print(OS, PP);
else
diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h
index 89203f1..12b929b 100644
--- a/lib/AST/CXXABI.h
+++ b/lib/AST/CXXABI.h
@@ -44,7 +44,6 @@
};
/// Creates an instance of a C++ ABI class.
-CXXABI *CreateARMCXXABI(ASTContext &Ctx);
CXXABI *CreateItaniumCXXABI(ASTContext &Ctx);
CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx);
}
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index eef043c..6e80ee7 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -58,7 +58,7 @@
Paths.clear();
ClassSubobjects.clear();
ScratchPath.clear();
- DetectedVirtual = 0;
+ DetectedVirtual = nullptr;
}
/// @brief Swaps the contents of this CXXBasePaths structure with the
@@ -203,7 +203,7 @@
if (BaseSpec.isVirtual()) {
VisitBase = !Subobjects.first;
Subobjects.first = true;
- if (isDetectingVirtual() && DetectedVirtual == 0) {
+ if (isDetectingVirtual() && DetectedVirtual == nullptr) {
// If this is the first virtual we find, remember it. If it turns out
// there is no base path here, we'll reset it later.
DetectedVirtual = BaseType->getAs<RecordType>();
@@ -286,7 +286,7 @@
// If we set a virtual earlier, and this isn't a path, forget it again.
if (SetVirtual && !FoundPathThroughBase) {
- DetectedVirtual = 0;
+ DetectedVirtual = nullptr;
}
}
@@ -325,7 +325,7 @@
for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end();
PE != PEEnd && !Hidden; ++PE) {
if (PE->Base->isVirtual()) {
- CXXRecordDecl *VBase = 0;
+ CXXRecordDecl *VBase = nullptr;
if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>())
VBase = cast<CXXRecordDecl>(Record->getDecl());
if (!VBase)
@@ -339,7 +339,7 @@
HidingPEnd = Paths.end();
HidingP != HidingPEnd;
++HidingP) {
- CXXRecordDecl *HidingClass = 0;
+ CXXRecordDecl *HidingClass = nullptr;
if (const RecordType *Record
= HidingP->back().Base->getType()->getAs<RecordType>())
HidingClass = cast<CXXRecordDecl>(Record->getDecl());
@@ -625,7 +625,7 @@
void
CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
FinalOverriderCollector Collector;
- Collector.Collect(this, false, 0, FinalOverriders);
+ Collector.Collect(this, false, nullptr, FinalOverriders);
// Weed out any final overriders that come from virtual base class
// subobjects that were hidden by other subobjects along any path.
diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp
index b0b2351..4f43346 100644
--- a/lib/AST/Comment.cpp
+++ b/lib/AST/Comment.cpp
@@ -136,7 +136,7 @@
IsInstanceMethod = false;
IsClassMethod = false;
ParamVars = None;
- TemplateParameters = NULL;
+ TemplateParameters = nullptr;
if (!CommentDecl) {
// If there is no declaration, the defaults is our only guess.
diff --git a/lib/AST/CommentCommandTraits.cpp b/lib/AST/CommentCommandTraits.cpp
index 8879aac..a7b07a4 100644
--- a/lib/AST/CommentCommandTraits.cpp
+++ b/lib/AST/CommentCommandTraits.cpp
@@ -113,7 +113,7 @@
unsigned CommandID) {
if (CommandID < llvm::array_lengthof(Commands))
return &Commands[CommandID];
- return NULL;
+ return nullptr;
}
const CommandInfo *CommandTraits::getRegisteredCommandInfo(
@@ -122,7 +122,7 @@
if (RegisteredCommands[i]->Name == Name)
return RegisteredCommands[i];
}
- return NULL;
+ return nullptr;
}
const CommandInfo *CommandTraits::getRegisteredCommandInfo(
diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp
index 03e0101..cb37ec3 100644
--- a/lib/AST/CommentParser.cpp
+++ b/lib/AST/CommentParser.cpp
@@ -311,9 +311,9 @@
BlockCommandComment *Parser::parseBlockCommand() {
assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));
- ParamCommandComment *PC = 0;
- TParamCommandComment *TPC = 0;
- BlockCommandComment *BC = 0;
+ ParamCommandComment *PC = nullptr;
+ TParamCommandComment *TPC = nullptr;
+ BlockCommandComment *BC = nullptr;
const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
CommandMarkerKind CommandMarker =
Tok.is(tok::backslash_command) ? CMK_Backslash : CMK_At;
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index e51f878..12823c3 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -29,7 +29,8 @@
DiagnosticsEngine &Diags, CommandTraits &Traits,
const Preprocessor *PP) :
Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
- PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), HeaderfileCommand(NULL) {
+ PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr),
+ HeaderfileCommand(nullptr) {
}
void Sema::setDecl(const Decl *D) {
@@ -482,6 +483,7 @@
if (isHTMLEndTagForbidden(TagName)) {
Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden)
<< TagName << HET->getSourceRange();
+ HET->setIsMalformed();
return HET;
}
@@ -497,14 +499,19 @@
if (!FoundOpen) {
Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced)
<< HET->getSourceRange();
+ HET->setIsMalformed();
return HET;
}
while (!HTMLOpenTags.empty()) {
- const HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
+ HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
StringRef LastNotClosedTagName = HST->getTagName();
- if (LastNotClosedTagName == TagName)
+ if (LastNotClosedTagName == TagName) {
+ // If the start tag is malformed, end tag is malformed as well.
+ if (HST->isMalformed())
+ HET->setIsMalformed();
break;
+ }
if (isHTMLEndTagOptional(LastNotClosedTagName))
continue;
@@ -518,16 +525,18 @@
HET->getLocation(),
&CloseLineInvalid);
- if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine)
+ if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) {
Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
<< HST->getTagName() << HET->getTagName()
<< HST->getSourceRange() << HET->getSourceRange();
- else {
+ HST->setIsMalformed();
+ } else {
Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
<< HST->getTagName() << HET->getTagName()
<< HST->getSourceRange();
Diag(HET->getLocation(), diag::note_doc_html_end_tag)
<< HET->getSourceRange();
+ HST->setIsMalformed();
}
}
@@ -538,6 +547,18 @@
ArrayRef<BlockContentComment *> Blocks) {
FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
resolveParamCommandIndexes(FC);
+
+ // Complain about HTML tags that are not closed.
+ while (!HTMLOpenTags.empty()) {
+ HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
+ if (isHTMLEndTagOptional(HST->getTagName()))
+ continue;
+
+ Diag(HST->getLocation(), diag::warn_doc_html_missing_end_tag)
+ << HST->getTagName() << HST->getSourceRange();
+ HST->setIsMalformed();
+ }
+
return FC;
}
@@ -603,7 +624,7 @@
void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
- const BlockCommandComment *PrevCommand = NULL;
+ const BlockCommandComment *PrevCommand = nullptr;
if (Info->IsBriefCommand) {
if (!BriefCommand) {
BriefCommand = Command;
@@ -703,7 +724,7 @@
SmallVector<ParamCommandComment *, 8> ParamVarDocs;
ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
- ParamVarDocs.resize(ParamVars.size(), NULL);
+ ParamVarDocs.resize(ParamVars.size(), nullptr);
// First pass over all \\param commands: resolve all parameter names.
for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
@@ -942,7 +963,7 @@
public:
SimpleTypoCorrector(StringRef Typo) :
Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
- BestDecl(NULL), BestEditDistance(MaxEditDistance + 1),
+ BestDecl(nullptr), BestEditDistance(MaxEditDistance + 1),
BestIndex(0), NextIndex(0)
{ }
@@ -950,7 +971,7 @@
const NamedDecl *getBestDecl() const {
if (BestEditDistance > MaxEditDistance)
- return NULL;
+ return nullptr;
return BestDecl;
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 15410f0..1c3a538 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -227,23 +227,21 @@
/// template parameter list. For visibility purposes, template
/// parameters are part of the signature of a template.
static LinkageInfo
-getLVForTemplateParameterList(const TemplateParameterList *params,
+getLVForTemplateParameterList(const TemplateParameterList *Params,
LVComputationKind computation) {
LinkageInfo LV;
- for (TemplateParameterList::const_iterator P = params->begin(),
- PEnd = params->end();
- P != PEnd; ++P) {
-
+ for (const NamedDecl *P : *Params) {
// Template type parameters are the most common and never
// contribute to visibility, pack or not.
- if (isa<TemplateTypeParmDecl>(*P))
+ if (isa<TemplateTypeParmDecl>(P))
continue;
// Non-type template parameters can be restricted by the value type, e.g.
// template <enum X> class A { ... };
// We have to be careful here, though, because we can be dealing with
// dependent types.
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ if (const NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(P)) {
// Handle the non-pack case first.
if (!NTTP->isExpandedParameterPack()) {
if (!NTTP->getType()->isDependentType()) {
@@ -263,7 +261,7 @@
// Template template parameters can be restricted by their
// template parameters, recursively.
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+ const TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(P);
// Handle the non-pack case first.
if (!TTP->isExpandedParameterPack()) {
@@ -288,7 +286,7 @@
LVComputationKind computation);
static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
- const Decl *Ret = NULL;
+ const Decl *Ret = nullptr;
const DeclContext *DC = D->getDeclContext();
while (DC->getDeclKind() != Decl::TranslationUnit) {
if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC))
@@ -303,43 +301,41 @@
///
/// Note that we don't take an LVComputationKind because we always
/// want to honor the visibility of template arguments in the same way.
-static LinkageInfo
-getLVForTemplateArgumentList(ArrayRef<TemplateArgument> args,
- LVComputationKind computation) {
+static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
+ LVComputationKind computation) {
LinkageInfo LV;
- for (unsigned i = 0, e = args.size(); i != e; ++i) {
- const TemplateArgument &arg = args[i];
- switch (arg.getKind()) {
+ for (const TemplateArgument &Arg : Args) {
+ switch (Arg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Expression:
continue;
case TemplateArgument::Type:
- LV.merge(getLVForType(*arg.getAsType(), computation));
+ LV.merge(getLVForType(*Arg.getAsType(), computation));
continue;
case TemplateArgument::Declaration:
- if (NamedDecl *ND = dyn_cast<NamedDecl>(arg.getAsDecl())) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) {
assert(!usesTypeVisibility(ND));
LV.merge(getLVForDecl(ND, computation));
}
continue;
case TemplateArgument::NullPtr:
- LV.merge(arg.getNullPtrType()->getLinkageAndVisibility());
+ LV.merge(Arg.getNullPtrType()->getLinkageAndVisibility());
continue;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
- if (TemplateDecl *Template
- = arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
+ if (TemplateDecl *Template =
+ Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
LV.merge(getLVForDecl(Template, computation));
continue;
case TemplateArgument::Pack:
- LV.merge(getLVForTemplateArgumentList(arg.getPackAsArray(), computation));
+ LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation));
continue;
}
llvm_unreachable("bad template argument kind");
@@ -494,7 +490,7 @@
TSK = MSI->getTemplateSpecializationKind();
}
- const FunctionDecl *Def = 0;
+ const FunctionDecl *Def = nullptr;
// InlineVisibilityHidden only applies to definitions, and
// isInlined() only gives meaningful answers on definitions
// anyway.
@@ -822,7 +818,7 @@
// we need to completely ignore the visibility from it.
// Specifically, if this decl exists and has an explicit attribute.
- const NamedDecl *explicitSpecSuppressor = 0;
+ const NamedDecl *explicitSpecSuppressor = nullptr;
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
// If the type of the function uses a type with unique-external
@@ -986,6 +982,10 @@
return getVisibilityOf(InstantiatedFrom, kind);
}
+ if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Var))
+ return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(),
+ kind);
+
return None;
}
// Also handle function template specializations.
@@ -1240,7 +1240,7 @@
// We have just computed the linkage for this decl. By induction we know
// that all other computed linkages match, check that the one we just
// computed also does.
- NamedDecl *Old = NULL;
+ NamedDecl *Old = nullptr;
for (auto I : D->redecls()) {
NamedDecl *T = cast<NamedDecl>(I);
if (T == D)
@@ -1313,7 +1313,7 @@
else
OS << *RD;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
- const FunctionProtoType *FT = 0;
+ const FunctionProtoType *FT = nullptr;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>());
@@ -1580,13 +1580,13 @@
QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
unsigned NumTPLists,
TemplateParameterList **TPLists) {
- assert((NumTPLists == 0 || TPLists != 0) &&
+ assert((NumTPLists == 0 || TPLists != nullptr) &&
"Empty array of template parameters with positive size!");
// Free previous template parameters (if any).
if (NumTemplParamLists > 0) {
Context.Deallocate(TemplParamLists);
- TemplParamLists = 0;
+ TemplParamLists = nullptr;
NumTemplParamLists = 0;
}
// Set info on matched template parameter lists (if any).
@@ -1616,10 +1616,12 @@
llvm_unreachable("Invalid storage class");
}
-VarDecl::VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo, StorageClass SC)
- : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() {
+VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
+ StorageClass SC)
+ : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
+ redeclarable_base(C), Init() {
static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned),
"VarDeclBitfields too large!");
static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned),
@@ -1633,12 +1635,13 @@
SourceLocation StartL, SourceLocation IdL,
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
StorageClass S) {
- return new (C, DC) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S);
+ return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S);
}
VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) VarDecl(Var, 0, SourceLocation(), SourceLocation(), 0,
- QualType(), 0, SC_None);
+ return new (C, ID)
+ VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
+ QualType(), nullptr, SC_None);
}
void VarDecl::setStorageClass(StorageClass SC) {
@@ -1646,6 +1649,21 @@
VarDeclBits.SClass = SC;
}
+VarDecl::TLSKind VarDecl::getTLSKind() const {
+ switch (VarDeclBits.TSCSpec) {
+ case TSCS_unspecified:
+ if (hasAttr<ThreadAttr>())
+ return TLS_Static;
+ return TLS_None;
+ case TSCS___thread: // Fall through.
+ case TSCS__Thread_local:
+ return TLS_Static;
+ case TSCS_thread_local:
+ return TLS_Dynamic;
+ }
+ llvm_unreachable("Unknown thread storage class specifier!");
+}
+
SourceRange VarDecl::getSourceRange() const {
if (const Expr *Init = getInit()) {
SourceLocation InitEnd = Init->getLocEnd();
@@ -1791,14 +1809,14 @@
VarDecl *VarDecl::getActingDefinition() {
DefinitionKind Kind = isThisDeclarationADefinition();
if (Kind != TentativeDefinition)
- return 0;
+ return nullptr;
- VarDecl *LastTentative = 0;
+ VarDecl *LastTentative = nullptr;
VarDecl *First = getFirstDecl();
for (auto I : First->redecls()) {
Kind = I->isThisDeclarationADefinition();
if (Kind == Definition)
- return 0;
+ return nullptr;
else if (Kind == TentativeDefinition)
LastTentative = I;
}
@@ -1811,7 +1829,7 @@
if (I->isThisDeclarationADefinition(C) == Definition)
return I;
}
- return 0;
+ return nullptr;
}
VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const {
@@ -1834,7 +1852,7 @@
return Expr;
}
}
- return 0;
+ return nullptr;
}
bool VarDecl::isOutOfLine() const {
@@ -1855,14 +1873,14 @@
VarDecl *VarDecl::getOutOfLineDefinition() {
if (!isStaticDataMember())
- return 0;
-
+ return nullptr;
+
for (auto RD : redecls()) {
if (RD->getLexicalDeclContext()->isFileContext())
return RD;
}
-
- return 0;
+
+ return nullptr;
}
void VarDecl::setInit(Expr *I) {
@@ -1939,7 +1957,7 @@
// first time it is evaluated. FIXME: The notes won't always be emitted the
// first time we try evaluation, so might not be produced at all.
if (Eval->WasEvaluated)
- return Eval->Evaluated.isUninit() ? 0 : &Eval->Evaluated;
+ return Eval->Evaluated.isUninit() ? nullptr : &Eval->Evaluated;
const Expr *Init = cast<Expr>(Eval->Value);
assert(!Init->isValueDependent());
@@ -1948,7 +1966,7 @@
// FIXME: Produce a diagnostic for self-initialization.
Eval->CheckedICE = true;
Eval->IsICE = false;
- return 0;
+ return nullptr;
}
Eval->IsEvaluating = true;
@@ -1974,7 +1992,7 @@
Eval->IsICE = Result && Notes.empty();
}
- return Result ? &Eval->Evaluated : 0;
+ return Result ? &Eval->Evaluated : nullptr;
}
bool VarDecl::checkInitIsICE() const {
@@ -2016,8 +2034,8 @@
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
-
- return 0;
+
+ return nullptr;
}
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
@@ -2057,7 +2075,7 @@
// return getASTContext().getInstantiatedFromStaticDataMember(this);
return getASTContext().getTemplateOrSpecializationInfo(this)
.dyn_cast<MemberSpecializationInfo *>();
- return 0;
+ return nullptr;
}
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
@@ -2099,7 +2117,7 @@
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, Expr *DefArg) {
- return new (C, DC) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo,
+ return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo,
S, DefArg);
}
@@ -2112,8 +2130,9 @@
}
ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(),
- 0, QualType(), 0, SC_None, 0);
+ return new (C, ID)
+ ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(),
+ nullptr, QualType(), nullptr, SC_None, nullptr);
}
SourceRange ParmVarDecl::getSourceRange() const {
@@ -2224,12 +2243,12 @@
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
if (!hasBody(Definition))
- return 0;
+ return nullptr;
if (Definition->Body)
return Definition->Body.get(getASTContext().getExternalSource());
- return 0;
+ return nullptr;
}
void FunctionDecl::setBody(Stmt *B) {
@@ -2309,12 +2328,6 @@
return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy);
}
-static bool isNamespaceStd(const DeclContext *DC) {
- const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC->getRedeclContext());
- return ND && isNamed(ND, "std") &&
- ND->getParent()->getRedeclContext()->isTranslationUnit();
-}
-
bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
return false;
@@ -2352,32 +2365,31 @@
Ty = Ty->getPointeeType();
if (Ty.getCVRQualifiers() != Qualifiers::Const)
return false;
- // FIXME: Recognise nothrow_t in an inline namespace inside std?
const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
- return RD && isNamed(RD, "nothrow_t") && isNamespaceStd(RD->getDeclContext());
+ return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace();
}
FunctionDecl *
FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const {
ASTContext &Ctx = getASTContext();
if (!Ctx.getLangOpts().SizedDeallocation)
- return 0;
+ return nullptr;
if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
- return 0;
+ return nullptr;
if (getDeclName().getCXXOverloadedOperator() != OO_Delete &&
getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
- return 0;
+ return nullptr;
if (isa<CXXRecordDecl>(getDeclContext()))
- return 0;
+ return nullptr;
if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
- return 0;
+ return nullptr;
if (getNumParams() != 2 || isVariadic() ||
!Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getParamType(1),
Ctx.getSizeType()))
- return 0;
+ return nullptr;
// This is a sized deallocation function. Find the corresponding unsized
// deallocation function.
@@ -2387,7 +2399,7 @@
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI))
if (FD->getNumParams() == 1 && !FD->isVariadic())
return FD;
- return 0;
+ return nullptr;
}
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
@@ -2438,7 +2450,7 @@
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
FunctionTemplateDecl *PrevFunTmpl
- = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
+ = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr;
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
FunTmpl->setPreviousDecl(PrevFunTmpl);
}
@@ -2512,7 +2524,7 @@
void FunctionDecl::setParams(ASTContext &C,
ArrayRef<ParmVarDecl *> NewParamInfo) {
- assert(ParamInfo == 0 && "Already has param info!");
+ assert(!ParamInfo && "Already has param info!");
assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!");
// Zero params -> null pointer.
@@ -2556,7 +2568,7 @@
assert(isInlined() && "expected to get called on an inlined function!");
const ASTContext &Context = getASTContext();
- if (!Context.getLangOpts().MSVCCompat)
+ if (!Context.getLangOpts().MSVCCompat && !hasAttr<DLLExportAttr>())
return false;
for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDecl())
@@ -2738,7 +2750,7 @@
if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
return getDeclName().getCXXLiteralIdentifier();
else
- return 0;
+ return nullptr;
}
FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
@@ -2760,8 +2772,8 @@
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
return cast<FunctionDecl>(Info->getInstantiatedFrom());
-
- return 0;
+
+ return nullptr;
}
void
@@ -2791,7 +2803,7 @@
// It is possible to instantiate TSK_ExplicitSpecialization kind
// if the FunctionDecl has a class scope specialization pattern.
case TSK_ExplicitSpecialization:
- return getClassScopeSpecializationPattern() != 0;
+ return getClassScopeSpecializationPattern() != nullptr;
case TSK_ExplicitInstantiationDeclaration:
// Handled below.
@@ -2874,7 +2886,7 @@
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->Template.getPointer();
}
- return 0;
+ return nullptr;
}
FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const {
@@ -2888,7 +2900,7 @@
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->TemplateArguments;
}
- return 0;
+ return nullptr;
}
const ASTTemplateArgumentListInfo *
@@ -2898,7 +2910,7 @@
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->TemplateArgumentsAsWritten;
}
- return 0;
+ return nullptr;
}
void
@@ -3133,8 +3145,9 @@
}
FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) FieldDecl(Field, 0, SourceLocation(), SourceLocation(),
- 0, QualType(), 0, 0, false, ICIS_NoInit);
+ return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(),
+ SourceLocation(), nullptr, QualType(), nullptr,
+ nullptr, false, ICIS_NoInit);
}
bool FieldDecl::isAnonymousStructOrUnion() const {
@@ -3206,8 +3219,10 @@
void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
NamedDeclOrQualifier = TDD;
- if (TypeForDecl)
- assert(TypeForDecl->isLinkageValid());
+ if (const Type *T = getTypeForDecl()) {
+ (void)T;
+ assert(T->isLinkageValid());
+ }
assert(isLinkageValid());
}
@@ -3215,7 +3230,7 @@
IsBeingDefined = true;
if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) {
- struct CXXRecordDecl::DefinitionData *Data =
+ struct CXXRecordDecl::DefinitionData *Data =
new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
for (auto I : redecls())
cast<CXXRecordDecl>(I)->DefinitionData = Data;
@@ -3254,7 +3269,7 @@
if (R->isCompleteDefinition())
return R;
- return 0;
+ return nullptr;
}
void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
@@ -3269,7 +3284,7 @@
if (hasExtInfo()) {
if (getExtInfo()->NumTemplParamLists == 0) {
getASTContext().Deallocate(getExtInfo());
- NamedDeclOrQualifier = (TypedefNameDecl*) 0;
+ NamedDeclOrQualifier = (TypedefNameDecl*)nullptr;
}
else
getExtInfo()->QualifierLoc = QualifierLoc;
@@ -3300,7 +3315,7 @@
IdentifierInfo *Id,
EnumDecl *PrevDecl, bool IsScoped,
bool IsScopedUsingClassTag, bool IsFixed) {
- EnumDecl *Enum = new (C, DC) EnumDecl(DC, StartLoc, IdLoc, Id, PrevDecl,
+ EnumDecl *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
IsScoped, IsScopedUsingClassTag,
IsFixed);
Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
@@ -3309,8 +3324,9 @@
}
EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- EnumDecl *Enum = new (C, ID) EnumDecl(0, SourceLocation(), SourceLocation(),
- 0, 0, false, false, false);
+ EnumDecl *Enum =
+ new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
+ nullptr, nullptr, false, false, false);
Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
return Enum;
}
@@ -3356,7 +3372,7 @@
if (SpecializationInfo)
return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom());
- return 0;
+ return nullptr;
}
void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
@@ -3369,10 +3385,11 @@
// RecordDecl Implementation
//===----------------------------------------------------------------------===//
-RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
- SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, RecordDecl *PrevDecl)
- : TagDecl(DK, TK, DC, IdLoc, Id, PrevDecl, StartLoc) {
+RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
+ DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ RecordDecl *PrevDecl)
+ : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
HasFlexibleArrayMember = false;
AnonymousStructOrUnion = false;
HasObjectMember = false;
@@ -3384,8 +3401,8 @@
RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, RecordDecl* PrevDecl) {
- RecordDecl* R = new (C, DC) RecordDecl(Record, TK, DC, StartLoc, IdLoc, Id,
- PrevDecl);
+ RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
+ StartLoc, IdLoc, Id, PrevDecl);
R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
C.getTypeDeclType(R, PrevDecl);
@@ -3393,8 +3410,9 @@
}
RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
- RecordDecl *R = new (C, ID) RecordDecl(Record, TTK_Struct, 0, SourceLocation(),
- SourceLocation(), 0, 0);
+ RecordDecl *R =
+ new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(),
+ SourceLocation(), nullptr, nullptr);
R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
return R;
}
@@ -3466,7 +3484,7 @@
//===----------------------------------------------------------------------===//
void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
- assert(ParamInfo == 0 && "Already has param info!");
+ assert(!ParamInfo && "Already has param info!");
// Zero params -> null pointer.
if (!NewParamInfo.empty()) {
@@ -3484,7 +3502,7 @@
if (begin == end) {
NumCaptures = 0;
- Captures = 0;
+ Captures = nullptr;
return;
}
@@ -3518,25 +3536,26 @@
void TranslationUnitDecl::anchor() { }
TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
- return new (C, (DeclContext*)0) TranslationUnitDecl(C);
+ return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
}
void LabelDecl::anchor() { }
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II) {
- return new (C, DC) LabelDecl(DC, IdentL, II, 0, IdentL);
+ return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, IdentL);
}
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II,
SourceLocation GnuLabelL) {
assert(GnuLabelL != IdentL && "Use this only for GNU local labels");
- return new (C, DC) LabelDecl(DC, IdentL, II, 0, GnuLabelL);
+ return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL);
}
LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) LabelDecl(0, SourceLocation(), 0, 0, SourceLocation());
+ return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr,
+ SourceLocation());
}
void ValueDecl::anchor() { }
@@ -3555,12 +3574,13 @@
SourceLocation IdLoc,
IdentifierInfo *Id,
QualType Type) {
- return new (C, DC) ImplicitParamDecl(DC, IdLoc, Id, Type);
+ return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type);
}
ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) ImplicitParamDecl(0, SourceLocation(), 0, QualType());
+ return new (C, ID) ImplicitParamDecl(C, nullptr, SourceLocation(), nullptr,
+ QualType());
}
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
@@ -3572,15 +3592,15 @@
bool hasWrittenPrototype,
bool isConstexprSpecified) {
FunctionDecl *New =
- new (C, DC) FunctionDecl(Function, DC, StartLoc, NameInfo, T, TInfo, SC,
- isInlineSpecified, isConstexprSpecified);
+ new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo,
+ SC, isInlineSpecified, isConstexprSpecified);
New->HasWrittenPrototype = hasWrittenPrototype;
return New;
}
FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) FunctionDecl(Function, 0, SourceLocation(),
- DeclarationNameInfo(), QualType(), 0,
+ return new (C, ID) FunctionDecl(Function, C, nullptr, SourceLocation(),
+ DeclarationNameInfo(), QualType(), nullptr,
SC_None, false, false);
}
@@ -3589,7 +3609,7 @@
}
BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) BlockDecl(0, SourceLocation());
+ return new (C, ID) BlockDecl(nullptr, SourceLocation());
}
CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC,
@@ -3601,7 +3621,7 @@
CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumParams) {
return new (C, ID, NumParams * sizeof(ImplicitParamDecl *))
- CapturedDecl(0, NumParams);
+ CapturedDecl(nullptr, NumParams);
}
EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
@@ -3613,8 +3633,8 @@
EnumConstantDecl *
EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) EnumConstantDecl(0, SourceLocation(), 0, QualType(), 0,
- llvm::APSInt());
+ return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr,
+ QualType(), nullptr, llvm::APSInt());
}
void IndirectFieldDecl::anchor() { }
@@ -3628,8 +3648,9 @@
IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) IndirectFieldDecl(0, SourceLocation(), DeclarationName(),
- QualType(), 0, 0);
+ return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(),
+ DeclarationName(), QualType(), nullptr,
+ 0);
}
SourceRange EnumConstantDecl::getSourceRange() const {
@@ -3644,24 +3665,26 @@
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo) {
- return new (C, DC) TypedefDecl(DC, StartLoc, IdLoc, Id, TInfo);
+ return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}
void TypedefNameDecl::anchor() { }
TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) TypedefDecl(0, SourceLocation(), SourceLocation(), 0, 0);
+ return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(),
+ nullptr, nullptr);
}
TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
TypeSourceInfo *TInfo) {
- return new (C, DC) TypeAliasDecl(DC, StartLoc, IdLoc, Id, TInfo);
+ return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}
TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) TypeAliasDecl(0, SourceLocation(), SourceLocation(), 0, 0);
+ return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(),
+ SourceLocation(), nullptr, nullptr);
}
SourceRange TypedefDecl::getSourceRange() const {
@@ -3691,7 +3714,8 @@
FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation());
+ return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(),
+ SourceLocation());
}
void EmptyDecl::anchor() {}
@@ -3701,7 +3725,7 @@
}
EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) EmptyDecl(0, SourceLocation());
+ return new (C, ID) EmptyDecl(nullptr, SourceLocation());
}
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 1de1fe2..2b1506d 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -164,7 +164,7 @@
return FD;
if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(this))
return FTD->getTemplatedDecl();
- return 0;
+ return nullptr;
}
bool Decl::isTemplateDecl() const {
@@ -178,7 +178,7 @@
if (DC->isFunctionOrMethod())
return DC;
- return 0;
+ return nullptr;
}
@@ -251,6 +251,10 @@
return false;
}
+bool Decl::isInStdNamespace() const {
+ return getDeclContext()->isStdNamespace();
+}
+
TranslationUnitDecl *Decl::getTranslationUnitDecl() {
if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this))
return TUD;
@@ -487,8 +491,8 @@
return true;
if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) {
- if (CheckAvailability(getASTContext(), Availability, 0)
- == AR_NotYetIntroduced)
+ if (CheckAvailability(getASTContext(), Availability,
+ nullptr) == AR_NotYetIntroduced)
return true;
}
}
@@ -709,7 +713,7 @@
else if (const TypedefNameDecl *D = dyn_cast<TypedefNameDecl>(this))
Ty = D->getUnderlyingType();
else
- return 0;
+ return nullptr;
if (Ty->isFunctionPointerType())
Ty = Ty->getAs<PointerType>()->getPointeeType();
@@ -738,7 +742,7 @@
} else if (CapturedDecl *CD = dyn_cast<CapturedDecl>(D)) {
return getNonClosureContext(CD->getParent());
} else {
- return 0;
+ return nullptr;
}
}
@@ -795,6 +799,22 @@
cast<NamespaceDecl>(this)->isInline();
}
+bool DeclContext::isStdNamespace() const {
+ if (!isNamespace())
+ return false;
+
+ const NamespaceDecl *ND = cast<NamespaceDecl>(this);
+ if (ND->isInline()) {
+ return ND->getParent()->isStdNamespace();
+ }
+
+ if (!getParent()->getRedeclContext()->isTranslationUnit())
+ return false;
+
+ const IdentifierInfo *II = ND->getIdentifier();
+ return II && II->isStr("std");
+}
+
bool DeclContext::isDependentContext() const {
if (isFileContext())
return false;
@@ -837,7 +857,7 @@
while (DC->getDeclKind() != Decl::TranslationUnit) {
if (DC->getDeclKind() == Decl::LinkageSpec)
return cast<LinkageSpecDecl>(DC)->getLanguage() == ID;
- DC = DC->getParent();
+ DC = DC->getLexicalParent();
}
return false;
}
@@ -900,18 +920,17 @@
// If this is a tag type that has a definition or is currently
// being defined, that definition is our primary context.
TagDecl *Tag = cast<TagDecl>(this);
- assert(isa<TagType>(Tag->TypeForDecl) ||
- isa<InjectedClassNameType>(Tag->TypeForDecl));
if (TagDecl *Def = Tag->getDefinition())
return Def;
- if (!isa<InjectedClassNameType>(Tag->TypeForDecl)) {
- const TagType *TagTy = cast<TagType>(Tag->TypeForDecl);
- if (TagTy->isBeingDefined())
- // FIXME: is it necessarily being defined in the decl
- // that owns the type?
- return TagTy->getDecl();
+ if (const TagType *TagTy = dyn_cast<TagType>(Tag->getTypeForDecl())) {
+ // Note, TagType::getDecl returns the (partial) definition one exists.
+ TagDecl *PossiblePartialDef = TagTy->getDecl();
+ if (PossiblePartialDef->isBeingDefined())
+ return PossiblePartialDef;
+ } else {
+ assert(isa<InjectedClassNameType>(Tag->getTypeForDecl()));
}
return Tag;
@@ -944,8 +963,8 @@
DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls,
bool FieldsAlreadyLoaded) {
// Build up a chain of declarations via the Decl::NextInContextAndBits field.
- Decl *FirstNewDecl = 0;
- Decl *PrevDecl = 0;
+ Decl *FirstNewDecl = nullptr;
+ Decl *PrevDecl = nullptr;
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
if (FieldsAlreadyLoaded && isa<FieldDecl>(Decls[I]))
continue;
@@ -1106,7 +1125,7 @@
// Remove D from the decl chain. This is O(n) but hopefully rare.
if (D == FirstDecl) {
if (D == LastDecl)
- FirstDecl = LastDecl = 0;
+ FirstDecl = LastDecl = nullptr;
else
FirstDecl = D->NextInContextAndBits.getPointer();
} else {
@@ -1121,7 +1140,7 @@
}
// Mark that D is no longer in the decl chain.
- D->NextInContextAndBits.setPointer(0);
+ D->NextInContextAndBits.setPointer(nullptr);
// Remove D from the lookup table if necessary.
if (isa<NamedDecl>(D)) {
@@ -1304,7 +1323,7 @@
}
}
- return lookup_result(lookup_iterator(0), lookup_iterator(0));
+ return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
}
StoredDeclsMap *Map = LookupPtr.getPointer();
@@ -1312,11 +1331,11 @@
Map = buildLookup();
if (!Map)
- return lookup_result(lookup_iterator(0), lookup_iterator(0));
+ return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
StoredDeclsMap::iterator I = Map->find(Name);
if (I == Map->end())
- return lookup_result(lookup_iterator(0), lookup_iterator(0));
+ return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
return I->second.getLookupResult();
}
@@ -1353,12 +1372,12 @@
}
if (!Map)
- return lookup_result(lookup_iterator(0), lookup_iterator(0));
+ return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
StoredDeclsMap::iterator I = Map->find(Name);
- return I != Map->end()
- ? I->second.getLookupResult()
- : lookup_result(lookup_iterator(0), lookup_iterator(0));
+ return I != Map->end() ? I->second.getLookupResult()
+ : lookup_result(lookup_iterator(nullptr),
+ lookup_iterator(nullptr));
}
void DeclContext::localUncachedLookup(DeclarationName Name,
@@ -1597,7 +1616,7 @@
// Allocate the copy of the PartialDiagnostic via the ASTContext's
// BumpPtrAllocator, rather than the ASTContext itself.
- PartialDiagnostic::Storage *DiagStorage = 0;
+ PartialDiagnostic::Storage *DiagStorage = nullptr;
if (PDiag.hasStorage())
DiagStorage = new (C) PartialDiagnostic::Storage;
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index d0ec4b9..0ac8b73 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -82,19 +82,21 @@
return VBases.get(Definition->getASTContext().getExternalSource());
}
-CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
- SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, CXXRecordDecl *PrevDecl)
- : RecordDecl(K, TK, DC, StartLoc, IdLoc, Id, PrevDecl),
- DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0),
- TemplateOrInstantiation() { }
+CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
+ DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl)
+ : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl),
+ DefinitionData(PrevDecl ? PrevDecl->DefinitionData
+ : DefinitionDataPtr(this)),
+ TemplateOrInstantiation() {}
CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
CXXRecordDecl* PrevDecl,
bool DelayTypeCreation) {
- CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, DC, StartLoc,
+ CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc,
IdLoc, Id, PrevDecl);
R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
@@ -104,27 +106,29 @@
return R;
}
-CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
- TypeSourceInfo *Info, SourceLocation Loc,
- bool Dependent, bool IsGeneric,
- LambdaCaptureDefault CaptureDefault) {
+CXXRecordDecl *
+CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
+ TypeSourceInfo *Info, SourceLocation Loc,
+ bool Dependent, bool IsGeneric,
+ LambdaCaptureDefault CaptureDefault) {
CXXRecordDecl *R =
- new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, 0, 0);
+ new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
+ nullptr, nullptr);
R->IsBeingDefined = true;
- R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info,
- Dependent,
- IsGeneric,
- CaptureDefault);
+ R->DefinitionData =
+ new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
+ CaptureDefault);
R->MayHaveOutOfDateDef = false;
R->setImplicit(true);
- C.getTypeDeclType(R, /*PrevDecl=*/0);
+ C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
return R;
}
CXXRecordDecl *
CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
CXXRecordDecl *R = new (C, ID) CXXRecordDecl(
- CXXRecord, TTK_Struct, 0, SourceLocation(), SourceLocation(), 0, 0);
+ CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
+ nullptr, nullptr);
R->MayHaveOutOfDateDef = false;
return R;
}
@@ -386,7 +390,7 @@
if (!isDependentContext())
return false;
- return !forallBases(SawBase, 0);
+ return !forallBases(SawBase, nullptr);
}
bool CXXRecordDecl::isTriviallyCopyable() const {
@@ -972,7 +976,7 @@
}
CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
- if (!isLambda()) return 0;
+ if (!isLambda()) return nullptr;
DeclarationName Name =
getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
DeclContext::lookup_const_result Calls = lookup(Name);
@@ -989,11 +993,11 @@
}
CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
- if (!isLambda()) return 0;
+ if (!isLambda()) return nullptr;
DeclarationName Name =
&getASTContext().Idents.get(getLambdaStaticInvokerName());
DeclContext::lookup_const_result Invoker = lookup(Name);
- if (Invoker.empty()) return 0;
+ if (Invoker.empty()) return nullptr;
assert(Invoker.size() == 1 && "More than one static invoker operator!");
NamedDecl *InvokerFun = Invoker.front();
if (FunctionTemplateDecl *InvokerTemplate =
@@ -1007,11 +1011,11 @@
llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
FieldDecl *&ThisCapture) const {
Captures.clear();
- ThisCapture = 0;
+ ThisCapture = nullptr;
LambdaDefinitionData &Lambda = getLambdaData();
RecordDecl::field_iterator Field = field_begin();
- for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures;
+ for (const LambdaCapture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures;
C != CEnd; ++C, ++Field) {
if (C->capturesThis())
ThisCapture = *Field;
@@ -1023,11 +1027,11 @@
TemplateParameterList *
CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
- if (!isLambda()) return 0;
+ if (!isLambda()) return nullptr;
CXXMethodDecl *CallOp = getLambdaCallOperator();
if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate())
return Tmpl->getTemplateParameters();
- return 0;
+ return nullptr;
}
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
@@ -1204,8 +1208,8 @@
CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom());
-
- return 0;
+
+ return nullptr;
}
void
@@ -1255,14 +1259,14 @@
DeclContext::lookup_const_result R = lookup(Name);
if (R.empty())
- return 0;
+ return nullptr;
CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(R.front());
return Dtor;
}
void CXXRecordDecl::completeDefinition() {
- completeDefinition(0);
+ completeDefinition(nullptr);
}
void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
@@ -1374,7 +1378,7 @@
if (MayBeBase && recursivelyOverrides(this, MD))
return MD;
}
- return NULL;
+ return nullptr;
}
lookup_const_result Candidates = RD->lookup(getDeclName());
@@ -1398,7 +1402,7 @@
return T;
}
- return NULL;
+ return nullptr;
}
CXXMethodDecl *
@@ -1408,13 +1412,14 @@
QualType T, TypeSourceInfo *TInfo,
StorageClass SC, bool isInline,
bool isConstexpr, SourceLocation EndLocation) {
- return new (C, RD) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo,
- SC, isInline, isConstexpr, EndLocation);
+ return new (C, RD) CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo,
+ T, TInfo, SC, isInline, isConstexpr,
+ EndLocation);
}
CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) CXXMethodDecl(CXXMethod, 0, SourceLocation(),
- DeclarationNameInfo(), QualType(), 0,
+ return new (C, ID) CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(),
+ DeclarationNameInfo(), QualType(), nullptr,
SC_None, false, false, SourceLocation());
}
@@ -1512,12 +1517,12 @@
}
CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const {
- if (isa<CXXConstructorDecl>(this)) return 0;
+ if (isa<CXXConstructorDecl>(this)) return nullptr;
return getASTContext().overridden_methods_begin(this);
}
CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const {
- if (isa<CXXConstructorDecl>(this)) return 0;
+ if (isa<CXXConstructorDecl>(this)) return nullptr;
return getASTContext().overridden_methods_end(this);
}
@@ -1647,7 +1652,7 @@
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getType().getTypePtr();
else
- return 0;
+ return nullptr;
}
SourceLocation CXXCtorInitializer::getSourceLocation() const {
@@ -1678,9 +1683,9 @@
CXXConstructorDecl *
CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) CXXConstructorDecl(0, SourceLocation(),
+ return new (C, ID) CXXConstructorDecl(C, nullptr, SourceLocation(),
DeclarationNameInfo(), QualType(),
- 0, false, false, false, false);
+ nullptr, false, false, false, false);
}
CXXConstructorDecl *
@@ -1693,7 +1698,7 @@
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
- return new (C, RD) CXXConstructorDecl(RD, StartLoc, NameInfo, T, TInfo,
+ return new (C, RD) CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo,
isExplicit, isInline,
isImplicitlyDeclared, isConstexpr);
}
@@ -1703,8 +1708,8 @@
Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(E))
return Construct->getConstructor();
-
- return 0;
+
+ return nullptr;
}
bool CXXConstructorDecl::isDefaultConstructor() const {
@@ -1740,8 +1745,8 @@
// all other parameters have default arguments.
if ((getNumParams() < 1) ||
(getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
- (getPrimaryTemplate() != 0) ||
- (getDescribedFunctionTemplate() != 0))
+ (getPrimaryTemplate() != nullptr) ||
+ (getDescribedFunctionTemplate() != nullptr))
return false;
const ParmVarDecl *Param = getParamDecl(0);
@@ -1789,8 +1794,8 @@
bool CXXConstructorDecl::isSpecializationCopyingObject() const {
if ((getNumParams() < 1) ||
(getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
- (getPrimaryTemplate() == 0) ||
- (getDescribedFunctionTemplate() != 0))
+ (getPrimaryTemplate() == nullptr) ||
+ (getDescribedFunctionTemplate() != nullptr))
return false;
const ParmVarDecl *Param = getParamDecl(0);
@@ -1811,7 +1816,7 @@
// Hack: we store the inherited constructor in the overridden method table
method_iterator It = getASTContext().overridden_methods_begin(this);
if (It == getASTContext().overridden_methods_end(this))
- return 0;
+ return nullptr;
return cast<CXXConstructorDecl>(*It);
}
@@ -1828,8 +1833,9 @@
CXXDestructorDecl *
CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) CXXDestructorDecl(
- 0, SourceLocation(), DeclarationNameInfo(), QualType(), 0, false, false);
+ return new (C, ID)
+ CXXDestructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(),
+ QualType(), nullptr, false, false);
}
CXXDestructorDecl *
@@ -1841,7 +1847,7 @@
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXDestructorName &&
"Name must refer to a destructor");
- return new (C, RD) CXXDestructorDecl(RD, StartLoc, NameInfo, T, TInfo,
+ return new (C, RD) CXXDestructorDecl(C, RD, StartLoc, NameInfo, T, TInfo,
isInline, isImplicitlyDeclared);
}
@@ -1849,9 +1855,9 @@
CXXConversionDecl *
CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) CXXConversionDecl(0, SourceLocation(),
+ return new (C, ID) CXXConversionDecl(C, nullptr, SourceLocation(),
DeclarationNameInfo(), QualType(),
- 0, false, false, false,
+ nullptr, false, false, false,
SourceLocation());
}
@@ -1865,7 +1871,7 @@
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConversionFunctionName &&
"Name must refer to a conversion function");
- return new (C, RD) CXXConversionDecl(RD, StartLoc, NameInfo, T, TInfo,
+ return new (C, RD) CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo,
isInline, isExplicit, isConstexpr,
EndLocation);
}
@@ -1888,8 +1894,8 @@
LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) LinkageSpecDecl(0, SourceLocation(), SourceLocation(),
- lang_c, false);
+ return new (C, ID) LinkageSpecDecl(nullptr, SourceLocation(),
+ SourceLocation(), lang_c, false);
}
void UsingDirectiveDecl::anchor() { }
@@ -1909,9 +1915,10 @@
UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) UsingDirectiveDecl(0, SourceLocation(), SourceLocation(),
+ return new (C, ID) UsingDirectiveDecl(nullptr, SourceLocation(),
+ SourceLocation(),
NestedNameSpecifierLoc(),
- SourceLocation(), 0, 0);
+ SourceLocation(), nullptr, nullptr);
}
NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
@@ -1921,15 +1928,14 @@
return cast_or_null<NamespaceDecl>(NominatedNamespace);
}
-NamespaceDecl::NamespaceDecl(DeclContext *DC, bool Inline,
- SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- NamespaceDecl *PrevDecl)
- : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
- LocStart(StartLoc), RBraceLoc(), AnonOrFirstNamespaceAndInline(0, Inline)
-{
+NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, NamespaceDecl *PrevDecl)
+ : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
+ redeclarable_base(C), LocStart(StartLoc), RBraceLoc(),
+ AnonOrFirstNamespaceAndInline(nullptr, Inline) {
setPreviousDecl(PrevDecl);
-
+
if (PrevDecl)
AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace());
}
@@ -1938,16 +1944,17 @@
bool Inline, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
NamespaceDecl *PrevDecl) {
- return new (C, DC) NamespaceDecl(DC, Inline, StartLoc, IdLoc, Id, PrevDecl);
+ return new (C, DC) NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id,
+ PrevDecl);
}
NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) NamespaceDecl(0, false, SourceLocation(), SourceLocation(),
- 0, 0);
+ return new (C, ID) NamespaceDecl(C, nullptr, false, SourceLocation(),
+ SourceLocation(), nullptr, nullptr);
}
-NamespaceDecl *NamespaceDecl::getNextRedeclaration() {
- return RedeclLink.getNext();
+NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() {
+ return getNextRedeclaration();
}
NamespaceDecl *NamespaceDecl::getPreviousDeclImpl() {
return getPreviousDecl();
@@ -1973,16 +1980,18 @@
NamespaceAliasDecl *
NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) NamespaceAliasDecl(0, SourceLocation(), SourceLocation(),
- 0, NestedNameSpecifierLoc(),
- SourceLocation(), 0);
+ return new (C, ID) NamespaceAliasDecl(nullptr, SourceLocation(),
+ SourceLocation(), nullptr,
+ NestedNameSpecifierLoc(),
+ SourceLocation(), nullptr);
}
void UsingShadowDecl::anchor() { }
UsingShadowDecl *
UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) UsingShadowDecl(0, SourceLocation(), 0, 0);
+ return new (C, ID) UsingShadowDecl(C, nullptr, SourceLocation(),
+ nullptr, nullptr);
}
UsingDecl *UsingShadowDecl::getUsingDecl() const {
@@ -2034,8 +2043,9 @@
}
UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) UsingDecl(0, SourceLocation(), NestedNameSpecifierLoc(),
- DeclarationNameInfo(), false);
+ return new (C, ID) UsingDecl(nullptr, SourceLocation(),
+ NestedNameSpecifierLoc(), DeclarationNameInfo(),
+ false);
}
SourceRange UsingDecl::getSourceRange() const {
@@ -2057,9 +2067,10 @@
UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) UnresolvedUsingValueDecl(0, QualType(), SourceLocation(),
+ return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(),
+ SourceLocation(),
NestedNameSpecifierLoc(),
- DeclarationNameInfo());
+ DeclarationNameInfo());
}
SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
@@ -2085,8 +2096,8 @@
UnresolvedUsingTypenameDecl *
UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) UnresolvedUsingTypenameDecl(
- 0, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(),
- SourceLocation(), 0);
+ nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(),
+ SourceLocation(), nullptr);
}
void StaticAssertDecl::anchor() { }
@@ -2103,8 +2114,8 @@
StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) StaticAssertDecl(0, SourceLocation(), 0, 0,
- SourceLocation(), false);
+ return new (C, ID) StaticAssertDecl(nullptr, SourceLocation(), nullptr,
+ nullptr, SourceLocation(), false);
}
MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
@@ -2118,8 +2129,9 @@
MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) MSPropertyDecl(0, SourceLocation(), DeclarationName(),
- QualType(), 0, SourceLocation(), 0, 0);
+ return new (C, ID) MSPropertyDecl(nullptr, SourceLocation(),
+ DeclarationName(), QualType(), nullptr,
+ SourceLocation(), nullptr, nullptr);
}
static const char *getAccessName(AccessSpecifier AS) {
diff --git a/lib/AST/DeclFriend.cpp b/lib/AST/DeclFriend.cpp
index 02374c7..a996cab 100644
--- a/lib/AST/DeclFriend.cpp
+++ b/lib/AST/DeclFriend.cpp
@@ -62,5 +62,5 @@
FriendDecl *CXXRecordDecl::getFirstFriend() const {
ExternalASTSource *Source = getParentASTContext().getExternalSource();
Decl *First = data().FirstFriend.get(Source);
- return First ? cast<FriendDecl>(First) : 0;
+ return First ? cast<FriendDecl>(First) : nullptr;
}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index c53dba3..186a741 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -25,7 +25,7 @@
//===----------------------------------------------------------------------===//
void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
- List = 0;
+ List = nullptr;
if (Elts == 0) return; // Setting to an empty list is a noop.
@@ -60,7 +60,7 @@
if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
return ivar;
}
- return 0;
+ return nullptr;
}
// Get the local instance/class method declared in this interface.
@@ -72,7 +72,7 @@
if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
if (Def->isHidden() && !AllowHidden)
- return 0;
+ return nullptr;
}
// Since instance & class methods can have the same name, the loop below
@@ -90,7 +90,7 @@
if (MD && MD->isInstanceMethod() == isInstance)
return MD;
}
- return 0;
+ return nullptr;
}
/// HasUserDeclaredSetterMethod - This routine returns 'true' if a user declared setter
@@ -157,7 +157,7 @@
if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
if (Def->isHidden())
- return 0;
+ return nullptr;
}
DeclContext::lookup_const_result R = DC->lookup(propertyID);
@@ -166,7 +166,7 @@
if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I))
return PD;
- return 0;
+ return nullptr;
}
IdentifierInfo *
@@ -187,7 +187,7 @@
if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
if (Def->isHidden())
- return 0;
+ return nullptr;
}
if (ObjCPropertyDecl *PD =
@@ -233,7 +233,7 @@
break;
}
}
- return 0;
+ return nullptr;
}
void ObjCInterfaceDecl::anchor() { }
@@ -247,8 +247,8 @@
IdentifierInfo *PropertyId) const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
-
+ return nullptr;
+
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -261,7 +261,7 @@
if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId))
return P;
- return 0;
+ return nullptr;
}
void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM,
@@ -294,7 +294,7 @@
return Class;
Class = Class->getSuperClass();
}
- return 0;
+ return nullptr;
}
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
@@ -350,7 +350,7 @@
break;
IFace = IFace->getSuperClass();
}
- return 0;
+ return nullptr;
}
static bool isIntroducingInitializers(const ObjCInterfaceDecl *D) {
@@ -364,6 +364,12 @@
return true;
}
}
+ if (const auto *ImplD = D->getImplementation()) {
+ for (const auto *MD : ImplD->instance_methods()) {
+ if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
+ return true;
+ }
+ }
return false;
}
@@ -379,11 +385,21 @@
// misleading warnings.
if (isIntroducingInitializers(this)) {
data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
- return false;
} else {
- data().InheritedDesignatedInitializers = DefinitionData::IDI_Inherited;
- return true;
+ if (auto SuperD = getSuperClass()) {
+ data().InheritedDesignatedInitializers =
+ SuperD->declaresOrInheritsDesignatedInitializers() ?
+ DefinitionData::IDI_Inherited :
+ DefinitionData::IDI_NotInherited;
+ } else {
+ data().InheritedDesignatedInitializers =
+ DefinitionData::IDI_NotInherited;
+ }
}
+ assert(data().InheritedDesignatedInitializers
+ != DefinitionData::IDI_Unknown);
+ return data().InheritedDesignatedInitializers ==
+ DefinitionData::IDI_Inherited;
}
}
@@ -467,13 +483,13 @@
ObjCInterfaceDecl *&clsDeclared) {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
+ return nullptr;
if (data().ExternallyCompleted)
LoadExternalDefinition();
ObjCInterfaceDecl* ClassDecl = this;
- while (ClassDecl != NULL) {
+ while (ClassDecl != nullptr) {
if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
clsDeclared = ClassDecl;
return I;
@@ -488,7 +504,7 @@
ClassDecl = ClassDecl->getSuperClass();
}
- return NULL;
+ return nullptr;
}
/// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super
@@ -498,18 +514,18 @@
const IdentifierInfo*ICName) {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
+ return nullptr;
if (data().ExternallyCompleted)
LoadExternalDefinition();
ObjCInterfaceDecl* ClassDecl = this;
- while (ClassDecl != NULL) {
+ while (ClassDecl != nullptr) {
if (ClassDecl->getIdentifier() == ICName)
return ClassDecl;
ClassDecl = ClassDecl->getSuperClass();
}
- return NULL;
+ return nullptr;
}
ObjCProtocolDecl *
@@ -518,7 +534,7 @@
if (P->lookupProtocolNamed(Name))
return P;
ObjCInterfaceDecl *SuperClass = getSuperClass();
- return SuperClass ? SuperClass->lookupNestedProtocol(Name) : NULL;
+ return SuperClass ? SuperClass->lookupNestedProtocol(Name) : nullptr;
}
/// lookupMethod - This method returns an instance/class method by looking in
@@ -533,10 +549,10 @@
{
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
+ return nullptr;
const ObjCInterfaceDecl* ClassDecl = this;
- ObjCMethodDecl *MethodDecl = 0;
+ ObjCMethodDecl *MethodDecl = nullptr;
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -569,12 +585,12 @@
}
if (!followSuper)
- return NULL;
+ return nullptr;
// Get the super class (if any).
ClassDecl = ClassDecl->getSuperClass();
}
- return NULL;
+ return nullptr;
}
// Will search "local" class/category implementations for a method decl.
@@ -585,12 +601,12 @@
bool Instance) const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
+ return nullptr;
if (data().ExternallyCompleted)
LoadExternalDefinition();
- ObjCMethodDecl *Method = 0;
+ ObjCMethodDecl *Method = nullptr;
if (ObjCImplementationDecl *ImpDecl = getImplementation())
Method = Instance ? ImpDecl->getInstanceMethod(Sel)
: ImpDecl->getClassMethod(Sel);
@@ -634,7 +650,7 @@
ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(),
- Selector(), QualType(), 0, 0);
+ Selector(), QualType(), nullptr, nullptr);
}
bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
@@ -668,7 +684,7 @@
void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
ArrayRef<ParmVarDecl*> Params,
ArrayRef<SourceLocation> SelLocs) {
- ParamsAndSelLocs = 0;
+ ParamsAndSelLocs = nullptr;
NumParams = Params.size();
if (Params.empty() && SelLocs.empty())
return;
@@ -705,9 +721,9 @@
/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
-ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
+ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
ASTContext &Ctx = getASTContext();
- ObjCMethodDecl *Redecl = 0;
+ ObjCMethodDecl *Redecl = nullptr;
if (HasRedeclaration)
Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this));
if (Redecl)
@@ -932,7 +948,7 @@
if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
return IMD->getClassInterface();
if (isa<ObjCProtocolDecl>(getDeclContext()))
- return 0;
+ return nullptr;
llvm_unreachable("unknown method context");
}
@@ -1067,11 +1083,11 @@
Selector Sel = getSelector();
unsigned NumArgs = Sel.getNumArgs();
if (NumArgs > 1)
- return 0;
+ return nullptr;
if (!isInstanceMethod() || getMethodFamily() != OMF_None)
- return 0;
-
+ return nullptr;
+
if (isPropertyAccessor()) {
const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());
// If container is class extension, find its primary class.
@@ -1092,7 +1108,7 @@
}
if (!CheckOverrides)
- return 0;
+ return nullptr;
typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy;
OverridesTy Overrides;
@@ -1103,8 +1119,7 @@
return Prop;
}
- return 0;
-
+ return nullptr;
}
//===----------------------------------------------------------------------===//
@@ -1119,35 +1134,37 @@
SourceLocation ClassLoc,
bool isInternal){
ObjCInterfaceDecl *Result = new (C, DC)
- ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, PrevDecl, isInternal);
+ ObjCInterfaceDecl(C, DC, atLoc, Id, ClassLoc, PrevDecl, isInternal);
Result->Data.setInt(!C.getLangOpts().Modules);
C.getObjCInterfaceType(Result, PrevDecl);
return Result;
}
-ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(ASTContext &C,
+ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
unsigned ID) {
- ObjCInterfaceDecl *Result = new (C, ID) ObjCInterfaceDecl(0, SourceLocation(),
- 0, SourceLocation(),
- 0, false);
+ ObjCInterfaceDecl *Result = new (C, ID) ObjCInterfaceDecl(C, nullptr,
+ SourceLocation(),
+ nullptr,
+ SourceLocation(),
+ nullptr, false);
Result->Data.setInt(!C.getLangOpts().Modules);
return Result;
}
-ObjCInterfaceDecl::
-ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
- SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
- bool isInternal)
- : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
- TypeForDecl(0), Data()
-{
+ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
+ SourceLocation AtLoc, IdentifierInfo *Id,
+ SourceLocation CLoc,
+ ObjCInterfaceDecl *PrevDecl,
+ bool IsInternal)
+ : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
+ redeclarable_base(C), TypeForDecl(nullptr), Data() {
setPreviousDecl(PrevDecl);
// Copy the 'data' pointer over.
if (PrevDecl)
Data = PrevDecl->Data;
- setImplicit(isInternal);
+ setImplicit(IsInternal);
}
void ObjCInterfaceDecl::LoadExternalDefinition() const {
@@ -1192,7 +1209,7 @@
}
// FIXME: Should make sure no callers ever do this.
- return 0;
+ return nullptr;
}
void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
@@ -1225,9 +1242,9 @@
ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
-
- ObjCIvarDecl *curIvar = 0;
+ return nullptr;
+
+ ObjCIvarDecl *curIvar = nullptr;
if (!data().IvarList) {
if (!ivar_empty()) {
ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
@@ -1297,7 +1314,7 @@
ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
+ return nullptr;
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -1305,8 +1322,8 @@
for (auto *Cat : visible_categories())
if (Cat->getIdentifier() == CategoryId)
return Cat;
-
- return 0;
+
+ return nullptr;
}
ObjCMethodDecl *
@@ -1317,7 +1334,7 @@
return MD;
}
- return 0;
+ return nullptr;
}
ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
@@ -1326,8 +1343,8 @@
if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel))
return MD;
}
-
- return 0;
+
+ return nullptr;
}
/// ClassImplementsProtocol - Checks that 'lProto' protocol
@@ -1407,7 +1424,7 @@
else
ID = cast<ObjCCategoryDecl>(DC)->getClassInterface();
}
- ID->setIvarList(0);
+ ID->setIvarList(nullptr);
}
return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW,
@@ -1415,8 +1432,9 @@
}
ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) ObjCIvarDecl(0, SourceLocation(), SourceLocation(), 0,
- QualType(), 0, ObjCIvarDecl::None, 0, false);
+ return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(),
+ nullptr, QualType(), nullptr,
+ ObjCIvarDecl::None, nullptr, false);
}
const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
@@ -1458,8 +1476,9 @@
ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) ObjCAtDefsFieldDecl(0, SourceLocation(), SourceLocation(),
- 0, QualType(), 0);
+ return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(),
+ SourceLocation(), nullptr, QualType(),
+ nullptr);
}
//===----------------------------------------------------------------------===//
@@ -1468,12 +1487,12 @@
void ObjCProtocolDecl::anchor() { }
-ObjCProtocolDecl::ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id,
- SourceLocation nameLoc,
+ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC,
+ IdentifierInfo *Id, SourceLocation nameLoc,
SourceLocation atStartLoc,
ObjCProtocolDecl *PrevDecl)
- : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), Data()
-{
+ : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc),
+ redeclarable_base(C), Data() {
setPreviousDecl(PrevDecl);
if (PrevDecl)
Data = PrevDecl->Data;
@@ -1485,7 +1504,7 @@
SourceLocation atStartLoc,
ObjCProtocolDecl *PrevDecl) {
ObjCProtocolDecl *Result =
- new (C, DC) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc, PrevDecl);
+ new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl);
Result->Data.setInt(!C.getLangOpts().Modules);
return Result;
}
@@ -1493,7 +1512,8 @@
ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
ObjCProtocolDecl *Result =
- new (C, ID) ObjCProtocolDecl(0, 0, SourceLocation(), SourceLocation(), 0);
+ new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(),
+ SourceLocation(), nullptr);
Result->Data.setInt(!C.getLangOpts().Modules);
return Result;
}
@@ -1508,20 +1528,20 @@
if ((PDecl = I->lookupProtocolNamed(Name)))
return PDecl;
- return NULL;
+ return nullptr;
}
// lookupMethod - Lookup a instance/class method in the protocol and protocols
// it inherited.
ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
bool isInstance) const {
- ObjCMethodDecl *MethodDecl = NULL;
+ ObjCMethodDecl *MethodDecl = nullptr;
// If there is no definition or the definition is hidden, we don't find
// anything.
const ObjCProtocolDecl *Def = getDefinition();
if (!Def || Def->isHidden())
- return NULL;
+ return nullptr;
if ((MethodDecl = getMethod(Sel, isInstance)))
return MethodDecl;
@@ -1529,7 +1549,7 @@
for (const auto *I : protocols())
if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
return MethodDecl;
- return NULL;
+ return nullptr;
}
void ObjCProtocolDecl::allocateDefinitionData() {
@@ -1615,8 +1635,9 @@
ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(),
- SourceLocation(), 0, 0);
+ return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ nullptr, nullptr);
}
ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
@@ -1650,15 +1671,16 @@
ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) ObjCCategoryImplDecl(0, 0, 0, SourceLocation(),
- SourceLocation(), SourceLocation());
+ return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr,
+ SourceLocation(), SourceLocation(),
+ SourceLocation());
}
ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
// The class interface might be NULL if we are working with invalid code.
if (const ObjCInterfaceDecl *ID = getClassInterface())
return ID->FindCategoryDeclaration(getIdentifier());
- return 0;
+ return nullptr;
}
@@ -1697,7 +1719,7 @@
if (PID->getPropertyIvarDecl() &&
PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
return PID;
- return 0;
+ return nullptr;
}
/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
@@ -1709,7 +1731,7 @@
for (auto *PID : property_impls())
if (PID->getPropertyDecl()->getIdentifier() == Id)
return PID;
- return 0;
+ return nullptr;
}
raw_ostream &clang::operator<<(raw_ostream &OS,
@@ -1742,8 +1764,8 @@
ObjCImplementationDecl *
ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) ObjCImplementationDecl(0, 0, 0, SourceLocation(),
- SourceLocation());
+ return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr,
+ SourceLocation(), SourceLocation());
}
void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
@@ -1781,7 +1803,8 @@
ObjCCompatibleAliasDecl *
ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) ObjCCompatibleAliasDecl(0, SourceLocation(), 0, 0);
+ return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(),
+ nullptr, nullptr);
}
//===----------------------------------------------------------------------===//
@@ -1802,8 +1825,9 @@
ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) ObjCPropertyDecl(0, SourceLocation(), 0, SourceLocation(),
- SourceLocation(), 0);
+ return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr,
+ SourceLocation(), SourceLocation(),
+ nullptr);
}
//===----------------------------------------------------------------------===//
@@ -1824,8 +1848,9 @@
ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) ObjCPropertyImplDecl(0, SourceLocation(), SourceLocation(),
- 0, Dynamic, 0, SourceLocation());
+ return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(),
+ SourceLocation(), nullptr, Dynamic,
+ nullptr, SourceLocation());
}
SourceRange ObjCPropertyImplDecl::getSourceRange() const {
diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp
index 37d4ae2..5f8b42b 100644
--- a/lib/AST/DeclOpenMP.cpp
+++ b/lib/AST/DeclOpenMP.cpp
@@ -40,7 +40,7 @@
unsigned ID,
unsigned N) {
OMPThreadPrivateDecl *D = new (C, ID, N * sizeof(Expr *))
- OMPThreadPrivateDecl(OMPThreadPrivate, 0, SourceLocation());
+ OMPThreadPrivateDecl(OMPThreadPrivate, nullptr, SourceLocation());
D->NumVars = N;
return D;
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index a57532c..558654d 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -85,7 +85,7 @@
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
void PrintTemplateParameters(const TemplateParameterList *Params,
- const TemplateArgumentList *Args = 0);
+ const TemplateArgumentList *Args = nullptr);
void prettyPrintAttributes(Decl *D);
};
}
@@ -282,21 +282,21 @@
Visit(*D);
// FIXME: Need to be able to tell the DeclPrinter when
- const char *Terminator = 0;
+ const char *Terminator = nullptr;
if (isa<OMPThreadPrivateDecl>(*D))
- Terminator = 0;
+ Terminator = nullptr;
else if (isa<FunctionDecl>(*D) &&
cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
- Terminator = 0;
+ Terminator = nullptr;
else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
- Terminator = 0;
+ Terminator = nullptr;
else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
isa<ObjCImplementationDecl>(*D) ||
isa<ObjCInterfaceDecl>(*D) ||
isa<ObjCProtocolDecl>(*D) ||
isa<ObjCCategoryImplDecl>(*D) ||
isa<ObjCCategoryDecl>(*D))
- Terminator = 0;
+ Terminator = nullptr;
else if (isa<EnumConstantDecl>(*D)) {
DeclContext::decl_iterator Next = D;
++Next;
@@ -379,7 +379,7 @@
Out << *D;
if (Expr *Init = D->getInitExpr()) {
Out << " = ";
- Init->printPretty(Out, 0, Policy, Indentation);
+ Init->printPretty(Out, nullptr, Policy, Indentation);
}
}
@@ -416,7 +416,7 @@
}
if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
- const FunctionProtoType *FT = 0;
+ const FunctionProtoType *FT = nullptr;
if (D->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(AFT);
@@ -480,7 +480,7 @@
if (FT->getExceptionSpecType() == EST_ComputedNoexcept) {
Proto += "(";
llvm::raw_string_ostream EOut(Proto);
- FT->getNoexceptExpr()->printPretty(EOut, 0, SubPolicy,
+ FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
Indentation);
EOut.flush();
Proto += EOut.str();
@@ -518,9 +518,9 @@
Init = Tmp->getSubExpr();
Init = Init->IgnoreParens();
-
- Expr *SimpleInit = 0;
- Expr **Args = 0;
+
+ Expr *SimpleInit = nullptr;
+ Expr **Args = nullptr;
unsigned NumArgs = 0;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
Args = ParenList->getExprs();
@@ -533,7 +533,7 @@
SimpleInit = Init;
if (SimpleInit)
- SimpleInit->printPretty(Out, 0, Policy, Indentation);
+ SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
else {
for (unsigned I = 0; I != NumArgs; ++I) {
if (isa<CXXDefaultArgExpr>(Args[I]))
@@ -541,7 +541,7 @@
if (I)
Out << ", ";
- Args[I]->printPretty(Out, 0, Policy, Indentation);
+ Args[I]->printPretty(Out, nullptr, Policy, Indentation);
}
}
}
@@ -586,7 +586,7 @@
} else
Out << ' ';
- D->getBody()->printPretty(Out, 0, SubPolicy, Indentation);
+ D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
Out << '\n';
}
}
@@ -627,7 +627,7 @@
if (D->isBitField()) {
Out << " : ";
- D->getBitWidth()->printPretty(Out, 0, Policy, Indentation);
+ D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation);
}
Expr *Init = D->getInClassInitializer();
@@ -636,7 +636,7 @@
Out << " ";
else
Out << " = ";
- Init->printPretty(Out, 0, Policy, Indentation);
+ Init->printPretty(Out, nullptr, Policy, Indentation);
}
prettyPrintAttributes(D);
}
@@ -691,7 +691,7 @@
else if (D->getInitStyle() == VarDecl::CInit) {
Out << " = ";
}
- Init->printPretty(Out, 0, Policy, Indentation);
+ Init->printPretty(Out, nullptr, Policy, Indentation);
if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
Out << ")";
}
@@ -705,7 +705,7 @@
void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
Out << "__asm (";
- D->getAsmString()->printPretty(Out, 0, Policy, Indentation);
+ D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation);
Out << ")";
}
@@ -716,9 +716,9 @@
void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
Out << "static_assert(";
- D->getAssertExpr()->printPretty(Out, 0, Policy, Indentation);
+ D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation);
Out << ", ";
- D->getMessage()->printPretty(Out, 0, Policy, Indentation);
+ D->getMessage()->printPretty(Out, nullptr, Policy, Indentation);
Out << ")";
}
@@ -856,7 +856,8 @@
Args->get(i).print(Policy, Out);
} else if (NTTP->hasDefaultArgument()) {
Out << " = ";
- NTTP->getDefaultArgument()->printPretty(Out, 0, Policy, Indentation);
+ NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
+ Indentation);
}
} else if (const TemplateTemplateParmDecl *TTPD =
dyn_cast<TemplateTemplateParmDecl>(Param)) {
@@ -940,7 +941,7 @@
if (OMD->getBody() && !Policy.TerseOutput) {
Out << ' ';
- OMD->getBody()->printPretty(Out, 0, Policy);
+ OMD->getBody()->printPretty(Out, nullptr, Policy);
Out << '\n';
}
else if (Policy.PolishForDeclaration)
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index fc73e6f..a69146b 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -170,7 +170,7 @@
llvm::FoldingSetNodeID ID;
EntryType::Profile(ID,Args,NumArgs, getASTContext());
EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
- return Entry ? SETraits::getMostRecentDecl(Entry) : 0;
+ return Entry ? SETraits::getMostRecentDecl(Entry) : nullptr;
}
/// \brief Generate the injected template arguments for the given template
@@ -229,13 +229,13 @@
TemplateParameterList *Params,
NamedDecl *Decl) {
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
- return new (C, DC) FunctionTemplateDecl(DC, L, Name, Params, Decl);
+ return new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
}
FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(),
- 0, 0);
+ return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(),
+ DeclarationName(), nullptr, nullptr);
}
RedeclarableTemplateDecl::CommonBase *
@@ -250,7 +250,7 @@
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
- CommonPtr->LazySpecializations = 0;
+ CommonPtr->LazySpecializations = nullptr;
for (uint32_t I = 0, N = *Specs++; I != N; ++I)
(void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
}
@@ -307,15 +307,16 @@
NamedDecl *Decl,
ClassTemplateDecl *PrevDecl) {
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
- ClassTemplateDecl *New =
- new (C, DC) ClassTemplateDecl(DC, L, Name, Params, Decl);
+ ClassTemplateDecl *New = new (C, DC) ClassTemplateDecl(C, DC, L, Name,
+ Params, Decl);
New->setPreviousDecl(PrevDecl);
return New;
}
-ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
+ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) ClassTemplateDecl(EmptyShell());
+ return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
+ DeclarationName(), nullptr, nullptr);
}
void ClassTemplateDecl::LoadLazySpecializations() const {
@@ -323,7 +324,7 @@
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
- CommonPtr->LazySpecializations = 0;
+ CommonPtr->LazySpecializations = nullptr;
for (uint32_t I = 0, N = *Specs++; I != N; ++I)
(void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
}
@@ -417,7 +418,7 @@
return P->getMostRecentDecl();
}
- return 0;
+ return nullptr;
}
ClassTemplatePartialSpecializationDecl *
@@ -432,7 +433,7 @@
return P->getMostRecentDecl();
}
- return 0;
+ return nullptr;
}
QualType
@@ -472,14 +473,14 @@
TemplateTypeParmDecl *TTPDecl =
new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);
- TTPDecl->TypeForDecl = TTPType.getTypePtr();
+ TTPDecl->setTypeForDecl(TTPType.getTypePtr());
return TTPDecl;
}
TemplateTypeParmDecl *
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
- return new (C, ID) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(),
- 0, false);
+ return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(),
+ SourceLocation(), nullptr, false);
}
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
@@ -497,15 +498,15 @@
}
unsigned TemplateTypeParmDecl::getDepth() const {
- return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth();
+ return getTypeForDecl()->getAs<TemplateTypeParmType>()->getDepth();
}
unsigned TemplateTypeParmDecl::getIndex() const {
- return TypeForDecl->getAs<TemplateTypeParmType>()->getIndex();
+ return getTypeForDecl()->getAs<TemplateTypeParmType>()->getIndex();
}
bool TemplateTypeParmDecl::isParameterPack() const {
- return TypeForDecl->getAs<TemplateTypeParmType>()->isParameterPack();
+ return getTypeForDecl()->getAs<TemplateTypeParmType>()->isParameterPack();
}
//===----------------------------------------------------------------------===//
@@ -523,7 +524,7 @@
unsigned NumExpandedTypes,
TypeSourceInfo **ExpandedTInfos)
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
- TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
+ TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false),
ParameterPack(true), ExpandedParameterPack(true),
NumExpandedTypes(NumExpandedTypes)
{
@@ -563,9 +564,9 @@
NonTypeTemplateParmDecl *
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) NonTypeTemplateParmDecl(0, SourceLocation(),
- SourceLocation(), 0, 0, 0,
- QualType(), false, 0);
+ return new (C, ID) NonTypeTemplateParmDecl(nullptr, SourceLocation(),
+ SourceLocation(), 0, 0, nullptr,
+ QualType(), false, nullptr);
}
NonTypeTemplateParmDecl *
@@ -573,8 +574,8 @@
unsigned NumExpandedTypes) {
unsigned Extra = NumExpandedTypes * 2 * sizeof(void*);
return new (C, ID, Extra) NonTypeTemplateParmDecl(
- 0, SourceLocation(), SourceLocation(), 0, 0, 0, QualType(), 0,
- 0, NumExpandedTypes, 0);
+ nullptr, SourceLocation(), SourceLocation(), 0, 0, nullptr, QualType(),
+ nullptr, nullptr, NumExpandedTypes, nullptr);
}
SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
@@ -631,16 +632,16 @@
TemplateTemplateParmDecl *
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, false,
- 0, 0);
+ return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
+ false, nullptr, nullptr);
}
TemplateTemplateParmDecl *
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumExpansions) {
return new (C, ID, sizeof(TemplateParameterList*) * NumExpansions)
- TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, 0, 0,
- NumExpansions, 0);
+ TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
+ nullptr, NumExpansions, nullptr);
}
//===----------------------------------------------------------------------===//
@@ -667,7 +668,7 @@
const TemplateArgumentList *TemplateArgs,
const TemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation POI) {
- const ASTTemplateArgumentListInfo *ArgsAsWritten = 0;
+ const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
if (TemplateArgsAsWritten)
ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
*TemplateArgsAsWritten);
@@ -695,20 +696,20 @@
const TemplateArgument *Args,
unsigned NumArgs,
ClassTemplateSpecializationDecl *PrevDecl)
- : CXXRecordDecl(DK, TK, DC, StartLoc, IdLoc,
+ : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
SpecializedTemplate->getIdentifier(),
PrevDecl),
SpecializedTemplate(SpecializedTemplate),
- ExplicitInfo(0),
+ ExplicitInfo(nullptr),
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)),
SpecializationKind(TSK_Undeclared) {
}
-ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(Kind DK)
- : CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), SourceLocation(), 0, 0),
- ExplicitInfo(0),
- SpecializationKind(TSK_Undeclared) {
-}
+ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
+ Kind DK)
+ : CXXRecordDecl(DK, TTK_Struct, C, nullptr, SourceLocation(),
+ SourceLocation(), nullptr, nullptr),
+ ExplicitInfo(nullptr), SpecializationKind(TSK_Undeclared) {}
ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
@@ -733,7 +734,7 @@
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
ClassTemplateSpecializationDecl *Result =
- new (C, ID) ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
+ new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
Result->MayHaveOutOfDateDef = false;
return Result;
}
@@ -777,7 +778,7 @@
typedef ClassTemplatePartialSpecializationDecl CTPSDecl;
CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this));
CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
- assert(inst_from != 0);
+ assert(inst_from != nullptr);
return inst_from->getSourceRange();
}
else {
@@ -816,7 +817,7 @@
SpecializedTemplate,
Args, NumArgs, PrevDecl),
TemplateParams(Params), ArgsAsWritten(ArgInfos),
- InstantiatedFromMember(0, false)
+ InstantiatedFromMember(nullptr, false)
{
AdoptTemplateParameterList(Params, this);
}
@@ -850,7 +851,7 @@
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
ClassTemplatePartialSpecializationDecl *Result =
- new (C, ID) ClassTemplatePartialSpecializationDecl();
+ new (C, ID) ClassTemplatePartialSpecializationDecl(C);
Result->MayHaveOutOfDateDef = false;
return Result;
}
@@ -888,13 +889,13 @@
TemplateParameterList *Params,
NamedDecl *Decl) {
AdoptTemplateParameterList(Params, DC);
- return new (C, DC) TypeAliasTemplateDecl(DC, L, Name, Params, Decl);
+ return new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
}
TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(),
- 0, 0);
+ return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(),
+ DeclarationName(), nullptr, nullptr);
}
void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) {
@@ -917,7 +918,7 @@
ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) ClassScopeFunctionSpecializationDecl(
- 0, SourceLocation(), 0, false, TemplateArgumentListInfo());
+ nullptr, SourceLocation(), nullptr, false, TemplateArgumentListInfo());
}
//===----------------------------------------------------------------------===//
@@ -935,19 +936,20 @@
return CurD;
CurD = CurD->getPreviousDecl();
}
- return 0;
+ return nullptr;
}
VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
TemplateParameterList *Params,
VarDecl *Decl) {
- return new (C, DC) VarTemplateDecl(DC, L, Name, Params, Decl);
+ return new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
}
VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) VarTemplateDecl(EmptyShell());
+ return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
+ DeclarationName(), nullptr, nullptr);
}
// TODO: Unify across class, function and variable templates?
@@ -957,7 +959,7 @@
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
- CommonPtr->LazySpecializations = 0;
+ CommonPtr->LazySpecializations = nullptr;
for (uint32_t I = 0, N = *Specs++; I != N; ++I)
(void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
}
@@ -1049,27 +1051,28 @@
return P->getMostRecentDecl();
}
- return 0;
+ return nullptr;
}
//===----------------------------------------------------------------------===//
// VarTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
- ASTContext &Context, Kind DK, DeclContext *DC, SourceLocation StartLoc,
+ Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
unsigned NumArgs)
- : VarDecl(DK, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), T,
- TInfo, S),
- SpecializedTemplate(SpecializedTemplate), ExplicitInfo(0),
+ : VarDecl(DK, Context, DC, StartLoc, IdLoc,
+ SpecializedTemplate->getIdentifier(), T, TInfo, S),
+ SpecializedTemplate(SpecializedTemplate), ExplicitInfo(nullptr),
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)),
SpecializationKind(TSK_Undeclared) {}
-VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK)
- : VarDecl(DK, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0,
- SC_None),
- ExplicitInfo(0), SpecializationKind(TSK_Undeclared) {}
+VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK,
+ ASTContext &C)
+ : VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
+ QualType(), nullptr, SC_None),
+ ExplicitInfo(nullptr), SpecializationKind(TSK_Undeclared) {}
VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
@@ -1077,13 +1080,14 @@
TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
unsigned NumArgs) {
return new (Context, DC) VarTemplateSpecializationDecl(
- Context, VarTemplateSpecialization, DC, StartLoc, IdLoc,
+ VarTemplateSpecialization, Context, DC, StartLoc, IdLoc,
SpecializedTemplate, T, TInfo, S, Args, NumArgs);
}
VarTemplateSpecializationDecl *
VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) VarTemplateSpecializationDecl(VarTemplateSpecialization);
+ return new (C, ID)
+ VarTemplateSpecializationDecl(VarTemplateSpecialization, C);
}
void VarTemplateSpecializationDecl::getNameForDiagnostic(
@@ -1122,11 +1126,11 @@
VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
const ASTTemplateArgumentListInfo *ArgInfos)
- : VarTemplateSpecializationDecl(Context, VarTemplatePartialSpecialization,
+ : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
DC, StartLoc, IdLoc, SpecializedTemplate, T,
TInfo, S, Args, NumArgs),
TemplateParams(Params), ArgsAsWritten(ArgInfos),
- InstantiatedFromMember(0, false) {
+ InstantiatedFromMember(nullptr, false) {
// TODO: The template parameters should be in DC by now. Verify.
// AdoptTemplateParameterList(Params, DC);
}
@@ -1152,5 +1156,5 @@
VarTemplatePartialSpecializationDecl *
VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) VarTemplatePartialSpecializationDecl();
+ return new (C, ID) VarTemplatePartialSpecializationDecl(C);
}
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index f9041c0..b7c2877 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -167,7 +167,7 @@
case DeclarationName::CXXOperatorName: {
static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
- 0,
+ nullptr,
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Spelling,
#include "clang/Basic/OperatorKinds.def"
@@ -273,7 +273,7 @@
if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
return CXXLit->ID;
else
- return 0;
+ return nullptr;
}
void *DeclarationName::getFETokenInfoAsVoidSlow() const {
@@ -346,7 +346,7 @@
for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
CXXOperatorNames[Op].ExtraKindOrNumArgs
= Op + DeclarationNameExtra::CXXConversionFunction;
- CXXOperatorNames[Op].FETokenInfo = 0;
+ CXXOperatorNames[Op].FETokenInfo = nullptr;
}
}
@@ -407,14 +407,14 @@
ID.AddInteger(EKind);
ID.AddPointer(Ty.getAsOpaquePtr());
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
return DeclarationName(Name);
CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
SpecialName->ExtraKindOrNumArgs = EKind;
SpecialName->Type = Ty;
- SpecialName->FETokenInfo = 0;
+ SpecialName->FETokenInfo = nullptr;
SpecialNames->InsertNode(SpecialName, InsertPos);
return DeclarationName(SpecialName);
@@ -434,7 +434,7 @@
llvm::FoldingSetNodeID ID;
ID.AddPointer(II);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (CXXLiteralOperatorIdName *Name =
LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
return DeclarationName (Name);
@@ -442,7 +442,7 @@
CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
LiteralName->ID = II;
- LiteralName->FETokenInfo = 0;
+ LiteralName->FETokenInfo = nullptr;
LiteralNames->InsertNode(LiteralName, InsertPos);
return DeclarationName(LiteralName);
@@ -455,7 +455,7 @@
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
- NamedType.TInfo = 0;
+ NamedType.TInfo = nullptr;
break;
case DeclarationName::CXXOperatorName:
CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 2f5f14f..7e1b2d9 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -44,7 +44,7 @@
DerivedType = PTy->getPointeeType();
if (DerivedType->isDependentType())
- return NULL;
+ return nullptr;
const RecordType *Ty = DerivedType->castAs<RecordType>();
Decl *D = Ty->getDecl();
@@ -121,6 +121,8 @@
switch (UO->getOpcode()) {
case UO_Plus:
return UO->getSubExpr()->isKnownToHaveBooleanValue();
+ case UO_LNot:
+ return true;
default:
return false;
}
@@ -400,7 +402,7 @@
const TemplateArgumentListInfo *TemplateArgs) {
// Filter out cases where the found Decl is the same as the value refenenced.
if (D == FoundD)
- FoundD = 0;
+ FoundD = nullptr;
std::size_t Size = sizeof(DeclRefExpr);
if (QualifierLoc)
@@ -476,7 +478,7 @@
return "";
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
- if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual)
+ if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
return FD->getNameAsString();
SmallString<256> Name;
@@ -492,16 +494,28 @@
PrintingPolicy Policy(Context.getLangOpts());
std::string Proto;
llvm::raw_string_ostream POut(Proto);
- FD->printQualifiedName(POut, Policy);
const FunctionDecl *Decl = FD;
if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern())
Decl = Pattern;
const FunctionType *AFT = Decl->getType()->getAs<FunctionType>();
- const FunctionProtoType *FT = 0;
+ const FunctionProtoType *FT = nullptr;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(AFT);
+ if (IT == FuncSig) {
+ switch (FT->getCallConv()) {
+ case CC_C: POut << "__cdecl "; break;
+ case CC_X86StdCall: POut << "__stdcall "; break;
+ case CC_X86FastCall: POut << "__fastcall "; break;
+ case CC_X86ThisCall: POut << "__thiscall "; break;
+ // Only bother printing the conventions that MSVC knows about.
+ default: break;
+ }
+ }
+
+ FD->printQualifiedName(POut, Policy);
+
POut << "(";
if (FT) {
for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
@@ -1118,7 +1132,7 @@
}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), SubExprs(0), NumArgs(0) {
+ : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) {
// FIXME: Why do we allocate this?
SubExprs = new (C) Stmt*[PREARGS_START];
CallExprBits.NumPreArgs = 0;
@@ -1126,7 +1140,7 @@
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
EmptyShell Empty)
- : Expr(SC, Empty), SubExprs(0), NumArgs(0) {
+ : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) {
// FIXME: Why do we allocate this?
SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs];
CallExprBits.NumPreArgs = NumPreArgs;
@@ -1153,7 +1167,7 @@
if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE))
return ME->getMemberDecl();
- return 0;
+ return nullptr;
}
FunctionDecl *CallExpr::getDirectCallee() {
@@ -1182,7 +1196,7 @@
// Null out new args.
for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs;
i != NumArgs+PREARGS_START+NumPreArgs; ++i)
- NewSubExprs[i] = 0;
+ NewSubExprs[i] = nullptr;
if (SubExprs) C.Deallocate(SubExprs);
SubExprs = NewSubExprs;
@@ -1624,7 +1638,7 @@
}
Expr *CastExpr::getSubExprAsWritten() {
- Expr *SubExpr = 0;
+ Expr *SubExpr = nullptr;
CastExpr *E = this;
do {
SubExpr = E->getSubExpr();
@@ -1820,7 +1834,7 @@
: Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
false, false),
InitExprs(C, initExprs.size()),
- LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(0, true)
+ LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(nullptr, true)
{
sawArrayRangeDesignator(false);
for (unsigned I = 0; I != initExprs.size(); ++I) {
@@ -1843,14 +1857,14 @@
}
void InitListExpr::resizeInits(const ASTContext &C, unsigned NumInits) {
- InitExprs.resize(C, NumInits, 0);
+ InitExprs.resize(C, NumInits, nullptr);
}
Expr *InitListExpr::updateInit(const ASTContext &C, unsigned Init, Expr *expr) {
if (Init >= InitExprs.size()) {
- InitExprs.insert(C, InitExprs.end(), Init - InitExprs.size() + 1, 0);
+ InitExprs.insert(C, InitExprs.end(), Init - InitExprs.size() + 1, nullptr);
setInit(Init, expr);
- return 0;
+ return nullptr;
}
Expr *Result = cast_or_null<Expr>(InitExprs[Init]);
@@ -1864,7 +1878,7 @@
// Fill out any "holes" in the array due to designated initializers.
Expr **inits = getInits();
for (unsigned i = 0, e = getNumInits(); i != e; ++i)
- if (inits[i] == 0)
+ if (inits[i] == nullptr)
inits[i] = filler;
}
@@ -2080,6 +2094,9 @@
case OO_Greater:
case OO_GreaterEqual:
case OO_LessEqual:
+ if (Op->getCallReturnType()->isReferenceType() ||
+ Op->getCallReturnType()->isVoidType())
+ break;
WarnE = this;
Loc = Op->getOperatorLoc();
R1 = Op->getSourceRange();
@@ -2386,6 +2403,27 @@
}
}
+Expr *Expr::IgnoreCasts() {
+ Expr *E = this;
+ while (true) {
+ if (CastExpr *P = dyn_cast<CastExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = Materialize->GetTemporaryExpr();
+ continue;
+ }
+ if (SubstNonTypeTemplateParmExpr *NTTP
+ = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
+ E = NTTP->getReplacement();
+ continue;
+ }
+ return E;
+ }
+}
+
/// IgnoreParenLValueCasts - Ignore parentheses and lvalue-to-rvalue
/// casts. This is intended purely as a temporary workaround for code
/// that hasn't yet been rewritten to do the right thing about those
@@ -2631,7 +2669,8 @@
return false;
}
-bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
+bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
+ const Expr **Culprit) const {
// This function is attempting whether an expression is an initializer
// which can be evaluated at compile-time. It very closely parallels
// ConstExprEmitter in CGExprConstant.cpp; if they don't match, it
@@ -2643,7 +2682,11 @@
if (IsForRef) {
EvalResult Result;
- return EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects;
+ if (EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects)
+ return true;
+ if (Culprit)
+ *Culprit = this;
+ return false;
}
switch (getStmtClass()) {
@@ -2662,7 +2705,7 @@
// Trivial copy constructor
assert(CE->getNumArgs() == 1 && "trivial ctor with > 1 argument");
- return CE->getArg(0)->isConstantInitializer(Ctx, false);
+ return CE->getArg(0)->isConstantInitializer(Ctx, false, Culprit);
}
break;
@@ -2672,14 +2715,14 @@
// "struct x {int x;} x = (struct x) {};".
// FIXME: This accepts other cases it shouldn't!
const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
- return Exp->isConstantInitializer(Ctx, false);
+ return Exp->isConstantInitializer(Ctx, false, Culprit);
}
case InitListExprClass: {
const InitListExpr *ILE = cast<InitListExpr>(this);
if (ILE->getType()->isArrayType()) {
unsigned numInits = ILE->getNumInits();
for (unsigned i = 0; i < numInits; i++) {
- if (!ILE->getInit(i)->isConstantInitializer(Ctx, false))
+ if (!ILE->getInit(i)->isConstantInitializer(Ctx, false, Culprit))
return false;
}
return true;
@@ -2703,11 +2746,14 @@
if (Field->isBitField()) {
// Bitfields have to evaluate to an integer.
llvm::APSInt ResultTmp;
- if (!Elt->EvaluateAsInt(ResultTmp, Ctx))
+ if (!Elt->EvaluateAsInt(ResultTmp, Ctx)) {
+ if (Culprit)
+ *Culprit = Elt;
return false;
+ }
} else {
bool RefType = Field->getType()->isReferenceType();
- if (!Elt->isConstantInitializer(Ctx, RefType))
+ if (!Elt->isConstantInitializer(Ctx, RefType, Culprit))
return false;
}
}
@@ -2721,19 +2767,22 @@
return true;
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()
- ->isConstantInitializer(Ctx, IsForRef);
+ ->isConstantInitializer(Ctx, IsForRef, Culprit);
case GenericSelectionExprClass:
return cast<GenericSelectionExpr>(this)->getResultExpr()
- ->isConstantInitializer(Ctx, IsForRef);
+ ->isConstantInitializer(Ctx, IsForRef, Culprit);
case ChooseExprClass:
- if (cast<ChooseExpr>(this)->isConditionDependent())
+ if (cast<ChooseExpr>(this)->isConditionDependent()) {
+ if (Culprit)
+ *Culprit = this;
return false;
+ }
return cast<ChooseExpr>(this)->getChosenSubExpr()
- ->isConstantInitializer(Ctx, IsForRef);
+ ->isConstantInitializer(Ctx, IsForRef, Culprit);
case UnaryOperatorClass: {
const UnaryOperator* Exp = cast<UnaryOperator>(this);
if (Exp->getOpcode() == UO_Extension)
- return Exp->getSubExpr()->isConstantInitializer(Ctx, false);
+ return Exp->getSubExpr()->isConstantInitializer(Ctx, false, Culprit);
break;
}
case CXXFunctionalCastExprClass:
@@ -2753,25 +2802,29 @@
CE->getCastKind() == CK_ConstructorConversion ||
CE->getCastKind() == CK_NonAtomicToAtomic ||
CE->getCastKind() == CK_AtomicToNonAtomic)
- return CE->getSubExpr()->isConstantInitializer(Ctx, false);
+ return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit);
break;
}
case MaterializeTemporaryExprClass:
return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
- ->isConstantInitializer(Ctx, false);
+ ->isConstantInitializer(Ctx, false, Culprit);
case SubstNonTypeTemplateParmExprClass:
return cast<SubstNonTypeTemplateParmExpr>(this)->getReplacement()
- ->isConstantInitializer(Ctx, false);
+ ->isConstantInitializer(Ctx, false, Culprit);
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()
- ->isConstantInitializer(Ctx, false);
+ ->isConstantInitializer(Ctx, false, Culprit);
case CXXDefaultInitExprClass:
return cast<CXXDefaultInitExpr>(this)->getExpr()
- ->isConstantInitializer(Ctx, false);
+ ->isConstantInitializer(Ctx, false, Culprit);
}
- return isEvaluatable(Ctx);
+ if (isEvaluatable(Ctx))
+ return true;
+ if (Culprit)
+ *Culprit = this;
+ return false;
}
bool Expr::HasSideEffects(const ASTContext &Ctx) const {
@@ -3223,7 +3276,7 @@
return BinOp->getRHS()->getSourceBitField();
}
- return 0;
+ return nullptr;
}
bool Expr::refersToVectorElement() const {
@@ -3329,8 +3382,9 @@
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
Kind(IsInstanceSuper? SuperInstance : SuperClass),
- HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit),
- SuperLoc(SuperLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+ HasMethod(Method != nullptr), IsDelegateInitCall(false),
+ IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc),
+ RBracLoc(RBracLoc)
{
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(SuperType.getAsOpaquePtr());
@@ -3353,8 +3407,8 @@
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
Kind(Class),
- HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit),
- LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+ HasMethod(Method != nullptr), IsDelegateInitCall(false),
+ IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver);
@@ -3378,8 +3432,8 @@
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
Kind(Instance),
- HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit),
- LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+ HasMethod(Method != nullptr), IsDelegateInitCall(false),
+ IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver);
@@ -3561,7 +3615,7 @@
if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>())
return Ty->getInterface();
- return 0;
+ return nullptr;
}
StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
@@ -3934,7 +3988,7 @@
ExprBits.ContainsUnexpandedParameterPack = true;
if (isa<OpaqueValueExpr>(E))
- assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != 0 &&
+ assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != nullptr &&
"opaque-value semantic expressions for pseudo-object "
"operations must have sources");
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index ee49925..1c90678 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -67,19 +67,19 @@
// Loop all record redeclaration looking for an uuid attribute.
CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
if (!RD)
- return 0;
+ return nullptr;
// __uuidof can grab UUIDs from template arguments.
if (ClassTemplateSpecializationDecl *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
- UuidAttr *UuidForRD = 0;
+ UuidAttr *UuidForRD = nullptr;
for (unsigned I = 0, N = TAL.size(); I != N; ++I) {
const TemplateArgument &TA = TAL[I];
bool SeenMultipleGUIDs = false;
- UuidAttr *UuidForTA = 0;
+ UuidAttr *UuidForTA = nullptr;
if (TA.getKind() == TemplateArgument::Type)
UuidForTA = GetUuidAttrOfType(TA.getAsType(), &SeenMultipleGUIDs);
else if (TA.getKind() == TemplateArgument::Declaration)
@@ -101,7 +101,7 @@
if (SeenMultipleGUIDs) {
if (RDHasMultipleGUIDsPtr)
*RDHasMultipleGUIDsPtr = true;
- return 0;
+ return nullptr;
}
}
@@ -112,7 +112,7 @@
if (auto Uuid = I->getAttr<UuidAttr>())
return Uuid;
- return 0;
+ return nullptr;
}
StringRef CXXUuidofExpr::getUuidAsStringRef(ASTContext &Context) const {
@@ -149,14 +149,15 @@
ty->isDependentType(), ty->isDependentType(),
ty->isInstantiationDependentType(),
ty->containsUnexpandedParameterPack()),
- SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete),
+ SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete),
AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
Range(Range), DirectInitRange(directInitRange),
GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
- assert((initializer != 0 || initializationStyle == NoInit) &&
+ assert((initializer != nullptr || initializationStyle == NoInit) &&
"Only NoInit can have no initializer.");
StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;
- AllocateArgsArray(C, arraySize != 0, placementArgs.size(), initializer != 0);
+ AllocateArgsArray(C, arraySize != nullptr, placementArgs.size(),
+ initializer != nullptr);
unsigned i = 0;
if (Array) {
if (arraySize->isInstantiationDependent())
@@ -201,7 +202,7 @@
void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray,
unsigned numPlaceArgs, bool hasInitializer){
- assert(SubExprs == 0 && "SubExprs already allocated");
+ assert(SubExprs == nullptr && "SubExprs already allocated");
Array = isArray;
NumPlacementArgs = numPlaceArgs;
@@ -343,9 +344,9 @@
QualifierLoc.getNestedNameSpecifier()
->containsUnexpandedParameterPack()))),
NameInfo(NameInfo), QualifierLoc(QualifierLoc),
- Results(0), NumResults(End - Begin),
- HasTemplateKWAndArgsInfo(TemplateArgs != 0 || TemplateKWLoc.isValid())
-{
+ Results(nullptr), NumResults(End - Begin),
+ HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
+ TemplateKWLoc.isValid()) {
NumResults = End - Begin;
if (NumResults) {
// Determine whether this expression is type-dependent.
@@ -396,7 +397,7 @@
void OverloadExpr::initializeResults(const ASTContext &C,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
- assert(Results == 0 && "Results already initialized!");
+ assert(!Results && "Results already initialized!");
NumResults = End - Begin;
if (NumResults) {
Results = static_cast<DeclAccessPair *>(
@@ -431,7 +432,7 @@
QualifierLoc.getNestedNameSpecifier()
->containsUnexpandedParameterPack()))),
QualifierLoc(QualifierLoc), NameInfo(NameInfo),
- HasTemplateKWAndArgsInfo(Args != 0 || TemplateKWLoc.isValid())
+ HasTemplateKWAndArgsInfo(Args != nullptr || TemplateKWLoc.isValid())
{
if (Args) {
bool Dependent = true;
@@ -476,7 +477,7 @@
DependentScopeDeclRefExpr *E
= new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
SourceLocation(),
- DeclarationNameInfo(), 0);
+ DeclarationNameInfo(), nullptr);
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
}
@@ -542,7 +543,7 @@
return BO->getLHS();
// FIXME: Will eventually need to cope with member pointers.
- return 0;
+ return nullptr;
}
CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const {
@@ -551,14 +552,14 @@
return cast<CXXMethodDecl>(MemExpr->getMemberDecl());
// FIXME: Will eventually need to cope with member pointers.
- return 0;
+ return nullptr;
}
CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() const {
Expr* ThisArg = getImplicitObjectArgument();
if (!ThisArg)
- return 0;
+ return nullptr;
if (ThisArg->getType()->isAnyPointerType())
return ThisArg->getType()->getPointeeType()->getAsCXXRecordDecl();
@@ -864,7 +865,7 @@
Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates),
ListInitialization(ListInitialization),
ZeroInitialization(ZeroInitialization),
- ConstructKind(ConstructKind), Args(0)
+ ConstructKind(ConstructKind), Args(nullptr)
{
if (NumArgs) {
Args = new (C) Stmt*[args.size()];
@@ -884,7 +885,7 @@
}
}
-LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit,
+LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
LambdaCaptureKind Kind, VarDecl *Var,
SourceLocation EllipsisLoc)
: DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
@@ -894,8 +895,8 @@
Bits |= Capture_Implicit;
switch (Kind) {
- case LCK_This:
- assert(Var == 0 && "'this' capture cannot have a variable!");
+ case LCK_This:
+ assert(!Var && "'this' capture cannot have a variable!");
break;
case LCK_ByCopy:
@@ -908,7 +909,7 @@
DeclAndBits.setInt(Bits);
}
-LambdaCaptureKind LambdaExpr::Capture::getCaptureKind() const {
+LambdaCaptureKind LambdaCapture::getCaptureKind() const {
Decl *D = DeclAndBits.getPointer();
if (!D)
return LCK_This;
@@ -1029,6 +1030,10 @@
return capture_begin() + NumCaptures;
}
+LambdaExpr::capture_range LambdaExpr::captures() const {
+ return capture_range(capture_begin(), capture_end());
+}
+
LambdaExpr::capture_iterator LambdaExpr::explicit_capture_begin() const {
return capture_begin();
}
@@ -1039,6 +1044,10 @@
return Data.Captures + Data.NumExplicitCaptures;
}
+LambdaExpr::capture_range LambdaExpr::explicit_captures() const {
+ return capture_range(explicit_capture_begin(), explicit_capture_end());
+}
+
LambdaExpr::capture_iterator LambdaExpr::implicit_capture_begin() const {
return explicit_capture_end();
}
@@ -1047,6 +1056,10 @@
return capture_end();
}
+LambdaExpr::capture_range LambdaExpr::implicit_captures() const {
+ return capture_range(implicit_capture_begin(), implicit_capture_end());
+}
+
ArrayRef<VarDecl *>
LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const {
assert(HasArrayIndexVars && "No array index-var data?");
@@ -1185,7 +1198,8 @@
->containsUnexpandedParameterPack()) ||
MemberNameInfo.containsUnexpandedParameterPack())),
Base(Base), BaseType(BaseType), IsArrow(IsArrow),
- HasTemplateKWAndArgsInfo(TemplateArgs != 0 || TemplateKWLoc.isValid()),
+ HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
+ TemplateKWLoc.isValid()),
OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
MemberNameInfo(MemberNameInfo) {
@@ -1258,26 +1272,26 @@
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
if (!HasTemplateKWAndArgsInfo)
- return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(),
+ return new (C) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
0, SourceLocation(),
- NestedNameSpecifierLoc(), 0,
- DeclarationNameInfo());
+ NestedNameSpecifierLoc(),
+ nullptr, DeclarationNameInfo());
std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>());
CXXDependentScopeMemberExpr *E
- = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(),
+ = new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
0, SourceLocation(),
NestedNameSpecifierLoc(),
- SourceLocation(), 0,
- DeclarationNameInfo(), 0);
+ SourceLocation(), nullptr,
+ DeclarationNameInfo(), nullptr);
E->HasTemplateKWAndArgsInfo = true;
return E;
}
bool CXXDependentScopeMemberExpr::isImplicitAccess() const {
- if (Base == 0)
+ if (!Base)
return true;
return cast<Expr>(Base)->isImplicitCXXThis();
@@ -1331,7 +1345,7 @@
}
bool UnresolvedMemberExpr::isImplicitAccess() const {
- if (Base == 0)
+ if (!Base)
return true;
return cast<Expr>(Base)->isImplicitCXXThis();
@@ -1380,7 +1394,7 @@
// If there was a nested name specifier, it names the naming class.
// It can't be dependent: after all, we were actually able to do the
// lookup.
- CXXRecordDecl *Record = 0;
+ CXXRecordDecl *Record = nullptr;
if (getQualifier()) {
const Type *T = getQualifier()->getAsType();
assert(T && "qualifier in member expression does not name type");
@@ -1443,7 +1457,26 @@
unsigned NumParams) {
return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
sizeof(ParmVarDecl*) * NumParams))
- FunctionParmPackExpr(QualType(), 0, SourceLocation(), 0, 0);
+ FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr);
+}
+
+void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy,
+ unsigned ManglingNumber) {
+ // We only need extra state if we have to remember more than just the Stmt.
+ if (!ExtendedBy)
+ return;
+
+ // We may need to allocate extra storage for the mangling number and the
+ // extended-by ValueDecl.
+ if (!State.is<ExtraState *>()) {
+ auto ES = new (ExtendedBy->getASTContext()) ExtraState;
+ ES->Temporary = State.get<Stmt *>();
+ State = ES;
+ }
+
+ auto ES = State.get<ExtraState *>();
+ ES->ExtendingDecl = ExtendedBy;
+ ES->ManglingNumber = ManglingNumber;
}
TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 55b9f13..d3d2530 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -549,8 +549,8 @@
// category of the other.
bool TrueIsThrow = isa<CXXThrowExpr>(True->IgnoreParenImpCasts());
bool FalseIsThrow = isa<CXXThrowExpr>(False->IgnoreParenImpCasts());
- if (const Expr *NonThrow = TrueIsThrow ? (FalseIsThrow ? 0 : False)
- : (FalseIsThrow ? True : 0))
+ if (const Expr *NonThrow = TrueIsThrow ? (FalseIsThrow ? nullptr : False)
+ : (FalseIsThrow ? True : nullptr))
return ClassifyInternal(Ctx, NonThrow);
// [Otherwise] the result [...] is a prvalue.
@@ -593,7 +593,8 @@
// Assignment to a property in ObjC is an implicit setter access. But a
// setter might not exist.
if (const ObjCPropertyRefExpr *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) {
- if (Expr->isImplicitProperty() && Expr->getImplicitPropertySetter() == 0)
+ if (Expr->isImplicitProperty() &&
+ Expr->getImplicitPropertySetter() == nullptr)
return Cl::CM_NoSetterProperty;
}
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 9c69080..c1468cb 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -320,7 +320,7 @@
APValue *getTemporary(const void *Key) {
MapTy::iterator I = Temporaries.find(Key);
- return I == Temporaries.end() ? 0 : &I->second;
+ return I == Temporaries.end() ? nullptr : &I->second;
}
APValue &createTemporary(const void *Key, bool IsLifetimeExtended);
};
@@ -347,7 +347,8 @@
PartialDiagnostic *Diag;
public:
- explicit OptionalDiagnostic(PartialDiagnostic *Diag = 0) : Diag(Diag) {}
+ explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr)
+ : Diag(Diag) {}
template<typename T>
OptionalDiagnostic &operator<<(const T &v) {
@@ -506,12 +507,13 @@
bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; }
EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode)
- : Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0),
+ : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr),
CallStackDepth(0), NextCallIndex(1),
StepsLeft(getLangOpts().ConstexprStepLimit),
- BottomFrame(*this, SourceLocation(), 0, 0, 0),
- EvaluatingDecl((const ValueDecl*)0), EvaluatingDeclValue(0),
- HasActiveDiagnostic(false), EvalMode(Mode) {}
+ BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
+ EvaluatingDecl((const ValueDecl *)nullptr),
+ EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
+ EvalMode(Mode) {}
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base;
@@ -544,7 +546,7 @@
CallStackFrame *Frame = CurrentCall;
while (Frame->Index > CallIndex)
Frame = Frame->Caller;
- return (Frame->Index == CallIndex) ? Frame : 0;
+ return (Frame->Index == CallIndex) ? Frame : nullptr;
}
bool nextStep(const Stmt *S) {
@@ -741,7 +743,7 @@
public:
SpeculativeEvaluationRAII(EvalInfo &Info,
- SmallVectorImpl<PartialDiagnosticAt> *NewDiag = 0)
+ SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr)
: Info(Info), Old(Info.EvalStatus) {
Info.EvalStatus.Diag = NewDiag;
// If we're speculatively evaluating, we may have skipped over some
@@ -968,7 +970,7 @@
// any object: we won't use such a designator for anything.
if (!Info.getLangOpts().CPlusPlus11)
Designator.setInvalid();
- return checkNullPointer(Info, E, CSK) &&
+ return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) &&
Designator.checkSubobject(Info, E, CSK);
}
@@ -986,7 +988,7 @@
Designator.addComplexUnchecked(EltTy, Imag);
}
void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
- if (checkNullPointer(Info, E, CSK_ArrayIndex))
+ if (N && checkNullPointer(Info, E, CSK_ArrayIndex))
Designator.adjustIndex(Info, E, N);
}
};
@@ -1301,7 +1303,7 @@
/// Check that this core constant expression is of literal type, and if not,
/// produce an appropriate diagnostic.
static bool CheckLiteralType(EvalInfo &Info, const Expr *E,
- const LValue *This = 0) {
+ const LValue *This = nullptr) {
if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx))
return true;
@@ -1762,7 +1764,7 @@
static bool HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj,
const CXXRecordDecl *Derived,
const CXXRecordDecl *Base,
- const ASTRecordLayout *RL = 0) {
+ const ASTRecordLayout *RL = nullptr) {
if (!RL) {
if (Derived->isInvalidDecl()) return false;
RL = &Info.Ctx.getASTRecordLayout(Derived);
@@ -1815,7 +1817,7 @@
/// currently described by LVal.
static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal,
const FieldDecl *FD,
- const ASTRecordLayout *RL = 0) {
+ const ASTRecordLayout *RL = nullptr) {
if (!RL) {
if (FD->getParent()->isInvalidDecl()) return false;
RL = &Info.Ctx.getASTRecordLayout(FD->getParent());
@@ -2070,7 +2072,7 @@
/// The type of the complete object.
QualType Type;
- CompleteObject() : Value(0) {}
+ CompleteObject() : Value(nullptr) {}
CompleteObject(APValue *Value, QualType Type)
: Value(Value), Type(Type) {
assert(Value && "missing value for complete object");
@@ -2098,7 +2100,7 @@
APValue *O = Obj.Value;
QualType ObjType = Obj.Type;
- const FieldDecl *LastField = 0;
+ const FieldDecl *LastField = nullptr;
// Walk the designator's path to find the subobject.
for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) {
@@ -2121,7 +2123,7 @@
return true;
}
- LastField = 0;
+ LastField = nullptr;
if (ObjType->isArrayType()) {
// Next subobject is an array element.
const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType);
@@ -2404,7 +2406,7 @@
return CompleteObject();
}
- CallStackFrame *Frame = 0;
+ CallStackFrame *Frame = nullptr;
if (LVal.CallIndex) {
Frame = Info.getCallFrame(LVal.CallIndex);
if (!Frame) {
@@ -2429,7 +2431,7 @@
}
// Compute value storage location and type of base object.
- APValue *BaseVal = 0;
+ APValue *BaseVal = nullptr;
QualType BaseType = getType(LVal.Base);
if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) {
@@ -2799,7 +2801,7 @@
// if we're post-incrementing a complex.
if (Old) {
*Old = Subobj;
- Old = 0;
+ Old = nullptr;
}
switch (Subobj.getKind()) {
@@ -2957,14 +2959,14 @@
bool IncludeMember = true) {
MemberPtr MemPtr;
if (!EvaluateMemberPointer(RHS, MemPtr, Info))
- return 0;
+ return nullptr;
// C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to
// member value, the behavior is undefined.
if (!MemPtr.getDecl()) {
// FIXME: Specific diagnostic.
Info.Diag(RHS);
- return 0;
+ return nullptr;
}
if (MemPtr.isDerivedMember()) {
@@ -2974,7 +2976,7 @@
if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() >
LV.Designator.Entries.size()) {
Info.Diag(RHS);
- return 0;
+ return nullptr;
}
unsigned PathLengthToMember =
LV.Designator.Entries.size() - MemPtr.Path.size();
@@ -2984,14 +2986,14 @@
const CXXRecordDecl *MPDecl = MemPtr.Path[I];
if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) {
Info.Diag(RHS);
- return 0;
+ return nullptr;
}
}
// Truncate the lvalue to the appropriate derived class.
if (!CastToDerivedClass(Info, RHS, LV, MemPtr.getContainingRecord(),
PathLengthToMember))
- return 0;
+ return nullptr;
} else if (!MemPtr.Path.empty()) {
// Extend the LValue path with the member pointer's path.
LV.Designator.Entries.reserve(LV.Designator.Entries.size() +
@@ -3006,24 +3008,24 @@
for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) {
const CXXRecordDecl *Base = MemPtr.Path[N - I - 1];
if (!HandleLValueDirectBase(Info, RHS, LV, RD, Base))
- return 0;
+ return nullptr;
RD = Base;
}
// Finally cast to the class containing the member.
if (!HandleLValueDirectBase(Info, RHS, LV, RD,
MemPtr.getContainingRecord()))
- return 0;
+ return nullptr;
}
// Add the member. Note that we cannot build bound member functions here.
if (IncludeMember) {
if (const FieldDecl *FD = dyn_cast<FieldDecl>(MemPtr.getDecl())) {
if (!HandleLValueMember(Info, RHS, LV, FD))
- return 0;
+ return nullptr;
} else if (const IndirectFieldDecl *IFD =
dyn_cast<IndirectFieldDecl>(MemPtr.getDecl())) {
if (!HandleLValueIndirectMember(Info, RHS, LV, IFD))
- return 0;
+ return nullptr;
} else {
llvm_unreachable("can't construct reference to bound member function");
}
@@ -3043,7 +3045,7 @@
MemberPtr MemPtr;
EvaluateMemberPointer(BO->getRHS(), MemPtr, Info);
}
- return 0;
+ return nullptr;
}
return HandleMemberPointerAccess(Info, BO->getLHS()->getType(), LV,
@@ -3147,12 +3149,13 @@
}
static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
- const Stmt *S, const SwitchCase *SC = 0);
+ const Stmt *S,
+ const SwitchCase *SC = nullptr);
/// Evaluate the body of a loop, and translate the result as appropriate.
static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info,
const Stmt *Body,
- const SwitchCase *Case = 0) {
+ const SwitchCase *Case = nullptr) {
BlockScopeRAII Scope(Info);
switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case)) {
case ESR_Break:
@@ -3186,7 +3189,7 @@
// Find the switch case corresponding to the value of the condition.
// FIXME: Cache this lookup.
- const SwitchCase *Found = 0;
+ const SwitchCase *Found = nullptr;
for (const SwitchCase *SC = SS->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
if (isa<DefaultStmt>(SC)) {
@@ -3251,7 +3254,7 @@
case Stmt::CaseStmtClass:
case Stmt::DefaultStmtClass:
if (Case == S)
- Case = 0;
+ Case = nullptr;
break;
case Stmt::IfStmtClass: {
@@ -3344,7 +3347,7 @@
for (const auto *BI : CS->body()) {
EvalStmtResult ESR = EvaluateStmt(Result, Info, BI, Case);
if (ESR == ESR_Succeeded)
- Case = 0;
+ Case = nullptr;
else if (ESR != ESR_CaseNotFound)
return ESR;
}
@@ -3393,7 +3396,7 @@
EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case);
if (ESR != ESR_Continue)
return ESR;
- Case = 0;
+ Case = nullptr;
FullExpressionRAII CondScope(Info);
if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info))
@@ -3689,7 +3692,7 @@
APValue *Value = &Result;
// Determine the subobject to initialize.
- FieldDecl *FD = 0;
+ FieldDecl *FD = nullptr;
if (I->isBaseInitializer()) {
QualType BaseType(I->getBaseClass(), 0);
#ifndef NDEBUG
@@ -3956,14 +3959,14 @@
const Expr *Callee = E->getCallee()->IgnoreParens();
QualType CalleeType = Callee->getType();
- const FunctionDecl *FD = 0;
- LValue *This = 0, ThisVal;
+ const FunctionDecl *FD = nullptr;
+ LValue *This = nullptr, ThisVal;
ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs());
bool HasQualifier = false;
// Extract function decl and 'this' pointer from the callee.
if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
- const ValueDecl *Member = 0;
+ const ValueDecl *Member = nullptr;
if (const MemberExpr *ME = dyn_cast<MemberExpr>(Callee)) {
// Explicit bound member calls, such as x.f() or p->g();
if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal))
@@ -4025,7 +4028,7 @@
isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isVirtual())
return Error(E, diag::note_constexpr_virtual_call);
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
Stmt *Body = FD->getBody(Definition);
APValue Result;
@@ -4377,7 +4380,7 @@
}
bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
- CallStackFrame *Frame = 0;
+ CallStackFrame *Frame = nullptr;
if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1)
Frame = Info.CurrentCall;
@@ -4554,7 +4557,7 @@
return handleIncDec(
this->Info, UO, Result, UO->getSubExpr()->getType(),
- UO->isIncrementOp(), 0);
+ UO->isIncrementOp(), nullptr);
}
bool LValueExprEvaluator::VisitCompoundAssignOperator(
@@ -4622,7 +4625,7 @@
return true;
}
bool ZeroInitialization(const Expr *E) {
- return Success((Expr*)0);
+ return Success((Expr*)nullptr);
}
bool VisitBinaryOperator(const BinaryOperator *E);
@@ -4750,7 +4753,7 @@
if (Value.isInt()) {
unsigned Size = Info.Ctx.getTypeSize(E->getType());
uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue();
- Result.Base = (Expr*)0;
+ Result.Base = (Expr*)nullptr;
Result.Offset = CharUnits::fromQuantity(N);
Result.CallIndex = 0;
Result.Designator.setInvalid();
@@ -4822,7 +4825,7 @@
return true;
}
bool ZeroInitialization(const Expr *E) {
- return Success((const ValueDecl*)0);
+ return Success((const ValueDecl*)nullptr);
}
bool VisitCastExpr(const CastExpr *E);
@@ -4972,7 +4975,7 @@
// object's first non-static named data member is zero-initialized
RecordDecl::field_iterator I = RD->field_begin();
if (I == RD->field_end()) {
- Result = APValue((const FieldDecl*)0);
+ Result = APValue((const FieldDecl*)nullptr);
return true;
}
@@ -5119,7 +5122,7 @@
return ZeroInitialization(E);
}
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
FD->getBody(Definition);
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
@@ -5506,7 +5509,7 @@
unsigned NumEltsToInit = E->getNumInits();
unsigned NumElts = CAT->getSize().getZExtValue();
- const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : 0;
+ const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr;
// If the initializer might depend on the array index, run it for each
// array element. For now, just whitelist non-class value-initialization.
@@ -5601,7 +5604,7 @@
return EvaluateInPlace(*Value, Info, Subobject, &VIE);
}
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
FD->getBody(Definition);
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
@@ -6277,11 +6280,11 @@
const Expr *E;
EvalResult LHSResult; // meaningful only for binary operator expression.
enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind;
-
- Job() : StoredInfo(0) { }
+
+ Job() : StoredInfo(nullptr) {}
void startSpeculativeEval(EvalInfo &Info) {
OldEvalStatus = Info.EvalStatus;
- Info.EvalStatus.Diag = 0;
+ Info.EvalStatus.Diag = nullptr;
StoredInfo = &Info;
}
~Job() {
@@ -8645,7 +8648,7 @@
bool Expr::isIntegerConstantExpr(const ASTContext &Ctx,
SourceLocation *Loc) const {
if (Ctx.getLangOpts().CPlusPlus11)
- return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc);
+ return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc);
ICEDiag D = CheckICE(this, Ctx);
if (D.Kind != IK_ICE) {
@@ -8714,7 +8717,7 @@
}
// Build fake call to Callee.
- CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/0,
+ CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/nullptr,
ArgValues.data());
return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects;
}
@@ -8735,7 +8738,7 @@
EvalInfo::EM_PotentialConstantExpression);
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
- const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : 0;
+ const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr;
// Fabricate an arbitrary expression on the stack and pretend that it
// is a temporary being used as the 'this' pointer.
@@ -8754,7 +8757,7 @@
Info.setEvaluatingDecl(This.getLValueBase(), Scratch);
HandleConstructorCall(Loc, This, Args, CD, Info, Scratch);
} else
- HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : 0,
+ HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr,
Args, FD->getBody(), Info, Scratch);
return Diags.empty();
@@ -8777,7 +8780,7 @@
(void)Success;
assert(Success &&
"Failed to set up arguments for potential constant evaluation");
- CallStackFrame Frame(Info, SourceLocation(), FD, 0, ArgValues.data());
+ CallStackFrame Frame(Info, SourceLocation(), FD, nullptr, ArgValues.data());
APValue ResultScratch;
Evaluate(ResultScratch, Info, E);
diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp
index 96ebe92..8894107 100644
--- a/lib/AST/ExternalASTSource.cpp
+++ b/lib/AST/ExternalASTSource.cpp
@@ -14,16 +14,44 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclarationName.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace clang;
ExternalASTSource::~ExternalASTSource() { }
+void ExternalASTSource::FindFileRegionDecls(FileID File, unsigned Offset,
+ unsigned Length,
+ SmallVectorImpl<Decl *> &Decls) {}
+
+void ExternalASTSource::CompleteRedeclChain(const Decl *D) {}
+
+void ExternalASTSource::CompleteType(TagDecl *Tag) {}
+
+void ExternalASTSource::CompleteType(ObjCInterfaceDecl *Class) {}
+
+void ExternalASTSource::ReadComments() {}
+
+void ExternalASTSource::StartedDeserializing() {}
+
+void ExternalASTSource::FinishedDeserializing() {}
+
+void ExternalASTSource::StartTranslationUnit(ASTConsumer *Consumer) {}
+
void ExternalASTSource::PrintStats() { }
+bool ExternalASTSource::layoutRecordType(
+ const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets) {
+ return false;
+}
+
Decl *ExternalASTSource::GetExternalDecl(uint32_t ID) {
- return 0;
+ return nullptr;
}
Selector ExternalASTSource::GetExternalSelector(uint32_t ID) {
@@ -35,12 +63,12 @@
}
Stmt *ExternalASTSource::GetExternalDeclStmt(uint64_t Offset) {
- return 0;
+ return nullptr;
}
CXXBaseSpecifier *
ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
- return 0;
+ return nullptr;
}
bool
@@ -60,3 +88,21 @@
}
void ExternalASTSource::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { }
+
+uint32_t ExternalASTSource::incrementGeneration(ASTContext &C) {
+ uint32_t OldGeneration = CurrentGeneration;
+
+ // Make sure the generation of the topmost external source for the context is
+ // incremented. That might not be us.
+ auto *P = C.getExternalSource();
+ if (P && P != this)
+ CurrentGeneration = P->incrementGeneration(C);
+ else {
+ // FIXME: Only bump the generation counter if the current generation number
+ // has been observed?
+ if (!++CurrentGeneration)
+ llvm::report_fatal_error("generation counter overflowed", false);
+ }
+
+ return OldGeneration;
+}
diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp
index ffa2ddc..b5f8c0f 100644
--- a/lib/AST/ItaniumCXXABI.cpp
+++ b/lib/AST/ItaniumCXXABI.cpp
@@ -89,17 +89,8 @@
return new ItaniumNumberingContext();
}
};
-
-class ARMCXXABI : public ItaniumCXXABI {
-public:
- ARMCXXABI(ASTContext &Ctx) : ItaniumCXXABI(Ctx) { }
-};
}
CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) {
return new ItaniumCXXABI(Ctx);
}
-
-CXXABI *clang::CreateARMCXXABI(ASTContext &Ctx) {
- return new ARMCXXABI(Ctx);
-}
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 27ba2be..58a44b7 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -88,7 +88,7 @@
D = cast<Decl>(DC);
DC = getEffectiveDeclContext(D);
}
- return 0;
+ return nullptr;
}
static const FunctionDecl *getStructor(const FunctionDecl *fn) {
@@ -136,7 +136,8 @@
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
raw_ostream &) override;
- void mangleReferenceTemporary(const VarDecl *D, raw_ostream &) override;
+ void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber,
+ raw_ostream &) override;
void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) override;
void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) override;
void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
@@ -252,7 +253,7 @@
public:
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
- const NamedDecl *D = 0)
+ const NamedDecl *D = nullptr)
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0),
SeqID(0) {
// These can't be mangled without a ctor type or dtor type.
@@ -287,11 +288,13 @@
void mangleNumber(int64_t Number);
void mangleFloat(const llvm::APFloat &F);
void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleSeqID(unsigned SeqID);
void mangleName(const NamedDecl *ND);
void mangleType(QualType T);
void mangleNameOrStandardSubstitution(const NamedDecl *ND);
private:
+
bool mangleSubstitution(const NamedDecl *ND);
bool mangleSubstitution(QualType T);
bool mangleSubstitution(TemplateName Template);
@@ -456,6 +459,25 @@
if (!Context.shouldMangleDeclName(FD))
return;
+ if (FD->hasAttr<EnableIfAttr>()) {
+ FunctionTypeDepthState Saved = FunctionTypeDepth.push();
+ Out << "Ua9enable_ifI";
+ // FIXME: specific_attr_iterator iterates in reverse order. Fix that and use
+ // it here.
+ for (AttrVec::const_reverse_iterator I = FD->getAttrs().rbegin(),
+ E = FD->getAttrs().rend();
+ I != E; ++I) {
+ EnableIfAttr *EIA = dyn_cast<EnableIfAttr>(*I);
+ if (!EIA)
+ continue;
+ Out << 'X';
+ mangleExpression(EIA->getCond());
+ Out << 'E';
+ }
+ Out << 'E';
+ FunctionTypeDepth.pop(Saved);
+ }
+
// Whether the mangling of a function type includes the return type depends on
// the context and the nature of the function. The rules for deciding whether
// the return type is included are:
@@ -537,7 +559,7 @@
return Spec->getSpecializedTemplate();
}
- return 0;
+ return nullptr;
}
void CXXNameMangler::mangleName(const NamedDecl *ND) {
@@ -564,7 +586,7 @@
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
// Check if we have a template.
- const TemplateArgumentList *TemplateArgs = 0;
+ const TemplateArgumentList *TemplateArgs = nullptr;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleUnscopedTemplateName(TD);
mangleTemplateArgs(*TemplateArgs);
@@ -978,26 +1000,27 @@
// Pretend we had a different nested name specifier.
newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ 0,
+ /*prefix*/ nullptr,
/*template*/ false,
type.getTypePtr());
} else if (NamespaceDecl *nspace =
dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ 0,
+ /*prefix*/ nullptr,
nspace);
} else if (NamespaceAliasDecl *alias =
dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ 0,
+ /*prefix*/ nullptr,
alias);
} else {
// No sensible mangling to do here.
- newQualifier = 0;
+ newQualifier = nullptr;
}
if (newQualifier)
- return mangleUnresolvedPrefix(newQualifier, /*lookup*/ 0, recursive);
+ return mangleUnresolvedPrefix(newQualifier, /*lookup*/ nullptr,
+ recursive);
} else {
Out << "sr";
@@ -1020,7 +1043,7 @@
DeclarationName name,
unsigned knownArity) {
if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
- mangleUnqualifiedName(0, name, knownArity);
+ mangleUnqualifiedName(nullptr, name, knownArity);
}
static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) {
@@ -1035,10 +1058,10 @@
if (const FieldDecl *NamedDataMember =
FindFirstNamedDataMember(RT->getDecl()))
return NamedDataMember;
- }
+ }
// We didn't find a named data member.
- return 0;
+ return nullptr;
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
@@ -1244,7 +1267,7 @@
}
// Check if we have a template.
- const TemplateArgumentList *TemplateArgs = 0;
+ const TemplateArgumentList *TemplateArgs = nullptr;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD, NoFunction);
mangleTemplateArgs(*TemplateArgs);
@@ -1484,7 +1507,7 @@
return;
// Check if we have a template.
- const TemplateArgumentList *TemplateArgs = 0;
+ const TemplateArgumentList *TemplateArgs = nullptr;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD);
mangleTemplateArgs(*TemplateArgs);
@@ -1508,7 +1531,7 @@
if (OverloadedTemplateStorage *Overloaded
= Template.getAsOverloadedTemplate()) {
- mangleUnqualifiedName(0, (*Overloaded->begin())->getDeclName(),
+ mangleUnqualifiedName(nullptr, (*Overloaded->begin())->getDeclName(),
UnknownArity);
return;
}
@@ -1550,8 +1573,8 @@
void CXXNameMangler::mangleType(TemplateName TN) {
if (mangleSubstitution(TN))
return;
-
- TemplateDecl *TD = 0;
+
+ TemplateDecl *TD = nullptr;
switch (TN.getKind()) {
case TemplateName::QualifiedTemplate:
@@ -1578,7 +1601,7 @@
// <class-enum-type> ::= <name>
// <name> ::= <nested-name>
- mangleUnresolvedPrefix(Dependent->getQualifier(), 0);
+ mangleUnresolvedPrefix(Dependent->getQualifier(), nullptr);
mangleSourceName(Dependent->getIdentifier());
break;
}
@@ -2150,7 +2173,7 @@
void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
QualType EltType = T->getElementType();
assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType");
- const char *EltName = 0;
+ const char *EltName = nullptr;
if (T->getVectorKind() == VectorType::NeonPolyVector) {
switch (cast<BuiltinType>(EltType)->getKind()) {
case BuiltinType::SChar:
@@ -2183,7 +2206,7 @@
llvm_unreachable("unexpected Neon vector element type");
}
}
- const char *BaseName = 0;
+ const char *BaseName = nullptr;
unsigned BitSize = (T->getNumElements() *
getASTContext().getTypeSize(EltType));
if (BitSize == 64)
@@ -2277,9 +2300,10 @@
llvm::Triple Target = getASTContext().getTargetInfo().getTriple();
llvm::Triple::ArchType Arch =
getASTContext().getTargetInfo().getTriple().getArch();
- if (Arch == llvm::Triple::aarch64 ||
- Arch == llvm::Triple::aarch64_be ||
- (Arch == llvm::Triple::arm64 && !Target.isOSDarwin()))
+ if ((Arch == llvm::Triple::aarch64 ||
+ Arch == llvm::Triple::aarch64_be ||
+ Arch == llvm::Triple::arm64_be ||
+ Arch == llvm::Triple::arm64) && !Target.isOSDarwin())
mangleAArch64NeonVectorType(T);
else
mangleNeonVectorType(T);
@@ -2359,10 +2383,37 @@
}
void CXXNameMangler::mangleType(const DependentNameType *T) {
+ // Proposal by cxx-abi-dev, 2014-03-26
+ // <class-enum-type> ::= <name> # non-dependent or dependent type name or
+ // # dependent elaborated type specifier using
+ // # 'typename'
+ // ::= Ts <name> # dependent elaborated type specifier using
+ // # 'struct' or 'class'
+ // ::= Tu <name> # dependent elaborated type specifier using
+ // # 'union'
+ // ::= Te <name> # dependent elaborated type specifier using
+ // # 'enum'
+ switch (T->getKeyword()) {
+ case ETK_Typename:
+ break;
+ case ETK_Struct:
+ case ETK_Class:
+ case ETK_Interface:
+ Out << "Ts";
+ break;
+ case ETK_Union:
+ Out << "Tu";
+ break;
+ case ETK_Enum:
+ Out << "Te";
+ break;
+ default:
+ llvm_unreachable("unexpected keyword for dependent type name");
+ }
// Typename types are always nested
Out << 'N';
manglePrefix(T->getQualifier());
- mangleSourceName(T->getIdentifier());
+ mangleSourceName(T->getIdentifier());
Out << 'E';
}
@@ -2719,15 +2770,15 @@
case Expr::MemberExprClass: {
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), 0, ME->getMemberDecl()->getDeclName(),
- Arity);
+ ME->getQualifier(), nullptr,
+ ME->getMemberDecl()->getDeclName(), Arity);
break;
}
case Expr::UnresolvedMemberExprClass: {
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), 0, ME->getMemberName(),
+ ME->getQualifier(), nullptr, ME->getMemberName(),
Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
@@ -2747,7 +2798,7 @@
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
- mangleUnresolvedName(ULE->getQualifier(), 0, ULE->getName(), Arity);
+ mangleUnresolvedName(ULE->getQualifier(), nullptr, ULE->getName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
@@ -3010,7 +3061,8 @@
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
- mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity);
+ mangleUnresolvedName(DRE->getQualifier(), nullptr, DRE->getDeclName(),
+ Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
@@ -3365,6 +3417,27 @@
Out << 'T' << (Index - 1) << '_';
}
+void CXXNameMangler::mangleSeqID(unsigned SeqID) {
+ if (SeqID == 1)
+ Out << '0';
+ else if (SeqID > 1) {
+ SeqID--;
+
+ // <seq-id> is encoded in base-36, using digits and upper case letters.
+ char Buffer[7]; // log(2**32) / log(36) ~= 7
+ llvm::MutableArrayRef<char> BufferRef(Buffer);
+ llvm::MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin();
+
+ for (; SeqID != 0; SeqID /= 36) {
+ unsigned C = SeqID % 36;
+ *I++ = (C < 10 ? '0' + C : 'A' + C - 10);
+ }
+
+ Out.write(I.base(), I - BufferRef.rbegin());
+ }
+ Out << '_';
+}
+
void CXXNameMangler::mangleExistingSubstitution(QualType type) {
bool result = mangleSubstitution(type);
assert(result && "no existing substitution for type");
@@ -3421,30 +3494,8 @@
return false;
unsigned SeqID = I->second;
- if (SeqID == 0)
- Out << "S_";
- else {
- SeqID--;
-
- // <seq-id> is encoded in base-36, using digits and upper case letters.
- char Buffer[10];
- char *BufferPtr = llvm::array_endof(Buffer);
-
- if (SeqID == 0) *--BufferPtr = '0';
-
- while (SeqID) {
- assert(BufferPtr > Buffer && "Buffer overflow!");
-
- char c = static_cast<char>(SeqID % 36);
-
- *--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10);
- SeqID /= 36;
- }
-
- Out << 'S'
- << StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr)
- << '_';
- }
+ Out << 'S';
+ mangleSeqID(SeqID);
return true;
}
@@ -3737,12 +3788,15 @@
}
void ItaniumMangleContextImpl::mangleReferenceTemporary(const VarDecl *D,
+ unsigned ManglingNumber,
raw_ostream &Out) {
// We match the GCC mangling here.
// <special-name> ::= GR <object name>
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZGR";
Mangler.mangleName(D);
+ assert(ManglingNumber > 0 && "Reference temporary mangling number is zero!");
+ Mangler.mangleSeqID(ManglingNumber - 1);
}
void ItaniumMangleContextImpl::mangleCXXVTable(const CXXRecordDecl *RD,
diff --git a/lib/AST/MangleNumberingContext.cpp b/lib/AST/MangleNumberingContext.cpp
index b46a085..5f40f03 100644
--- a/lib/AST/MangleNumberingContext.cpp
+++ b/lib/AST/MangleNumberingContext.cpp
@@ -33,13 +33,13 @@
unsigned
MangleNumberingContext::getManglingNumber(const BlockDecl *BD) {
// FIXME: Compute a BlockPointerType? Not obvious how.
- const Type *Ty = 0;
+ const Type *Ty = nullptr;
return ++ManglingNumbers[Ty];
}
unsigned
MangleNumberingContext::getStaticLocalNumber(const VarDecl *VD) {
// FIXME: Compute a BlockPointerType? Not obvious how.
- const Type *Ty = 0;
+ const Type *Ty = nullptr;
return ++ManglingNumbers[Ty];
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 061fc13..d064b15 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -88,7 +88,7 @@
class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
typedef std::pair<const DeclContext *, IdentifierInfo *> DiscriminatorKeyTy;
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
- llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
+ llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier;
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
public:
@@ -97,7 +97,8 @@
bool shouldMangleCXXName(const NamedDecl *D) override;
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
- void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, raw_ostream &) override;
+ void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ raw_ostream &) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
raw_ostream &) override;
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
@@ -109,14 +110,27 @@
void mangleCXXVBTable(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;
- void mangleCXXRTTI(QualType T, raw_ostream &) override;
- void mangleCXXRTTIName(QualType T, raw_ostream &) override;
+ void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
+ void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
+ void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
+ uint32_t NVOffset, int32_t VBPtrOffset,
+ uint32_t VBTableOffset, uint32_t Flags,
+ raw_ostream &Out) override;
+ void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
+ raw_ostream &Out) override;
+ void mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived,
+ raw_ostream &Out) override;
+ void
+ mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
+ ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) override;
void mangleTypeName(QualType T, raw_ostream &) override;
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
raw_ostream &) override;
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
raw_ostream &) override;
- void mangleReferenceTemporary(const VarDecl *, raw_ostream &) override;
+ void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
+ raw_ostream &) override;
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
@@ -181,7 +195,7 @@
BackRefMap NameBackReferences;
bool UseNameBackReferences;
- typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap;
+ typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap;
ArgBackRefMap TypeBackReferences;
ASTContext &getASTContext() const { return Context.getASTContext(); }
@@ -194,19 +208,17 @@
enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_)
- : Context(C), Out(Out_),
- Structor(0), StructorType(-1),
- UseNameBackReferences(true),
- PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
- 64) { }
+ : Context(C), Out(Out_), Structor(nullptr), StructorType(-1),
+ UseNameBackReferences(true),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) {}
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
const CXXDestructorDecl *D, CXXDtorType Type)
- : Context(C), Out(Out_),
- Structor(getStructor(D)), StructorType(Type),
- UseNameBackReferences(true),
- PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
- 64) { }
+ : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
+ UseNameBackReferences(true),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) {}
raw_ostream &getStream() const { return Out; }
@@ -223,7 +235,8 @@
void mangleNumber(int64_t Number);
void mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM = QMM_Mangle);
- void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = 0,
+ void mangleFunctionType(const FunctionType *T,
+ const FunctionDecl *D = nullptr,
bool ForceInstMethod = false);
void mangleNestedName(const NamedDecl *ND);
@@ -237,12 +250,14 @@
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
void mangleCXXDtorType(CXXDtorType T);
void mangleQualifiers(Qualifiers Quals, bool IsMember);
+ void mangleRefQualifier(RefQualifierKind RefQualifier);
void manglePointerCVQualifiers(Qualifiers Quals);
void manglePointerExtQualifiers(Qualifiers Quals, const Type *PointeeType);
void mangleUnscopedTemplateName(const TemplateDecl *ND);
- void mangleTemplateInstantiationName(const TemplateDecl *TD,
- const TemplateArgumentList &TemplateArgs);
+ void
+ mangleTemplateInstantiationName(const TemplateDecl *TD,
+ const TemplateArgumentList &TemplateArgs);
void mangleObjCMethodName(const ObjCMethodDecl *MD);
void mangleArgumentType(QualType T, SourceRange Range);
@@ -332,8 +347,7 @@
// literals.
}
-void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
- StringRef Prefix) {
+void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
// MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
// Therefore it's really important that we don't decorate the
// name with leading underscores or leading/trailing at signs. So, by
@@ -351,10 +365,9 @@
// TODO: Fields? Can MSVC even mangle them?
// Issue a diagnostic for now.
DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this declaration yet");
- Diags.Report(D->getLocation(), DiagID)
- << D->getSourceRange();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error, "cannot mangle this declaration yet");
+ Diags.Report(D->getLocation(), DiagID) << D->getSourceRange();
}
}
@@ -415,7 +428,7 @@
Ty->isMemberPointerType()) {
mangleType(Ty, TL.getSourceRange(), QMM_Drop);
manglePointerExtQualifiers(
- Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), 0);
+ Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), nullptr);
if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) {
mangleQualifiers(MPT->getPointeeType().getQualifiers(), true);
// Member pointers are suffixed with a back reference to the member
@@ -470,6 +483,9 @@
mangleNumber(FieldOffset);
+ // The C++ standard doesn't allow base-to-derived member pointer conversions
+ // in template parameter contexts, so the vbptr offset of data member pointers
+ // is always zero.
if (MSInheritanceAttr::hasVBPtrOffsetField(IM))
mangleNumber(0);
if (MSInheritanceAttr::hasVBTableOffsetField(IM))
@@ -509,6 +525,7 @@
// thunk.
uint64_t NVOffset = 0;
uint64_t VBTableOffset = 0;
+ uint64_t VBPtrOffset = 0;
if (MD->isVirtual()) {
MicrosoftVTableContext *VTContext =
cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
@@ -518,11 +535,8 @@
NVOffset = ML.VFPtrOffset.getQuantity();
VBTableOffset = ML.VBTableIndex * 4;
if (ML.VBase) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(
- DiagnosticsEngine::Error,
- "cannot mangle pointers to member functions from virtual bases");
- Diags.Report(MD->getLocation(), DiagID);
+ const ASTRecordLayout &Layout = getASTContext().getASTRecordLayout(RD);
+ VBPtrOffset = Layout.getVBPtrOffset().getQuantity();
}
} else {
mangleName(MD);
@@ -532,7 +546,7 @@
if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM))
mangleNumber(NVOffset);
if (MSInheritanceAttr::hasVBPtrOffsetField(IM))
- mangleNumber(0);
+ mangleNumber(VBPtrOffset);
if (MSInheritanceAttr::hasVBTableOffsetField(IM))
mangleNumber(VBTableOffset);
}
@@ -599,7 +613,7 @@
static const TemplateDecl *
isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
// Check if we have a function template.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
TemplateArgs = FD->getTemplateSpecializationArgs();
return TD;
@@ -608,7 +622,7 @@
// Check if we have a class template.
if (const ClassTemplateSpecializationDecl *Spec =
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs();
return Spec->getSpecializedTemplate();
}
@@ -620,19 +634,18 @@
return Spec->getSpecializedTemplate();
}
- return 0;
+ return nullptr;
}
-void
-MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
- DeclarationName Name) {
+void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
+ DeclarationName Name) {
// <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name>
// ::= <source-name>
// ::= <template-name>
// Check if we have a template.
- const TemplateArgumentList *TemplateArgs = 0;
+ const TemplateArgumentList *TemplateArgs = nullptr;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
// Function templates aren't considered for name back referencing. This
// makes sense since function templates aren't likely to occur multiple
@@ -791,7 +804,7 @@
case DeclarationName::CXXLiteralOperatorName: {
// FIXME: Was this added in VS2010? Does MS even know how to mangle this?
- DiagnosticsEngine Diags = Context.getDiags();
+ DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this literal operator yet");
Diags.Report(ND->getLocation(), DiagID);
@@ -822,7 +835,7 @@
}
if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
- DiagnosticsEngine Diags = Context.getDiags();
+ DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID =
Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle a local inside this block yet");
@@ -1018,8 +1031,7 @@
}
void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
- const TemplateDecl *TD,
- const TemplateArgumentList &TemplateArgs) {
+ const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) {
// <template-name> ::= <unscoped-template-name> <template-args>
// ::= <substitution>
// Always start with the unqualified name.
@@ -1045,9 +1057,8 @@
mangleUnqualifiedName(TD);
}
-void
-MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
- bool IsBoolean) {
+void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
+ bool IsBoolean) {
// <integer-literal> ::= $0 <number>
Out << "$0";
// Make sure booleans are encoded as 0/1.
@@ -1057,8 +1068,7 @@
mangleNumber(Value.getSExtValue());
}
-void
-MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
+void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
// See if this is a constant expression.
llvm::APSInt Value;
if (E->isIntegerConstantExpr(Value, Context.getASTContext())) {
@@ -1066,7 +1076,7 @@
return;
}
- const CXXUuidofExpr *UE = 0;
+ const CXXUuidofExpr *UE = nullptr;
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
if (UO->getOpcode() == UO_AddrOf)
UE = dyn_cast<CXXUuidofExpr>(UO->getSubExpr());
@@ -1095,10 +1105,10 @@
// As bad as this diagnostic is, it's better than crashing.
DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot yet mangle expression type %0");
- Diags.Report(E->getExprLoc(), DiagID)
- << E->getStmtClassName() << E->getSourceRange();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error, "cannot yet mangle expression type %0");
+ Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName()
+ << E->getSourceRange();
}
void MicrosoftCXXNameMangler::mangleTemplateArgs(
@@ -1156,9 +1166,9 @@
if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
if (MPT->isMemberFunctionPointerType())
- mangleMemberFunctionPointer(RD, 0);
+ mangleMemberFunctionPointer(RD, nullptr);
else
- mangleMemberDataPointer(RD, 0);
+ mangleMemberDataPointer(RD, nullptr);
} else {
Out << "$0A@";
}
@@ -1169,9 +1179,8 @@
break;
case TemplateArgument::Pack:
// Unlike Itanium, there is no character code to indicate an argument pack.
- for (TemplateArgument::pack_iterator I = TA.pack_begin(), E = TA.pack_end();
- I != E; ++I)
- mangleTemplateArg(TD, *I);
+ for (const TemplateArgument &PA : TA.getPackAsArray())
+ mangleTemplateArg(TD, PA);
break;
case TemplateArgument::Template:
mangleType(cast<TagDecl>(
@@ -1263,6 +1272,24 @@
}
void
+MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
+ // <ref-qualifier> ::= G # lvalue reference
+ // ::= H # rvalue-reference
+ switch (RefQualifier) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ Out << 'G';
+ break;
+
+ case RQ_RValue:
+ Out << 'H';
+ break;
+ }
+}
+
+void
MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
const Type *PointeeType) {
bool HasRestrict = Quals.hasRestrict();
@@ -1524,7 +1551,8 @@
// this pointer.
if (IsInstMethod) {
Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals());
- manglePointerExtQualifiers(Quals, 0);
+ manglePointerExtQualifiers(Quals, nullptr);
+ mangleRefQualifier(Proto->getRefQualifier());
mangleQualifiers(Quals, false);
}
@@ -1566,7 +1594,7 @@
Out << 'X';
} else {
// Happens for function pointer type arguments for example.
- for (const auto &Arg : Proto->param_types())
+ for (const QualType Arg : Proto->param_types())
mangleArgumentType(Arg, Range);
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
@@ -1749,7 +1777,7 @@
SmallVector<llvm::APInt, 3> Dimensions;
for (;;) {
if (const ConstantArrayType *CAT =
- getASTContext().getAsConstantArrayType(ElementTy)) {
+ getASTContext().getAsConstantArrayType(ElementTy)) {
Dimensions.push_back(CAT->getSize());
ElementTy = CAT->getElementType();
} else if (ElementTy->isVariableArrayType()) {
@@ -1772,7 +1800,7 @@
<< DSAT->getBracketsRange();
return;
} else if (const IncompleteArrayType *IAT =
- getASTContext().getAsIncompleteArrayType(ElementTy)) {
+ getASTContext().getAsIncompleteArrayType(ElementTy)) {
Dimensions.push_back(llvm::APInt(32, 0));
ElementTy = IAT->getElementType();
}
@@ -1781,8 +1809,8 @@
Out << 'Y';
// <dimension-count> ::= <number> # number of extra dimensions
mangleNumber(Dimensions.size());
- for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim)
- mangleNumber(Dimensions[Dim].getLimitedValue());
+ for (const llvm::APInt &Dimension : Dimensions)
+ mangleNumber(Dimension.getLimitedValue());
mangleType(ElementTy, SourceRange(), QMM_Escape);
}
@@ -1795,7 +1823,7 @@
if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
Out << '8';
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
- mangleFunctionType(FPT, 0, true);
+ mangleFunctionType(FPT, nullptr, true);
} else {
mangleQualifiers(PointeeType.getQualifiers(), true);
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
@@ -2161,7 +2189,8 @@
Mangler.mangleName(MD);
mangleThunkThisAdjustment(MD, Thunk.This, Mangler, Out);
if (!Thunk.Return.isEmpty())
- assert(Thunk.Method != 0 && "Thunk info should hold the overridee decl");
+ assert(Thunk.Method != nullptr &&
+ "Thunk info should hold the overridee decl");
const CXXMethodDecl *DeclForFPT = Thunk.Method ? Thunk.Method : MD;
Mangler.mangleFunctionType(
@@ -2193,11 +2222,8 @@
Mangler.getStream() << "\01??_7";
Mangler.mangleName(Derived);
Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.
- for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(),
- E = BasePath.end();
- I != E; ++I) {
- Mangler.mangleName(*I);
- }
+ for (const CXXRecordDecl *RD : BasePath)
+ Mangler.mangleName(RD);
Mangler.getStream() << '@';
}
@@ -2212,28 +2238,68 @@
Mangler.getStream() << "\01??_8";
Mangler.mangleName(Derived);
Mangler.getStream() << "7B"; // '7' for vbtable, 'B' for const.
- for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(),
- E = BasePath.end();
- I != E; ++I) {
- Mangler.mangleName(*I);
- }
+ for (const CXXRecordDecl *RD : BasePath)
+ Mangler.mangleName(RD);
Mangler.getStream() << '@';
}
-void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &) {
- // FIXME: Give a location...
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle RTTI descriptors for type %0 yet");
- getDiags().Report(DiagID)
- << T.getBaseTypeIdentifier();
+void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R0";
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+ Mangler.getStream() << "@8";
}
-void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, raw_ostream &) {
- // FIXME: Give a location...
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle the name of type %0 into RTTI descriptors yet");
- getDiags().Report(DiagID)
- << T.getBaseTypeIdentifier();
+void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T,
+ raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << '.';
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+}
+
+void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor(
+ const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
+ uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R1";
+ Mangler.mangleNumber(NVOffset);
+ Mangler.mangleNumber(VBPtrOffset);
+ Mangler.mangleNumber(VBTableOffset);
+ Mangler.mangleNumber(Flags);
+ Mangler.mangleName(Derived);
+ Mangler.getStream() << "8";
+}
+
+void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray(
+ const CXXRecordDecl *Derived, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R2";
+ Mangler.mangleName(Derived);
+ Mangler.getStream() << "8";
+}
+
+void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor(
+ const CXXRecordDecl *Derived, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R3";
+ Mangler.mangleName(Derived);
+ Mangler.getStream() << "8";
+}
+
+void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(
+ const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) {
+ // <mangled-name> ::= ?_R4 <class-name> <storage-class>
+ // <cvr-qualifiers> [<name>] @
+ // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
+ // is always '6' for vftables.
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R4";
+ Mangler.mangleName(Derived);
+ Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.
+ for (const CXXRecordDecl *RD : BasePath)
+ Mangler.mangleName(RD);
+ Mangler.getStream() << '@';
}
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
@@ -2259,6 +2325,7 @@
}
void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
+ unsigned,
raw_ostream &) {
unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this reference temporary yet");
diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp
index a862630..986b3b5 100644
--- a/lib/AST/NSAPI.cpp
+++ b/lib/AST/NSAPI.cpp
@@ -14,9 +14,9 @@
using namespace clang;
NSAPI::NSAPI(ASTContext &ctx)
- : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
- NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
-}
+ : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
+ NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
+ NSUTF8StringEncodingId(nullptr) {}
IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
static const char *ClassName[NumClassIds] = {
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index b03c4e0..e4b39b5 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -30,7 +30,7 @@
llvm::FoldingSetNodeID ID;
Mockup.Profile(ID);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
NestedNameSpecifier *NNS
= Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
if (!NNS) {
@@ -61,7 +61,8 @@
const NamespaceDecl *NS) {
assert(NS && "Namespace cannot be NULL");
assert((!Prefix ||
- (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
+ (Prefix->getAsType() == nullptr &&
+ Prefix->getAsIdentifier() == nullptr)) &&
"Broken nested name specifier");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
@@ -76,7 +77,8 @@
NamespaceAliasDecl *Alias) {
assert(Alias && "Namespace alias cannot be NULL");
assert((!Prefix ||
- (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
+ (Prefix->getAsType() == nullptr &&
+ Prefix->getAsIdentifier() == nullptr)) &&
"Broken nested name specifier");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
@@ -101,7 +103,7 @@
NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
assert(II && "Identifier cannot be NULL");
NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(0);
+ Mockup.Prefix.setPointer(nullptr);
Mockup.Prefix.setInt(StoredIdentifier);
Mockup.Specifier = II;
return FindOrInsert(Context, Mockup);
@@ -117,7 +119,7 @@
}
NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
- if (Specifier == 0)
+ if (!Specifier)
return Global;
switch (Prefix.getInt()) {
@@ -144,7 +146,7 @@
if (Prefix.getInt() == StoredNamespaceOrAlias)
return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
- return 0;
+ return nullptr;
}
/// \brief Retrieve the namespace alias stored in this nested name
@@ -153,7 +155,7 @@
if (Prefix.getInt() == StoredNamespaceOrAlias)
return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
- return 0;
+ return nullptr;
}
@@ -437,7 +439,7 @@
NestedNameSpecifierLocBuilder::
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
- : Representation(Other.Representation), Buffer(0),
+ : Representation(Other.Representation), Buffer(nullptr),
BufferSize(0), BufferCapacity(0)
{
if (!Other.Buffer)
@@ -477,7 +479,7 @@
if (!Other.Buffer) {
// Empty.
- Buffer = 0;
+ Buffer = nullptr;
BufferSize = 0;
return *this;
}
@@ -599,7 +601,7 @@
free(Buffer);
if (!Other) {
- Representation = 0;
+ Representation = nullptr;
BufferSize = 0;
return;
}
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index ff44d93..a991302 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -37,7 +37,7 @@
// If we are rebuilding the map, clear out any existing state.
if (M[POE->getSyntacticForm()])
for (Stmt::child_range I = S->children(); I; ++I)
- M[*I] = 0;
+ M[*I] = nullptr;
M[POE->getSyntacticForm()] = S;
BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
@@ -92,7 +92,7 @@
}
}
-ParentMap::ParentMap(Stmt* S) : Impl(0) {
+ParentMap::ParentMap(Stmt *S) : Impl(nullptr) {
if (S) {
MapTy *M = new MapTy();
BuildParentMap(*M, S);
@@ -120,7 +120,7 @@
Stmt* ParentMap::getParent(Stmt* S) const {
MapTy* M = (MapTy*) Impl;
MapTy::iterator I = M->find(S);
- return I == M->end() ? 0 : I->second;
+ return I == M->end() ? nullptr : I->second;
}
Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
@@ -146,7 +146,7 @@
}
Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
- Stmt *Paren = 0;
+ Stmt *Paren = nullptr;
while (isa<ParenExpr>(S)) {
Paren = S;
S = getParent(S);
diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp
index 9d46cc6..b2c244e 100644
--- a/lib/AST/RecordLayout.cpp
+++ b/lib/AST/RecordLayout.cpp
@@ -21,8 +21,8 @@
if (FieldOffsets)
Ctx.Deallocate(FieldOffsets);
if (CXXInfo) {
- Ctx.Deallocate(CXXInfo);
CXXInfo->~CXXRecordLayoutInfo();
+ Ctx.Deallocate(CXXInfo);
}
this->~ASTRecordLayout();
Ctx.Deallocate(this);
@@ -35,8 +35,8 @@
const uint64_t *fieldoffsets,
unsigned fieldcount)
: Size(size), DataSize(datasize), Alignment(alignment),
- RequiredAlignment(requiredAlignment), FieldOffsets(0),
- FieldCount(fieldcount), CXXInfo(0) {
+ RequiredAlignment(requiredAlignment), FieldOffsets(nullptr),
+ FieldCount(fieldcount), CXXInfo(nullptr) {
if (FieldCount > 0) {
FieldOffsets = new (Ctx) uint64_t[FieldCount];
memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets));
@@ -63,7 +63,7 @@
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets)
: Size(size), DataSize(datasize), Alignment(alignment),
- RequiredAlignment(requiredAlignment), FieldOffsets(0),
+ RequiredAlignment(requiredAlignment), FieldOffsets(nullptr),
FieldCount(fieldcount), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
{
if (FieldCount > 0) {
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index ce55d2e..db64f31 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -65,7 +65,7 @@
const CXXRecordDecl *Class;
/// EmptyClassOffsets - A map from offsets to empty record decls.
- typedef SmallVector<const CXXRecordDecl *, 1> ClassVectorTy;
+ typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
EmptyClassOffsetsMapTy EmptyClassOffsets;
@@ -141,8 +141,7 @@
void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
// Check the bases.
for (const auto &I : Class->bases()) {
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
CharUnits EmptySize;
const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
@@ -168,7 +167,7 @@
continue;
CharUnits EmptySize;
- const CXXRecordDecl *MemberDecl = cast<CXXRecordDecl>(RT->getDecl());
+ const CXXRecordDecl *MemberDecl = RT->getAsCXXRecordDecl();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl);
if (MemberDecl->isEmpty()) {
// If the class decl is empty, get its size.
@@ -349,8 +348,7 @@
if (I.isVirtual())
continue;
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
@@ -360,9 +358,8 @@
if (RD == Class) {
// This is the most derived class, traverse virtual bases as well.
for (const auto &I : RD->vbases()) {
- const CXXRecordDecl *VBaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
-
+ const CXXRecordDecl *VBaseDecl = I.getType()->getAsCXXRecordDecl();
+
CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
return false;
@@ -394,10 +391,8 @@
return true;
QualType T = FD->getType();
- if (const RecordType *RT = T->getAs<RecordType>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
- }
// If we have an array type we need to look at every element.
if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
@@ -405,8 +400,8 @@
const RecordType *RT = ElemTy->getAs<RecordType>();
if (!RT)
return true;
-
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
uint64_t NumElements = Context.getConstantArrayElementCount(AT);
@@ -459,8 +454,7 @@
if (I.isVirtual())
continue;
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset);
@@ -469,9 +463,8 @@
if (RD == Class) {
// This is the most derived class, traverse virtual bases as well.
for (const auto &I : RD->vbases()) {
- const CXXRecordDecl *VBaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
-
+ const CXXRecordDecl *VBaseDecl = I.getType()->getAsCXXRecordDecl();
+
CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
}
@@ -493,8 +486,7 @@
void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD,
CharUnits Offset) {
QualType T = FD->getType();
- if (const RecordType *RT = T->getAs<RecordType>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
UpdateEmptyFieldSubobjects(RD, RD, Offset);
return;
}
@@ -505,8 +497,8 @@
const RecordType *RT = ElemTy->getAs<RecordType>();
if (!RT)
return;
-
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
uint64_t NumElements = Context.getConstantArrayElementCount(AT);
@@ -642,9 +634,9 @@
MaxFieldAlignment(CharUnits::Zero()),
DataSize(0), NonVirtualSize(CharUnits::Zero()),
NonVirtualAlignment(CharUnits::One()),
- PrimaryBase(0), PrimaryBaseIsVirtual(false),
+ PrimaryBase(nullptr), PrimaryBaseIsVirtual(false),
HasOwnVFPtr(false),
- FirstNearlyEmptyVBase(0) { }
+ FirstNearlyEmptyVBase(nullptr) {}
/// Reset this RecordLayoutBuilder to a fresh state, using the given
/// alignment as the initial alignment. This is used for the
@@ -780,8 +772,7 @@
assert(!I.getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
// Check if this is a nearly empty virtual base.
if (I.isVirtual() && Context.isNearlyEmpty(Base)) {
@@ -822,8 +813,7 @@
if (I.isVirtual())
continue;
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
if (Base->isDynamicClass()) {
// We found it.
@@ -876,11 +866,11 @@
Info->Class = RD;
Info->IsVirtual = IsVirtual;
- Info->Derived = 0;
- Info->PrimaryVirtualBaseInfo = 0;
-
- const CXXRecordDecl *PrimaryVirtualBase = 0;
- BaseSubobjectInfo *PrimaryVirtualBaseInfo = 0;
+ Info->Derived = nullptr;
+ Info->PrimaryVirtualBaseInfo = nullptr;
+
+ const CXXRecordDecl *PrimaryVirtualBase = nullptr;
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = nullptr;
// Check if this base has a primary virtual base.
if (RD->getNumVBases()) {
@@ -897,8 +887,8 @@
if (PrimaryVirtualBaseInfo->Derived) {
// We did have info about this primary base, and it turns out that it
// has already been claimed as a primary virtual base for another
- // base.
- PrimaryVirtualBase = 0;
+ // base.
+ PrimaryVirtualBase = nullptr;
} else {
// We can claim this base as our primary base.
Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
@@ -911,10 +901,9 @@
// Now go through all direct bases.
for (const auto &I : RD->bases()) {
bool IsVirtual = I.isVirtual();
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
-
+
+ const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
+
Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
}
@@ -937,11 +926,11 @@
for (const auto &I : RD->bases()) {
bool IsVirtual = I.isVirtual();
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
-
+ const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
+
// Compute the base subobject info for this base.
- BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, 0);
+ BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
+ nullptr);
if (IsVirtual) {
// ComputeBaseInfo has already added this base for us.
@@ -988,8 +977,8 @@
// If the primary virtual base was a primary virtual base of some other
// base class we'll have to steal it.
BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
- PrimaryBaseInfo->Derived = 0;
-
+ PrimaryBaseInfo->Derived = nullptr;
+
// We have a virtual primary base, insert it as an indirect primary base.
IndirectPrimaryBases.insert(PrimaryBase);
@@ -1315,16 +1304,14 @@
if (I.isVirtual())
continue;
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
assert(Bases.count(BaseDecl) && "Did not find base offset!");
}
// And all virtual bases.
for (const auto &I : RD->vbases()) {
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
assert(VBases.count(BaseDecl) && "Did not find base offset!");
}
@@ -1949,13 +1936,13 @@
const CXXRecordDecl *RD) {
// If a class isn't polymorphic it doesn't have a key function.
if (!RD->isPolymorphic())
- return 0;
+ return nullptr;
// A class that is not externally visible doesn't have a key function. (Or
// at least, there's no point to assigning a key function to such a class;
// this doesn't affect the ABI.)
if (!RD->isExternallyVisible())
- return 0;
+ return nullptr;
// Template instantiations don't have key functions per Itanium C++ ABI 5.2.6.
// Same behavior as GCC.
@@ -1963,7 +1950,7 @@
if (TSK == TSK_ImplicitInstantiation ||
TSK == TSK_ExplicitInstantiationDeclaration ||
TSK == TSK_ExplicitInstantiationDefinition)
- return 0;
+ return nullptr;
bool allowInlineFunctions =
Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline();
@@ -2001,7 +1988,7 @@
return MD;
}
- return 0;
+ return nullptr;
}
DiagnosticBuilder
@@ -2056,7 +2043,7 @@
}
// This section contains an implementation of struct layout that is, up to the
-// included tests, compatible with cl.exe (2012). The layout produced is
+// included tests, compatible with cl.exe (2013). The layout produced is
// significantly different than those produced by the Itanium ABI. Here we note
// the most important differences.
//
@@ -2064,52 +2051,86 @@
// alignment of the union.
// * The existence of zero-width bitfield that occurs after anything other than
// a non-zero length bitfield is ignored.
+// * There is no explicit primary base for the purposes of layout. All bases
+// with vfptrs are laid out first, followed by all bases without vfptrs.
// * The Itanium equivalent vtable pointers are split into a vfptr (virtual
// function pointer) and a vbptr (virtual base pointer). They can each be
// shared with a, non-virtual bases. These bases need not be the same. vfptrs
-// always occur at offset 0. vbptrs can occur at an
-// arbitrary offset and are placed after non-virtual bases but before fields.
+// always occur at offset 0. vbptrs can occur at an arbitrary offset and are
+// placed after the lexiographically last non-virtual base. This placement
+// is always before fields but can be in the middle of the non-virtual bases
+// due to the two-pass layout scheme for non-virtual-bases.
// * Virtual bases sometimes require a 'vtordisp' field that is laid out before
// the virtual base and is used in conjunction with virtual overrides during
-// construction and destruction.
-// * vfptrs are allocated in a block of memory equal to the alignment of the
-// fields and non-virtual bases at offset 0 in 32 bit mode and in a pointer
-// sized block of memory in 64 bit mode.
-// * vbptrs are allocated in a block of memory equal to the alignment of the
-// fields and non-virtual bases. This block is at a potentially unaligned
-// offset. If the allocation slot is unaligned and the alignment is less than
-// or equal to the pointer size, additional space is allocated so that the
-// pointer can be aligned properly. This causes very strange effects on the
-// placement of objects after the allocated block. (see the code).
+// construction and destruction. This is always a 4 byte value and is used as
+// an alternative to constructor vtables.
// * vtordisps are allocated in a block of memory with size and alignment equal
// to the alignment of the completed structure (before applying __declspec(
// align())). The vtordisp always occur at the end of the allocation block,
// immediately prior to the virtual base.
-// * The last zero sized non-virtual base is allocated after the placement of
-// vbptr if one exists and can be placed at the end of the struct, potentially
-// aliasing either the first member or another struct allocated after this
-// one.
-// * The last zero size virtual base may be placed at the end of the struct.
-// and can potentially alias a zero sized type in the next struct.
-// * If the last field is a non-zero length bitfield, all virtual bases will
-// have extra padding added before them for no obvious reason. The padding
-// has the same number of bits as the type of the bitfield.
-// * When laying out empty non-virtual bases, an extra byte of padding is added
-// if the non-virtual base before the empty non-virtual base has a vbptr.
+// * vfptrs are injected after all bases and fields have been laid out. In
+// order to guarantee proper alignment of all fields, the vfptr injection
+// pushes all bases and fields back by the alignment imposed by those bases
+// and fields. This can potentially add a significant amount of padding.
+// vfptrs are always injected at offset 0.
+// * vbptrs are injected after all bases and fields have been laid out. In
+// order to guarantee proper alignment of all fields, the vfptr injection
+// pushes all bases and fields back by the alignment imposed by those bases
+// and fields. This can potentially add a significant amount of padding.
+// vbptrs are injected immediately after the last non-virtual base as
+// lexiographically ordered in the code. If this site isn't pointer aligned
+// the vbptr is placed at the next properly aligned location. Enough padding
+// is added to guarantee a fit.
+// * The last zero sized non-virtual base can be placed at the end of the
+// struct (potentially aliasing another object), or may alias with the first
+// field, even if they are of the same type.
+// * The last zero size virtual base may be placed at the end of the struct
+// potentially aliasing another object.
// * The ABI attempts to avoid aliasing of zero sized bases by adding padding
// between bases or vbases with specific properties. The criteria for
// additional padding between two bases is that the first base is zero sized
-// or has a zero sized subobject and the second base is zero sized or leads
-// with a zero sized base (sharing of vfptrs can reorder the layout of the
-// so the leading base is not always the first one declared). The padding
-// added for bases is 1 byte. The padding added for vbases depends on the
-// alignment of the object but is at least 4 bytes (in both 32 and 64 bit
-// modes).
-// * There is no concept of non-virtual alignment or any distinction between
-// data size and non-virtual size.
+// or ends with a zero sized subobject and the second base is zero sized or
+// trails with a zero sized base or field (sharing of vfptrs can reorder the
+// layout of the so the leading base is not always the first one declared).
+// This rule does take into account fields that are not records, so padding
+// will occur even if the last field is, e.g. an int. The padding added for
+// bases is 1 byte. The padding added between vbases depends on the alignment
+// of the object but is at least 4 bytes (in both 32 and 64 bit modes).
+// * There is no concept of non-virtual alignment, non-virtual alignment and
+// alignment are always identical.
+// * There is a distinction between alignment and required alignment.
+// __declspec(align) changes the required alignment of a struct. This
+// alignment is _always_ obeyed, even in the presence of #pragma pack. A
+// record inherites required alignment from all of its fields an bases.
// * __declspec(align) on bitfields has the effect of changing the bitfield's
-// alignment instead of its required alignment. This has implications on how
-// it interacts with pragam pack.
+// alignment instead of its required alignment. This is the only known way
+// to make the alignment of a struct bigger than 8. Interestingly enough
+// this alignment is also immune to the effects of #pragma pack and can be
+// used to create structures with large alignment under #pragma pack.
+// However, because it does not impact required alignment, such a structure,
+// when used as a field or base, will not be aligned if #pragma pack is
+// still active at the time of use.
+//
+// Known incompatibilities:
+// * all: #pragma pack between fields in a record
+// * 2010 and back: If the last field in a record is a bitfield, every object
+// laid out after the record will have extra padding inserted before it. The
+// extra padding will have size equal to the size of the storage class of the
+// bitfield. 0 sized bitfields don't exhibit this behavior and the extra
+// padding can be avoided by adding a 0 sized bitfield after the non-zero-
+// sized bitfield.
+// * 2012 and back: In 64-bit mode, if the alignment of a record is 16 or
+// greater due to __declspec(align()) then a second layout phase occurs after
+// The locations of the vf and vb pointers are known. This layout phase
+// suffers from the "last field is a bitfield" bug in 2010 and results in
+// _every_ field getting padding put in front of it, potentially including the
+// vfptr, leaving the vfprt at a non-zero location which results in a fault if
+// anything tries to read the vftbl. The second layout phase also treats
+// bitfields as separate entities and gives them each storage rather than
+// packing them. Additionally, because this phase appears to perform a
+// (an unstable) sort on the members before laying them out and because merged
+// bitfields have the same address, the bitfields end up in whatever order
+// the sort left them in, a behavior we could never hope to replicate.
namespace {
struct MicrosoftRecordLayoutBuilder {
@@ -2150,8 +2171,7 @@
void finalizeLayout(const RecordDecl *RD);
/// \brief Gets the size and alignment of a base taking pragma pack and
/// __declspec(align) into account.
- ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout,
- bool AsBase = true);
+ ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout);
/// \brief Gets the size and alignment of a field taking pragma pack and
/// __declspec(align) into account. It also updates RequiredAlignment as a
/// side effect because it is most convenient to do so here.
@@ -2211,11 +2231,10 @@
bool HasOwnVFPtr : 1;
/// \brief True if the class has a vbtable pointer.
bool HasVBPtr : 1;
- /// \brief Lets us know if we're in 64-bit mode
- bool Is64BitMode : 1;
- /// \brief True if this class contains a zero sized member or base or a base
- /// with a zero sized member or base. Only used for MS-ABI.
- bool HasZeroSizedSubObject : 1;
+ /// \brief True if the last sub-object within the type is zero sized or the
+ /// object itself is zero sized. This *does not* count members that are not
+ /// records. Only used for MS-ABI.
+ bool EndsWithZeroSizedObject : 1;
/// \brief True if this class is zero sized or first base is zero sized or
/// has this property. Only used for MS-ABI.
bool LeadsWithZeroSizedBase : 1;
@@ -2224,21 +2243,21 @@
MicrosoftRecordLayoutBuilder::ElementInfo
MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
- const ASTRecordLayout &Layout, bool AsBase) {
+ const ASTRecordLayout &Layout) {
ElementInfo Info;
Info.Alignment = Layout.getAlignment();
// Respect pragma pack.
if (!MaxFieldAlignment.isZero())
Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
// Track zero-sized subobjects here where it's already available.
- if (Layout.hasZeroSizedSubObject())
- HasZeroSizedSubObject = true;
+ EndsWithZeroSizedObject = Layout.hasZeroSizedSubObject();
// Respect required alignment, this is necessary because we may have adjusted
// the alignment in the case of pragam pack. Note that the required alignment
// doesn't actually apply to the struct alignment at this point.
Alignment = std::max(Alignment, Info.Alignment);
+ RequiredAlignment = std::max(RequiredAlignment, Layout.getRequiredAlignment());
Info.Alignment = std::max(Info.Alignment, Layout.getRequiredAlignment());
- Info.Size = AsBase ? Layout.getNonVirtualSize() : Layout.getSize();
+ Info.Size = Layout.getNonVirtualSize();
return Info;
}
@@ -2252,37 +2271,27 @@
CharUnits FieldRequiredAlignment =
Context.toCharUnitsFromBits(FD->getMaxAlignment());
// Respect attributes applied to subobjects of the field.
- if (const RecordType *RT =
- FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RT->getDecl());
- // Get the element info for a layout, respecting pack.
- Info.Alignment = getAdjustedElementInfo(Layout, false).Alignment;
- // Capture required alignment as a side-effect.
- RequiredAlignment = std::max(RequiredAlignment,
- Layout.getRequiredAlignment());
- } else {
- if (FD->isBitField() && FD->getMaxAlignment() != 0)
- Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
- // Respect pragma pack.
- if (!MaxFieldAlignment.isZero())
- Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
- }
- // Respect packed field attribute.
- if (FD->hasAttr<PackedAttr>())
- Info.Alignment = CharUnits::One();
- // Take required alignment into account. __declspec(align) on bitfields
- // impacts the alignment rather than the required alignment.
- if (!FD->isBitField()) {
+ if (FD->isBitField())
+ // For some reason __declspec align impacts alignment rather than required
+ // alignment when it is applied to bitfields.
Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
+ else {
+ if (auto RT =
+ FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
+ auto const &Layout = Context.getASTRecordLayout(RT->getDecl());
+ EndsWithZeroSizedObject = Layout.hasZeroSizedSubObject();
+ FieldRequiredAlignment = std::max(FieldRequiredAlignment,
+ Layout.getRequiredAlignment());
+ }
// Capture required alignment as a side-effect.
RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
}
- // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
- if (!(FD->isBitField() && IsUnion)) {
- Alignment = std::max(Alignment, Info.Alignment);
- if (!MaxFieldAlignment.isZero())
- Alignment = std::min(Alignment, MaxFieldAlignment);
- }
+ // Respect pragma pack, attribute pack and declspec align
+ if (!MaxFieldAlignment.isZero())
+ Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
+ if (FD->hasAttr<PackedAttr>())
+ Info.Alignment = CharUnits::One();
+ Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
return Info;
}
@@ -2304,7 +2313,10 @@
injectVFPtr(RD);
if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
Alignment = std::max(Alignment, PointerInfo.Alignment);
- NonVirtualSize = Size = Size.RoundUpToAlignment(Alignment);
+ auto RoundingAlignment = Alignment;
+ if (!MaxFieldAlignment.isZero())
+ RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
+ NonVirtualSize = Size = Size.RoundUpToAlignment(RoundingAlignment);
RequiredAlignment = std::max(
RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
layoutVirtualBases(RD);
@@ -2313,13 +2325,13 @@
void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
IsUnion = RD->isUnion();
- Is64BitMode = Context.getTargetInfo().getPointerWidth(0) == 64;
Size = CharUnits::Zero();
Alignment = CharUnits::One();
// In 64-bit mode we always perform an alignment step after laying out vbases.
// In 32-bit mode we do not. The check to see if we need to perform alignment
// checks the RequiredAlignment field and performs alignment if it isn't 0.
- RequiredAlignment = Is64BitMode ? CharUnits::One() : CharUnits::Zero();
+ RequiredAlignment = Context.getTargetInfo().getPointerWidth(0) == 64 ?
+ CharUnits::One() : CharUnits::Zero();
// Compute the maximum field alignment.
MaxFieldAlignment = CharUnits::Zero();
// Honor the default struct packing maximum alignment flag.
@@ -2339,12 +2351,12 @@
void
MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {
- HasZeroSizedSubObject = false;
+ EndsWithZeroSizedObject = false;
LeadsWithZeroSizedBase = false;
HasOwnVFPtr = false;
HasVBPtr = false;
- PrimaryBase = 0;
- SharedVBPtrBase = 0;
+ PrimaryBase = nullptr;
+ SharedVBPtrBase = nullptr;
// Calculate pointer size and alignment. These are used for vfptr and vbprt
// injection.
PointerInfo.Size =
@@ -2363,7 +2375,7 @@
// first. We use these passes to calculate some additional aggregated
// information about the bases, such as reqruied alignment and the presence of
// zero sized members.
- const ASTRecordLayout* PreviousBaseLayout = 0;
+ const ASTRecordLayout *PreviousBaseLayout = nullptr;
// Iterate through the bases and lay out the non-virtual ones.
for (const auto &I : RD->bases()) {
const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
@@ -2373,9 +2385,6 @@
HasVBPtr = true;
continue;
}
- // Track RequiredAlignment for all bases in this pass.
- RequiredAlignment = std::max(RequiredAlignment,
- BaseLayout.getRequiredAlignment());
// Check fo a base to share a VBPtr with.
if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) {
SharedVBPtrBase = BaseDecl;
@@ -2408,8 +2417,10 @@
const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
// Only lay out bases without extendable VFPtrs on the second pass.
- if (BaseLayout.hasExtendableVFPtr())
+ if (BaseLayout.hasExtendableVFPtr()) {
+ VBPtrOffset = Bases[BaseDecl] + BaseLayout.getNonVirtualSize();
continue;
+ }
// If this is the first layout, check to see if it leads with a zero sized
// object. If it does, so do we.
if (CheckLeadingLayout) {
@@ -2418,6 +2429,7 @@
}
// Lay out the base.
layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout);
+ VBPtrOffset = Bases[BaseDecl] + BaseLayout.getNonVirtualSize();
}
// Set our VBPtroffset if we know it at this point.
if (!HasVBPtr)
@@ -2443,7 +2455,6 @@
Bases.insert(std::make_pair(BaseDecl, BaseOffset));
Size = BaseOffset + BaseLayout.getNonVirtualSize();
PreviousBaseLayout = &BaseLayout;
- VBPtrOffset = Size;
}
void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) {
@@ -2459,6 +2470,7 @@
}
LastFieldIsNonZeroWidthBitfield = false;
ElementInfo Info = getAdjustedElementInfo(FD);
+ Alignment = std::max(Alignment, Info.Alignment);
if (IsUnion) {
placeFieldAtOffset(CharUnits::Zero());
Size = std::max(Size, Info.Size);
@@ -2494,11 +2506,13 @@
if (IsUnion) {
placeFieldAtOffset(CharUnits::Zero());
Size = std::max(Size, Info.Size);
+ // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
} else {
// Allocate a new block of memory and place the bitfield in it.
CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment);
placeFieldAtOffset(FieldOffset);
Size = FieldOffset + Info.Size;
+ Alignment = std::max(Alignment, Info.Alignment);
RemainingBitsInField = Context.toBits(Info.Size) - Width;
}
}
@@ -2518,11 +2532,13 @@
if (IsUnion) {
placeFieldAtOffset(CharUnits::Zero());
Size = std::max(Size, Info.Size);
+ // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
} else {
// Round up the current record size to the field's alignment boundary.
CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment);
placeFieldAtOffset(FieldOffset);
Size = FieldOffset;
+ Alignment = std::max(Alignment, Info.Alignment);
}
}
@@ -2548,8 +2564,8 @@
*i += Context.toBits(Offset);
for (BaseOffsetsMapTy::iterator i = Bases.begin(), e = Bases.end();
i != e; ++i)
- if (i->second >= InjectionSite)
- i->second += Offset;
+ if (i->second >= InjectionSite)
+ i->second += Offset;
}
void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {
@@ -2596,28 +2612,20 @@
llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet =
computeVtorDispSet(RD);
// Iterate through the virtual bases and lay them out.
- const ASTRecordLayout* PreviousBaseLayout = 0;
+ const ASTRecordLayout *PreviousBaseLayout = nullptr;
for (const auto &I : RD->vbases()) {
const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
bool HasVtordisp = HasVtordispSet.count(BaseDecl);
- // If the last field we laid out was a non-zero length bitfield then add
- // some extra padding for no obvious reason.
- if (LastFieldIsNonZeroWidthBitfield)
- Size += CurrentBitfieldSize;
// Insert padding between two bases if the left first one is zero sized or
// contains a zero sized subobject and the right is zero sized or one leads
// with a zero sized base. The padding between virtual bases is 4
// bytes (in both 32 and 64 bits modes) and always involves rounding up to
// the required alignment, we don't know why.
- if (PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() &&
- BaseLayout.leadsWithZeroSizedBase())
- Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize;
- // Insert the vtordisp.
- if (HasVtordisp)
+ if ((PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() &&
+ BaseLayout.leadsWithZeroSizedBase()) || HasVtordisp)
Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize;
// Insert the virtual base.
- HasZeroSizedSubObject = false;
ElementInfo Info = getAdjustedElementInfo(BaseLayout);
CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
VBases.insert(std::make_pair(BaseDecl,
@@ -2633,28 +2641,34 @@
DataSize = Size;
if (!RequiredAlignment.isZero()) {
Alignment = std::max(Alignment, RequiredAlignment);
- Size = Size.RoundUpToAlignment(Alignment);
+ auto RoundingAlignment = Alignment;
+ if (!MaxFieldAlignment.isZero())
+ RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
+ RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
+ Size = Size.RoundUpToAlignment(RoundingAlignment);
}
// Zero-sized structures have size equal to their alignment.
if (Size.isZero()) {
- HasZeroSizedSubObject = true;
+ EndsWithZeroSizedObject = true;
LeadsWithZeroSizedBase = true;
Size = Alignment;
}
}
-static bool
-RequiresVtordisp(const llvm::SmallPtrSet<const CXXRecordDecl *, 2> &HasVtordisp,
- const CXXRecordDecl *RD) {
- if (HasVtordisp.count(RD))
+// Recursively walks the non-virtual bases of a class and determines if any of
+// them are in the bases with overridden methods set.
+static bool RequiresVtordisp(
+ const llvm::SmallPtrSet<const CXXRecordDecl *, 2> &
+ BasesWithOverriddenMethods,
+ const CXXRecordDecl *RD) {
+ if (BasesWithOverriddenMethods.count(RD))
return true;
// If any of a virtual bases non-virtual bases (recursively) requires a
// vtordisp than so does this virtual base.
for (const auto &I : RD->bases())
if (!I.isVirtual() &&
- RequiresVtordisp(
- HasVtordisp,
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl())))
+ RequiresVtordisp(BasesWithOverriddenMethods,
+ I.getType()->getAsCXXRecordDecl()))
return true;
return false;
}
@@ -2663,10 +2677,6 @@
MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) {
llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet;
- // /vd0 or #pragma vtordisp(0): Never use vtordisps when used as a vbase.
- if (RD->getMSVtorDispMode() == MSVtorDispAttr::Never)
- return HasVtordispSet;
-
// /vd2 or #pragma vtordisp(2): Always use vtordisps for virtual bases with
// vftables.
if (RD->getMSVtorDispMode() == MSVtorDispAttr::ForVFTable) {
@@ -2679,56 +2689,53 @@
return HasVtordispSet;
}
+ // If any of our bases need a vtordisp for this type, so do we. Check our
+ // direct bases for vtordisp requirements.
+ for (const auto &I : RD->bases()) {
+ const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
+ for (const auto &bi : Layout.getVBaseOffsetsMap())
+ if (bi.second.hasVtorDisp())
+ HasVtordispSet.insert(bi.first);
+ }
+ // We don't introduce any additional vtordisps if either:
+ // * A user declared constructor or destructor aren't declared.
+ // * #pragma vtordisp(0) or the /vd0 flag are in use.
+ if ((!RD->hasUserDeclaredConstructor() && !RD->hasUserDeclaredDestructor()) ||
+ RD->getMSVtorDispMode() == MSVtorDispAttr::Never)
+ return HasVtordispSet;
// /vd1 or #pragma vtordisp(1): Try to guess based on whether we think it's
// possible for a partially constructed object with virtual base overrides to
// escape a non-trivial constructor.
assert(RD->getMSVtorDispMode() == MSVtorDispAttr::ForVBaseOverride);
-
- // If any of our bases need a vtordisp for this type, so do we. Check our
- // direct bases for vtordisp requirements.
- for (const auto &I : RD->bases()) {
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
- for (ASTRecordLayout::VBaseOffsetsMapTy::const_iterator
- bi = Layout.getVBaseOffsetsMap().begin(),
- be = Layout.getVBaseOffsetsMap().end();
- bi != be; ++bi)
- if (bi->second.hasVtorDisp())
- HasVtordispSet.insert(bi->first);
+ // Compute a set of base classes which define methods we override. A virtual
+ // base in this set will require a vtordisp. A virtual base that transitively
+ // contains one of these bases as a non-virtual base will also require a
+ // vtordisp.
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
+ // Seed the working set with our non-destructor virtual methods.
+ for (const auto *I : RD->methods())
+ if (I->isVirtual() && !isa<CXXDestructorDecl>(I))
+ Work.insert(I);
+ while (!Work.empty()) {
+ const CXXMethodDecl *MD = *Work.begin();
+ CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),
+ e = MD->end_overridden_methods();
+ // If a virtual method has no-overrides it lives in its parent's vtable.
+ if (i == e)
+ BasesWithOverriddenMethods.insert(MD->getParent());
+ else
+ Work.insert(i, e);
+ // We've finished processing this element, remove it from the working set.
+ Work.erase(MD);
}
- // If we define a constructor or destructor and override a function that is
- // defined in a virtual base's vtable, that virtual bases need a vtordisp.
- // Here we collect a list of classes with vtables for which our virtual bases
- // actually live. The virtual bases with this property will require
- // vtordisps. In addition, virtual bases that contain non-virtual bases that
- // define functions we override also require vtordisps, this case is checked
- // explicitly below.
- if (RD->hasUserDeclaredConstructor() || RD->hasUserDeclaredDestructor()) {
- llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
- // Seed the working set with our non-destructor virtual methods.
- for (const auto *I : RD->methods())
- if (I->isVirtual() && !isa<CXXDestructorDecl>(I))
- Work.insert(I);
- while (!Work.empty()) {
- const CXXMethodDecl *MD = *Work.begin();
- CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),
- e = MD->end_overridden_methods();
- if (i == e)
- // If a virtual method has no-overrides it lives in its parent's vtable.
- HasVtordispSet.insert(MD->getParent());
- else
- Work.insert(i, e);
- // We've finished processing this element, remove it from the working set.
- Work.erase(MD);
- }
- }
- // Re-check all of our vbases for vtordisp requirements (in case their
- // non-virtual bases have vtordisp requirements).
+ // For each of our virtual bases, check if it is in the set of overridden
+ // bases or if it transitively contains a non-virtual base that is.
for (const auto &I : RD->vbases()) {
const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
if (!HasVtordispSet.count(BaseDecl) &&
- RequiresVtordisp(HasVtordispSet, BaseDecl))
+ RequiresVtordisp(BasesWithOverriddenMethods, BaseDecl))
HasVtordispSet.insert(BaseDecl);
}
return HasVtordispSet;
@@ -2750,7 +2757,7 @@
Builder.FieldOffsets.size(), Builder.NonVirtualSize,
Builder.Alignment, CharUnits::Zero(), Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
- Builder.HasZeroSizedSubObject, Builder.LeadsWithZeroSizedBase,
+ Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
Builder.Bases, Builder.VBases);
} else {
Builder.layout(D);
@@ -2784,7 +2791,7 @@
const ASTRecordLayout *Entry = ASTRecordLayouts[D];
if (Entry) return *Entry;
- const ASTRecordLayout *NewEntry = 0;
+ const ASTRecordLayout *NewEntry = nullptr;
if (isMsLayout(D) && !D->getASTContext().getExternalSource()) {
NewEntry = BuildMicrosoftASTRecordLayout(D);
@@ -2820,10 +2827,10 @@
EmptySubobjects.SizeOfLargestEmptySubobject,
Builder.PrimaryBase,
Builder.PrimaryBaseIsVirtual,
- 0, false, false,
+ nullptr, false, false,
Builder.Bases, Builder.VBases);
} else {
- RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
+ RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
Builder.Layout(D);
NewEntry =
@@ -2848,7 +2855,7 @@
const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) {
if (!getTargetInfo().getCXXABI().hasKeyFunctions())
- return 0;
+ return nullptr;
assert(RD->getDefinition() && "Cannot get key function for forward decl!");
RD = cast<CXXRecordDecl>(RD->getDefinition());
@@ -2929,10 +2936,10 @@
// entries later; however we shouldn't look up implementations
// frequently.
if (SynthCount == 0)
- return getObjCLayout(D, 0);
+ return getObjCLayout(D, nullptr);
}
- RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
+ RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
Builder.Layout(D);
const ASTRecordLayout *NewEntry =
@@ -3032,13 +3039,11 @@
CharUnits FieldOffset = Offset +
C.toCharUnitsFromBits(Layout.getFieldOffset(FieldNo));
- if (const RecordType *RT = Field.getType()->getAs<RecordType>()) {
- if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel,
- Field.getName().data(),
- /*IncludeVirtualBases=*/true);
- continue;
- }
+ if (const CXXRecordDecl *D = Field.getType()->getAsCXXRecordDecl()) {
+ DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel,
+ Field.getName().data(),
+ /*IncludeVirtualBases=*/true);
+ continue;
}
PrintOffset(OS, FieldOffset, IndentLevel);
@@ -3053,8 +3058,7 @@
Layout.getVBaseOffsetsMap();
for (const auto &I : RD->vbases()) {
assert(I.isVirtual() && "Found non-virtual class!");
- const CXXRecordDecl *VBase =
- cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase);
@@ -3078,7 +3082,6 @@
PrintIndentNoOffset(OS, IndentLevel - 1);
OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity();
OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity() << "]\n";
- OS << '\n';
}
void ASTContext::DumpRecordLayout(const RecordDecl *RD,
@@ -3088,7 +3091,7 @@
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
if (!Simple)
- return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, 0,
+ return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, nullptr,
/*IncludeVirtualBases=*/true);
OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n";
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index a03ef00..8588dda 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -65,13 +65,13 @@
unsigned sum = 0;
llvm::errs() << "\n*** Stmt/Expr Stats:\n";
for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
- if (StmtClassInfo[i].Name == 0) continue;
+ if (StmtClassInfo[i].Name == nullptr) continue;
sum += StmtClassInfo[i].Counter;
}
llvm::errs() << " " << sum << " stmts/exprs total.\n";
sum = 0;
for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
- if (StmtClassInfo[i].Name == 0) continue;
+ if (StmtClassInfo[i].Name == nullptr) continue;
if (StmtClassInfo[i].Counter == 0) continue;
llvm::errs() << " " << StmtClassInfo[i].Counter << " "
<< StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size
@@ -260,7 +260,7 @@
"NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
if (Stmts.size() == 0) {
- Body = 0;
+ Body = nullptr;
return;
}
@@ -285,8 +285,8 @@
AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
ArrayRef<const Attr*> Attrs,
Stmt *SubStmt) {
- void *Mem = C.Allocate(sizeof(AttributedStmt) +
- sizeof(Attr*) * (Attrs.size() - 1),
+ assert(!Attrs.empty() && "Attrs should not be empty");
+ void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * Attrs.size(),
llvm::alignOf<AttributedStmt>());
return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
}
@@ -294,8 +294,7 @@
AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
unsigned NumAttrs) {
assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
- void *Mem = C.Allocate(sizeof(AttributedStmt) +
- sizeof(Attr*) * (NumAttrs - 1),
+ void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * NumAttrs,
llvm::alignOf<AttributedStmt>());
return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
}
@@ -554,7 +553,7 @@
// Find the ']'.
const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
- if (NameEnd == 0)
+ if (NameEnd == nullptr)
return diag::err_asm_unterminated_symbolic_operand_name;
if (NameEnd == CurPtr)
return diag::err_asm_empty_symbolic_operand_name;
@@ -720,8 +719,7 @@
Stmt **CatchStmts, unsigned NumCatchStmts,
Stmt *atFinallyStmt)
: Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc),
- NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != 0)
-{
+ NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != nullptr) {
Stmt **Stmts = getStmts();
Stmts[0] = atTryStmt;
for (unsigned I = 0; I != NumCatchStmts; ++I)
@@ -738,7 +736,7 @@
unsigned NumCatchStmts,
Stmt *atFinallyStmt) {
unsigned Size = sizeof(ObjCAtTryStmt) +
- (1 + NumCatchStmts + (atFinallyStmt != 0)) * sizeof(Stmt *);
+ (1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *);
void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts,
atFinallyStmt);
@@ -833,7 +831,7 @@
VarDecl *IfStmt::getConditionVariable() const {
if (!SubExprs[VAR])
- return 0;
+ return nullptr;
DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
return cast<VarDecl>(DS->getSingleDecl());
@@ -841,7 +839,7 @@
void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
if (!V) {
- SubExprs[VAR] = 0;
+ SubExprs[VAR] = nullptr;
return;
}
@@ -864,7 +862,7 @@
VarDecl *ForStmt::getConditionVariable() const {
if (!SubExprs[CONDVAR])
- return 0;
+ return nullptr;
DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
return cast<VarDecl>(DS->getSingleDecl());
@@ -872,7 +870,7 @@
void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
if (!V) {
- SubExprs[CONDVAR] = 0;
+ SubExprs[CONDVAR] = nullptr;
return;
}
@@ -882,16 +880,16 @@
}
SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond)
- : Stmt(SwitchStmtClass), FirstCase(0), AllEnumCasesCovered(0)
+ : Stmt(SwitchStmtClass), FirstCase(nullptr), AllEnumCasesCovered(0)
{
setConditionVariable(C, Var);
SubExprs[COND] = cond;
- SubExprs[BODY] = NULL;
+ SubExprs[BODY] = nullptr;
}
VarDecl *SwitchStmt::getConditionVariable() const {
if (!SubExprs[VAR])
- return 0;
+ return nullptr;
DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
return cast<VarDecl>(DS->getSingleDecl());
@@ -899,7 +897,7 @@
void SwitchStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
if (!V) {
- SubExprs[VAR] = 0;
+ SubExprs[VAR] = nullptr;
return;
}
@@ -925,7 +923,7 @@
VarDecl *WhileStmt::getConditionVariable() const {
if (!SubExprs[VAR])
- return 0;
+ return nullptr;
DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
return cast<VarDecl>(DS->getSingleDecl());
@@ -933,7 +931,7 @@
void WhileStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
if (!V) {
- SubExprs[VAR] = 0;
+ SubExprs[VAR] = nullptr;
return;
}
@@ -947,7 +945,7 @@
if (AddrLabelExpr *E =
dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
return E->getLabel();
- return 0;
+ return nullptr;
}
// ReturnStmt
@@ -1049,8 +1047,8 @@
CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)
: Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),
- CapDeclAndKind(0, CR_Default), TheRecordDecl(0) {
- getStoredStmts()[NumCaptures] = 0;
+ CapDeclAndKind(nullptr, CR_Default), TheRecordDecl(nullptr) {
+ getStoredStmts()[NumCaptures] = nullptr;
}
CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S,
@@ -1192,6 +1190,30 @@
return new (Mem) OMPSharedClause(N);
}
+OMPLinearClause *OMPLinearClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL, Expr *Step) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * (VL.size() + 1));
+ OMPLinearClause *Clause = new (Mem)
+ OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setStep(Step);
+ return Clause;
+}
+
+OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
+ unsigned NumVars) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * (NumVars + 1));
+ return new (Mem) OMPLinearClause(NumVars);
+}
+
OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
diff --git a/lib/AST/StmtIterator.cpp b/lib/AST/StmtIterator.cpp
index 6e85375..1ccba04 100644
--- a/lib/AST/StmtIterator.cpp
+++ b/lib/AST/StmtIterator.cpp
@@ -27,7 +27,7 @@
t = vt->getElementType().getTypePtr();
}
- return NULL;
+ return nullptr;
}
void StmtIteratorBase::NextVA() {
@@ -54,7 +54,7 @@
}
void StmtIteratorBase::NextDecl(bool ImmediateAdvance) {
- assert (getVAPtr() == NULL);
+ assert(getVAPtr() == nullptr);
assert(inDeclGroup());
if (ImmediateAdvance)
@@ -93,12 +93,12 @@
}
StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge)
- : stmt(0), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
+ : stmt(nullptr), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
NextDecl(false);
}
StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t)
- : stmt(0), DGI(0), RawVAPtr(SizeOfTypeVAMode) {
+ : stmt(nullptr), DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) {
RawVAPtr |= reinterpret_cast<uintptr_t>(t);
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 7ad5491..0804d40 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -168,19 +168,8 @@
}
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
- OS << "[[";
- bool first = true;
- for (ArrayRef<const Attr*>::iterator it = Node->getAttrs().begin(),
- end = Node->getAttrs().end();
- it != end; ++it) {
- if (!first) {
- OS << ", ";
- first = false;
- }
- // TODO: check this
- (*it)->printPretty(OS, Policy);
- }
- OS << "]] ";
+ for (const auto *Attr : Node->getAttrs())
+ Attr->printPretty(OS, Policy);
PrintStmt(Node->getSubStmt(), 0);
}
@@ -603,19 +592,25 @@
void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
OS << "if(";
- Node->getCondition()->printPretty(OS, 0, Policy, 0);
+ Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
OS << "num_threads(";
- Node->getNumThreads()->printPretty(OS, 0, Policy, 0);
+ Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
OS << "safelen(";
- Node->getSafelen()->printPretty(OS, 0, Policy, 0);
+ Node->getSafelen()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
+ OS << "collapse(";
+ Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
@@ -625,6 +620,12 @@
<< ")";
}
+void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
+ OS << "proc_bind("
+ << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind())
+ << ")";
+}
+
template<typename T>
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
for (typename T::varlist_iterator I = Node->varlist_begin(),
@@ -635,7 +636,7 @@
cast<NamedDecl>(DRE->getDecl())->printQualifiedName(OS);
} else {
OS << (I == Node->varlist_begin() ? StartSym : ',');
- (*I)->printPretty(OS, 0, Policy, 0);
+ (*I)->printPretty(OS, nullptr, Policy, 0);
}
}
}
@@ -664,6 +665,18 @@
}
}
+void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "linear";
+ VisitOMPClauseList(Node, '(');
+ if (Node->getStep() != nullptr) {
+ OS << ": ";
+ Node->getStep()->printPretty(OS, nullptr, Policy, 0);
+ }
+ OS << ")";
+ }
+}
+
void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
if (!Node->varlist_empty()) {
OS << "copyin";
@@ -789,6 +802,9 @@
case PredefinedExpr::FuncDName:
OS << "__FUNCDNAME__";
break;
+ case PredefinedExpr::FuncSig:
+ OS << "__FUNCSIG__";
+ break;
case PredefinedExpr::LFunction:
OS << "L__FUNCTION__";
break;
@@ -1048,7 +1064,7 @@
MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
FieldDecl *ParentDecl = ParentMember
- ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : NULL;
+ ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : nullptr;
if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
OS << (Node->isArrow() ? "->" : ".");
@@ -1240,7 +1256,7 @@
}
void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
- const char *Name = 0;
+ const char *Name = nullptr;
switch (Node->getOp()) {
#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
@@ -1452,7 +1468,7 @@
}
void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) {
- if (Node->getSubExpr() == 0)
+ if (!Node->getSubExpr())
OS << "throw";
else {
OS << "throw ";
@@ -1968,14 +1984,14 @@
//===----------------------------------------------------------------------===//
void Stmt::dumpPretty(const ASTContext &Context) const {
- printPretty(llvm::errs(), 0, PrintingPolicy(Context.getLangOpts()));
+ printPretty(llvm::errs(), nullptr, PrintingPolicy(Context.getLangOpts()));
}
void Stmt::printPretty(raw_ostream &OS,
PrinterHelper *Helper,
const PrintingPolicy &Policy,
unsigned Indentation) const {
- if (this == 0) {
+ if (this == nullptr) {
OS << "<NULL>";
return;
}
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 07ed86a..9cff6d6 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -279,8 +279,15 @@
Profiler->VisitStmt(C->getSafelen());
}
+void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) {
+ if (C->getNumForLoops())
+ Profiler->VisitStmt(C->getNumForLoops());
+}
+
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
+void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
+
template<typename T>
void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
for (auto *I : Node->varlists())
@@ -297,6 +304,10 @@
void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
+ VisitOMPClauseList(C);
+ Profiler->VisitStmt(C->getStep());
+}
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
VisitOMPClauseList(C);
}
@@ -552,7 +563,7 @@
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
QualType T = S->getAssocType(i);
if (T.isNull())
- ID.AddPointer(0);
+ ID.AddPointer(nullptr);
else
VisitType(T);
VisitExpr(S->getAssocExpr(i));
@@ -946,10 +957,10 @@
VisitExpr(S);
ID.AddBoolean(S->isArrow());
VisitNestedNameSpecifier(S->getQualifier());
- ID.AddBoolean(S->getScopeTypeInfo() != 0);
+ ID.AddBoolean(S->getScopeTypeInfo() != nullptr);
if (S->getScopeTypeInfo())
VisitType(S->getScopeTypeInfo()->getType());
- ID.AddBoolean(S->getDestroyedTypeInfo() != 0);
+ ID.AddBoolean(S->getDestroyedTypeInfo() != nullptr);
if (S->getDestroyedTypeInfo())
VisitType(S->getDestroyedType());
else
@@ -1210,7 +1221,7 @@
}
}
- ID.AddPointer(D? D->getCanonicalDecl() : 0);
+ ID.AddPointer(D? D->getCanonicalDecl() : nullptr);
}
void StmtProfiler::VisitType(QualType T) {
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 52f95bf..d7ae73c 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -248,7 +248,7 @@
break;
case Declaration:
- ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
+ ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
break;
case Template:
@@ -386,7 +386,7 @@
}
case Expression:
- getAsExpr()->printPretty(Out, 0, Policy);
+ getAsExpr()->printPretty(Out, nullptr, Policy);
break;
case Pack:
@@ -489,7 +489,7 @@
LangOptions LangOpts;
LangOpts.CPlusPlus = true;
PrintingPolicy Policy(LangOpts);
- Arg.getAsExpr()->printPretty(OS, 0, Policy);
+ Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
return DB << OS.str();
}
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
index 8767c63..77c8fd5 100644
--- a/lib/AST/TemplateName.cpp
+++ b/lib/AST/TemplateName.cpp
@@ -78,7 +78,7 @@
if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
return sub->getReplacement().getAsTemplateDecl();
- return 0;
+ return nullptr;
}
bool TemplateName::isDependent() const {
@@ -121,7 +121,7 @@
return DTN->getQualifier() &&
DTN->getQualifier()->containsUnexpandedParameterPack();
- return getAsSubstTemplateTemplateParmPack() != 0;
+ return getAsSubstTemplateTemplateParmPack() != nullptr;
}
void
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index dc3fcc8..c2d4674 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -45,7 +45,7 @@
const IdentifierInfo* QualType::getBaseTypeIdentifier() const {
const Type* ty = getTypePtr();
- NamedDecl *ND = NULL;
+ NamedDecl *ND = nullptr;
if (ty->isPointerType() || ty->isReferenceType())
return ty->getPointeeType().getBaseTypeIdentifier();
else if (ty->isRecordType())
@@ -60,7 +60,7 @@
if (ND)
return ND->getIdentifier();
- return NULL;
+ return nullptr;
}
bool QualType::isConstant(QualType T, ASTContext &Ctx) {
@@ -202,7 +202,7 @@
// If the canonical form of this type isn't the right kind, reject it.
if (!isa<ArrayType>(CanonicalType))
- return 0;
+ return nullptr;
// If this is a typedef for an array type, strip the typedef off without
// losing all typedef information.
@@ -410,7 +410,7 @@
if (const ComplexType *Complex = getAs<ComplexType>())
if (Complex->getElementType()->isIntegerType())
return Complex;
- return 0;
+ return nullptr;
}
QualType Type::getPointeeType() const {
@@ -439,13 +439,13 @@
// If the canonical form of this type isn't the right kind, reject it.
if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
if (!RT->getDecl()->isStruct())
- return 0;
+ return nullptr;
// If this is a typedef for a structure type, strip the typedef off without
// losing all typedef information.
return cast<RecordType>(getUnqualifiedDesugaredType());
}
- return 0;
+ return nullptr;
}
const RecordType *Type::getAsUnionType() const {
@@ -458,14 +458,14 @@
// If the canonical form of this type isn't the right kind, reject it.
if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
if (!RT->getDecl()->isUnion())
- return 0;
+ return nullptr;
// If this is a typedef for a union type, strip the typedef off without
// losing all typedef information.
return cast<RecordType>(getUnqualifiedDesugaredType());
}
- return 0;
+ return nullptr;
}
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
@@ -489,11 +489,11 @@
if (const ObjCObjectType *T = getAs<ObjCObjectType>())
if (T->getNumProtocols() && T->getInterface())
return T;
- return 0;
+ return nullptr;
}
bool Type::isObjCQualifiedInterfaceType() const {
- return getAsObjCQualifiedInterfaceType() != 0;
+ return getAsObjCQualifiedInterfaceType() != nullptr;
}
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
@@ -503,7 +503,7 @@
if (OPT->isObjCQualifiedIdType())
return OPT;
}
- return 0;
+ return nullptr;
}
const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const {
@@ -513,7 +513,7 @@
if (OPT->isObjCQualifiedClassType())
return OPT;
}
- return 0;
+ return nullptr;
}
const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
@@ -521,7 +521,7 @@
if (OPT->getInterfaceType())
return OPT;
}
- return 0;
+ return nullptr;
}
const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const {
@@ -531,12 +531,12 @@
else if (const ReferenceType *RT = getAs<ReferenceType>())
PointeeType = RT->getPointeeType();
else
- return 0;
+ return nullptr;
if (const RecordType *RT = PointeeType->getAs<RecordType>())
return dyn_cast<CXXRecordDecl>(RT->getDecl());
- return 0;
+ return nullptr;
}
CXXRecordDecl *Type::getAsCXXRecordDecl() const {
@@ -545,8 +545,8 @@
else if (const InjectedClassNameType *Injected
= getAs<InjectedClassNameType>())
return Injected->getDecl();
-
- return 0;
+
+ return nullptr;
}
namespace {
@@ -556,7 +556,7 @@
using TypeVisitor<GetContainedAutoVisitor, AutoType*>::Visit;
AutoType *Visit(QualType T) {
if (T.isNull())
- return 0;
+ return nullptr;
return Visit(T.getTypePtr());
}
@@ -695,7 +695,7 @@
/// types.
bool Type::isAnyCharacterType() const {
const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
- if (BT == 0) return false;
+ if (!BT) return false;
switch (BT->getKind()) {
default: return false;
case BuiltinType::Char_U:
@@ -901,8 +901,8 @@
/// determine its size.
bool Type::isIncompleteType(NamedDecl **Def) const {
if (Def)
- *Def = 0;
-
+ *Def = nullptr;
+
switch (CanonicalType->getTypeClass()) {
default: return false;
case Builtin:
@@ -1431,8 +1431,7 @@
llvm_unreachable("Unknown elaborated type keyword.");
}
-const char*
-TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
+StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
switch (Keyword) {
case ETK_None: return "";
case ETK_Typename: return "typename";
@@ -1599,8 +1598,9 @@
result->containsUnexpandedParameterPack(), epi.ExtInfo),
NumParams(params.size()), NumExceptions(epi.NumExceptions),
ExceptionSpecType(epi.ExceptionSpecType),
- HasAnyConsumedParams(epi.ConsumedParameters != 0), Variadic(epi.Variadic),
- HasTrailingReturn(epi.HasTrailingReturn), RefQualifier(epi.RefQualifier) {
+ HasAnyConsumedParams(epi.ConsumedParameters != nullptr),
+ Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn),
+ RefQualifier(epi.RefQualifier) {
assert(NumParams == params.size() && "function has too many parameters");
// Fill in the trailing argument array.
@@ -1683,7 +1683,7 @@
return NR_Dependent;
llvm::APSInt value;
- bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, 0,
+ bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, nullptr,
/*evaluated*/false);
(void)isICE;
assert(isICE && "AST should not contain bad noexcept expressions.");
@@ -1924,7 +1924,7 @@
}
IdentifierInfo *TemplateTypeParmType::getIdentifier() const {
- return isCanonicalUnqualified() ? 0 : getDecl()->getIdentifier();
+ return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier();
}
SubstTemplateTypeParmPackType::
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 22a51bc..208d695 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -55,7 +55,7 @@
/// \brief Returns the alignment of the type source info data block.
unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
if (Ty.isNull()) return 1;
- return TypeAligner().Visit(TypeLoc(Ty, 0));
+ return TypeAligner().Visit(TypeLoc(Ty, nullptr));
}
namespace {
@@ -73,7 +73,7 @@
/// \brief Returns the size of the type source info data block.
unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
unsigned Total = 0;
- TypeLoc TyLoc(Ty, 0);
+ TypeLoc TyLoc(Ty, nullptr);
unsigned MaxAlign = 1;
while (!TyLoc.isNull()) {
unsigned Align = getLocalAlignmentForType(TyLoc.getType());
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 89ec8d6..dfb43a0 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -466,7 +466,7 @@
OS << '*';
if (T->getSizeExpr())
- T->getSizeExpr()->printPretty(OS, 0, Policy);
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
OS << ']';
printAfter(T->getElementType(), OS);
@@ -501,7 +501,7 @@
raw_ostream &OS) {
OS << '[';
if (T->getSizeExpr())
- T->getSizeExpr()->printPretty(OS, 0, Policy);
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
OS << ']';
printAfter(T->getElementType(), OS);
}
@@ -516,7 +516,7 @@
raw_ostream &OS) {
OS << " __attribute__((ext_vector_type(";
if (T->getSizeExpr())
- T->getSizeExpr()->printPretty(OS, 0, Policy);
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
OS << ")))";
printAfter(T->getElementType(), OS);
}
@@ -593,7 +593,7 @@
OS << " noexcept";
if (getExceptionSpecType() == EST_ComputedNoexcept) {
OS << '(';
- getNoexceptExpr()->printPretty(OS, 0, Policy);
+ getNoexceptExpr()->printPretty(OS, nullptr, Policy);
OS << ')';
}
}
@@ -761,7 +761,7 @@
void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
raw_ostream &OS) {
OS << "typeof ";
- T->getUnderlyingExpr()->printPretty(OS, 0, Policy);
+ T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
spaceBeforePlaceHolder(OS);
}
void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
@@ -777,7 +777,7 @@
void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
OS << "decltype(";
- T->getUnderlyingExpr()->printPretty(OS, 0, Policy);
+ T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
OS << ')';
spaceBeforePlaceHolder(OS);
}
@@ -1424,7 +1424,7 @@
llvm::errs() << '\n';
}
-LLVM_DUMP_METHOD void QualType::dump() const { dump(0); }
+LLVM_DUMP_METHOD void QualType::dump() const { dump(nullptr); }
LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index c6b38d3..6dc3956 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -44,9 +44,9 @@
/// path from the derived class to the base class involves a virtual base
/// class.
CharUnits NonVirtualOffset;
-
- BaseOffset() : DerivedClass(0), VirtualBase(0),
- NonVirtualOffset(CharUnits::Zero()) { }
+
+ BaseOffset() : DerivedClass(nullptr), VirtualBase(nullptr),
+ NonVirtualOffset(CharUnits::Zero()) { }
BaseOffset(const CXXRecordDecl *DerivedClass,
const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset)
: DerivedClass(DerivedClass), VirtualBase(VirtualBase),
@@ -64,10 +64,15 @@
/// Method - The method decl of the overrider.
const CXXMethodDecl *Method;
+ /// VirtualBase - The virtual base class subobject of this overridder.
+ /// Note that this records the closest derived virtual base class subobject.
+ const CXXRecordDecl *VirtualBase;
+
/// Offset - the base offset of the overrider's parent in the layout class.
CharUnits Offset;
-
- OverriderInfo() : Method(0), Offset(CharUnits::Zero()) { }
+
+ OverriderInfo() : Method(nullptr), VirtualBase(nullptr),
+ Offset(CharUnits::Zero()) { }
};
private:
@@ -201,6 +206,7 @@
Overrider.Offset = OverriderOffset;
Overrider.Method = Method.Method;
+ Overrider.VirtualBase = Method.InVirtualSubobject;
}
}
@@ -216,8 +222,8 @@
CharUnits NonVirtualOffset = CharUnits::Zero();
unsigned NonVirtualStart = 0;
- const CXXRecordDecl *VirtualBase = 0;
-
+ const CXXRecordDecl *VirtualBase = nullptr;
+
// First, look for the virtual base class.
for (int I = Path.size(), E = 0; I != E; --I) {
const CXXBasePathElement &Element = Path[I - 1];
@@ -1290,7 +1296,7 @@
// We don't have vcall offsets for this virtual base, go ahead and
// build them.
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
- /*FinalOverriders=*/0,
+ /*FinalOverriders=*/nullptr,
BaseSubobject(Offset.VirtualBase,
CharUnits::Zero()),
/*BaseIsVirtual=*/true,
@@ -1444,8 +1450,8 @@
return OverriddenMD;
}
}
-
- return 0;
+
+ return nullptr;
}
void ItaniumVTableBuilder::AddMethods(
@@ -1499,7 +1505,7 @@
llvm_unreachable("Found a duplicate primary base!");
}
- const CXXDestructorDecl *ImplicitVirtualDtor = 0;
+ const CXXDestructorDecl *ImplicitVirtualDtor = nullptr;
typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy;
NewVirtualFunctionsTy NewVirtualFunctions;
@@ -2138,7 +2144,7 @@
ThunkInfoVectorTy ThunksVector = Thunks[MD];
std::sort(ThunksVector.begin(), ThunksVector.end(),
[](const ThunkInfo &LHS, const ThunkInfo &RHS) {
- assert(LHS.Method == 0 && RHS.Method == 0);
+ assert(LHS.Method == nullptr && RHS.Method == nullptr);
return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
});
@@ -2284,8 +2290,8 @@
VirtualBaseClassOffsetOffsets.find(ClassPair);
if (I != VirtualBaseClassOffsetOffsets.end())
return I->second;
-
- VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/0,
+
+ VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/nullptr,
BaseSubobject(RD, CharUnits::Zero()),
/*BaseIsVirtual=*/false,
/*OffsetInLayoutClass=*/CharUnits::Zero());
@@ -2529,7 +2535,7 @@
// pointing to the middle of a section.
BasesSetVectorTy VisitedBases;
- AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, 0,
+ AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr,
VisitedBases);
assert(Components.size() && "vftable can't be empty");
@@ -2649,6 +2655,8 @@
CharUnits Ret;
bool First = true;
+ const ASTRecordLayout &OverriderRDLayout =
+ Context.getASTRecordLayout(Overrider.Method->getParent());
for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end();
I != E; ++I) {
const CXXBasePath &Path = (*I);
@@ -2665,19 +2673,18 @@
const ASTRecordLayout &Layout = Context.getASTRecordLayout(PrevRD);
if (Element.Base->isVirtual()) {
- LastVBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(CurRD);
- if (Overrider.Method->getParent() == PrevRD) {
- // This one's interesting. If the final overrider is in a vbase B of the
- // most derived class and it overrides a method of the B's own vbase A,
- // it uses A* as "this". In its prologue, it can cast A* to B* with
- // a static offset. This offset is used regardless of the actual
- // offset of A from B in the most derived class, requiring an
- // this-adjusting thunk in the vftable if A and B are laid out
- // differently in the most derived class.
- ThisOffset += Layout.getVBaseClassOffset(CurRD);
- } else {
- ThisOffset = LastVBaseOffset;
- }
+ // The interesting things begin when you have virtual inheritance.
+ // The final overrider will use a static adjustment equal to the offset
+ // of the vbase in the final overrider class.
+ // For example, if the final overrider is in a vbase B of the most
+ // derived class and it overrides a method of the B's own vbase A,
+ // it uses A* as "this". In its prologue, it can cast A* to B* with
+ // a static offset. This offset is used regardless of the actual
+ // offset of A from B in the most derived class, requiring an
+ // this-adjusting thunk in the vftable if A and B are laid out
+ // differently in the most derived class.
+ LastVBaseOffset = ThisOffset =
+ Overrider.Offset + OverriderRDLayout.getVBaseClassOffset(CurRD);
} else {
ThisOffset += Layout.getBaseClassOffset(CurRD);
}
@@ -2715,26 +2722,22 @@
VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
assert(VBaseMapEntry != VBaseMap.end());
- // Check if we need a vtordisp adjustment at all.
- if (!VBaseMapEntry->second.hasVtorDisp())
+ // If there's no vtordisp or the final overrider is defined in the same vbase
+ // as the initial declaration, we don't need any vtordisp adjustment.
+ if (!VBaseMapEntry->second.hasVtorDisp() ||
+ Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
return;
- CharUnits VFPtrVBaseOffset = VBaseMapEntry->second.VBaseOffset;
+ // OK, now we know we need to use a vtordisp thunk.
// The implicit vtordisp field is located right before the vbase.
+ CharUnits VFPtrVBaseOffset = VBaseMapEntry->second.VBaseOffset;
TA.Virtual.Microsoft.VtordispOffset =
(VFPtrVBaseOffset - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
- // If the final overrider is defined in either:
- // - the most derived class or its non-virtual base or
- // - the same vbase as the initial declaration,
- // a simple vtordisp thunk will suffice.
- const CXXRecordDecl *OverriderRD = Overrider.Method->getParent();
- if (OverriderRD == MostDerivedClass)
- return;
-
- const CXXRecordDecl *OverriderVBase =
- ComputeBaseOffset(Context, OverriderRD, MostDerivedClass).VirtualBase;
- if (!OverriderVBase || OverriderVBase == WhichVFPtr.getVBaseWithVPtr())
+ // A simple vtordisp thunk will suffice if the final overrider is defined
+ // in either the most derived class or its non-virtual base.
+ if (Overrider.Method->getParent() == MostDerivedClass ||
+ !Overrider.VirtualBase)
return;
// Otherwise, we need to do use the dynamic offset of the final overrider
@@ -2744,7 +2747,7 @@
MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
TA.Virtual.Microsoft.VBOffsetOffset =
Context.getTypeSizeInChars(Context.IntTy).getQuantity() *
- VTables.getVBTableIndex(MostDerivedClass, OverriderVBase);
+ VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
TA.NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
}
@@ -2813,7 +2816,7 @@
// See if this class expands a vftable of the base we look at, which is either
// the one defined by the vfptr base path or the primary base of the current class.
- const CXXRecordDecl *NextBase = 0, *NextLastVBase = LastVBase;
+ const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
CharUnits NextBaseOffset;
if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
@@ -2942,7 +2945,7 @@
}
AddMethod(OverriderMD, ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
- ReturnAdjustingThunk ? MD : 0));
+ ReturnAdjustingThunk ? MD : nullptr));
}
}
@@ -3174,11 +3177,7 @@
const VPtrInfoVector &BasePaths =
ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
- for (VPtrInfoVector::const_iterator II = BasePaths.begin(),
- EE = BasePaths.end();
- II != EE; ++II) {
- VPtrInfo *BaseInfo = *II;
-
+ for (VPtrInfo *BaseInfo : BasePaths) {
// Don't include the path if it goes through a virtual base that we've
// already included.
if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases))
@@ -3196,12 +3195,16 @@
// FIXME: Why do we need this?
P->PathToBaseWithVPtr.insert(P->PathToBaseWithVPtr.begin(), Base);
- // Keep track of which derived class ultimately uses the vtable, and what
- // the full adjustment is from the MDC to this vtable. The adjustment is
- // captured by an optional vbase and a non-virtual offset.
- if (Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
+ // Keep track of which vtable the derived class is going to extend with
+ // new methods or bases. We append to either the vftable of our primary
+ // base, or the first non-virtual base that has a vbtable.
+ if (P->ReusingBase == Base &&
+ Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
: Layout.getPrimaryBase()))
P->ReusingBase = RD;
+
+ // Keep track of the full adjustment from the MDC to this vtable. The
+ // adjustment is captured by an optional vbase and a non-virtual offset.
if (B.isVirtual())
P->ContainingVBases.push_back(Base);
else if (P->ContainingVBases.empty())
@@ -3234,7 +3237,7 @@
static bool extendPath(VPtrInfo *P) {
if (P->NextBaseToMangle) {
P->MangledPath.push_back(P->NextBaseToMangle);
- P->NextBaseToMangle = 0; // Prevent the path from being extended twice.
+ P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
return true;
}
return false;
@@ -3272,6 +3275,8 @@
}
MicrosoftVTableContext::~MicrosoftVTableContext() {
+ for (auto &P : VFPtrLocations)
+ llvm::DeleteContainerPointers(*P.second);
llvm::DeleteContainerSeconds(VFPtrLocations);
llvm::DeleteContainerSeconds(VFTableLayouts);
llvm::DeleteContainerSeconds(VBaseInfo);
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index 72a9d03..23708e2 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -137,7 +137,7 @@
// of the public API of this class.
bool TraverseDecl(Decl *DeclNode) {
ScopedIncrement ScopedDepth(&CurrentDepth);
- return (DeclNode == NULL) || traverse(*DeclNode);
+ return (DeclNode == nullptr) || traverse(*DeclNode);
}
bool TraverseStmt(Stmt *StmtNode) {
ScopedIncrement ScopedDepth(&CurrentDepth);
@@ -145,11 +145,11 @@
if (Traversal ==
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) {
const Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode);
- if (ExprNode != NULL) {
+ if (ExprNode) {
StmtToTraverse = ExprNode->IgnoreParenImpCasts();
}
}
- return (StmtToTraverse == NULL) || traverse(*StmtToTraverse);
+ return (StmtToTraverse == nullptr) || traverse(*StmtToTraverse);
}
// We assume that the QualType and the contained type are on the same
// hierarchy level. Thus, we try to match either of them.
@@ -180,7 +180,7 @@
}
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
ScopedIncrement ScopedDepth(&CurrentDepth);
- return (NNS == NULL) || traverse(*NNS);
+ return (NNS == nullptr) || traverse(*NNS);
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
if (!NNS)
@@ -295,7 +295,7 @@
MatchASTVisitor(
std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *
MatcherCallbackPairs)
- : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(NULL) {}
+ : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(nullptr) {}
void onStartOfTranslationUnit() {
for (std::vector<std::pair<internal::DynTypedMatcher,
@@ -616,21 +616,21 @@
static CXXRecordDecl *getAsCXXRecordDecl(const Type *TypeNode) {
// Type::getAs<...>() drills through typedefs.
- if (TypeNode->getAs<DependentNameType>() != NULL ||
- TypeNode->getAs<DependentTemplateSpecializationType>() != NULL ||
- TypeNode->getAs<TemplateTypeParmType>() != NULL)
+ if (TypeNode->getAs<DependentNameType>() != nullptr ||
+ TypeNode->getAs<DependentTemplateSpecializationType>() != nullptr ||
+ TypeNode->getAs<TemplateTypeParmType>() != nullptr)
// Dependent names and template TypeNode parameters will be matched when
// the template is instantiated.
- return NULL;
+ return nullptr;
TemplateSpecializationType const *TemplateType =
TypeNode->getAs<TemplateSpecializationType>();
- if (TemplateType == NULL) {
+ if (!TemplateType) {
return TypeNode->getAsCXXRecordDecl();
}
if (TemplateType->getTemplateName().isDependent())
// Dependent template specializations will be matched when the
// template is instantiated.
- return NULL;
+ return nullptr;
// For template specialization types which are specializing a template
// declaration which is an explicit or partial specialization of another
@@ -642,7 +642,7 @@
// another template declaration, getAsCXXRecordDecl() returns NULL and
// we get the CXXRecordDecl of the templated declaration.
CXXRecordDecl *SpecializationDecl = TemplateType->getAsCXXRecordDecl();
- if (SpecializationDecl != NULL) {
+ if (SpecializationDecl) {
return SpecializationDecl;
}
NamedDecl *Templated =
@@ -671,7 +671,7 @@
return true;
CXXRecordDecl *ClassDecl = getAsCXXRecordDecl(TypeNode);
- if (ClassDecl == NULL)
+ if (!ClassDecl)
continue;
if (ClassDecl == Declaration) {
// This can happen for recursive template definitions; if the
@@ -690,7 +690,7 @@
}
bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
- if (DeclNode == NULL) {
+ if (!DeclNode) {
return true;
}
match(*DeclNode);
@@ -698,7 +698,7 @@
}
bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) {
- if (StmtNode == NULL) {
+ if (!StmtNode) {
return true;
}
match(*StmtNode);
@@ -744,7 +744,7 @@
private:
void HandleTranslationUnit(ASTContext &Context) override {
- if (ParsingDone != NULL) {
+ if (ParsingDone != nullptr) {
ParsingDone->run();
}
Finder->matchAST(Context);
@@ -765,7 +765,7 @@
MatchFinder::MatchCallback::~MatchCallback() {}
MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
-MatchFinder::MatchFinder() : ParsingDone(NULL) {}
+MatchFinder::MatchFinder() : ParsingDone(nullptr) {}
MatchFinder::~MatchFinder() {}
diff --git a/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/lib/ASTMatchers/Dynamic/Diagnostics.cpp
index da2ed9a..b0abdc7 100644
--- a/lib/ASTMatchers/Dynamic/Diagnostics.cpp
+++ b/lib/ASTMatchers/Dynamic/Diagnostics.cpp
@@ -87,7 +87,7 @@
StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
switch (Type) {
- case Diagnostics::ET_RegistryNotFound:
+ case Diagnostics::ET_RegistryMatcherNotFound:
return "Matcher not found: $0";
case Diagnostics::ET_RegistryWrongArgCount:
return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
@@ -98,6 +98,8 @@
case Diagnostics::ET_RegistryAmbiguousOverload:
// TODO: Add type info about the overload error.
return "Ambiguous matcher overload.";
+ case Diagnostics::ET_RegistryValueNotFound:
+ return "Value not found: $0";
case Diagnostics::ET_ParserStringError:
return "Error parsing string token: <$0>";
diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
index 7726807..439d3d5 100644
--- a/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -149,8 +149,8 @@
/// would produce a trivial matcher that will either always or never match.
/// Such matchers are excluded from code completion results.
virtual bool isConvertibleTo(
- ast_type_traits::ASTNodeKind Kind, unsigned *Specificity = 0,
- ast_type_traits::ASTNodeKind *LeastDerivedKind = 0) const = 0;
+ ast_type_traits::ASTNodeKind Kind, unsigned *Specificity = nullptr,
+ ast_type_traits::ASTNodeKind *LeastDerivedKind = nullptr) const = 0;
/// Returns whether the matcher will, given a matcher of any type T, yield a
/// matcher of type T.
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
index 24ffdcd..25629d9 100644
--- a/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -58,7 +58,7 @@
public:
explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
: Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
- CodeCompletionLocation(0) {
+ CodeCompletionLocation(nullptr) {
NextToken = getNextToken();
}
@@ -90,7 +90,7 @@
if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) {
Result.Kind = TokenInfo::TK_CodeCompletion;
Result.Text = StringRef(CodeCompletionLocation, 0);
- CodeCompletionLocation = 0;
+ CodeCompletionLocation = nullptr;
return Result;
}
@@ -143,7 +143,7 @@
// cause the portion of the identifier before the code completion
// location to become a code completion token.
if (CodeCompletionLocation == Code.data() + TokenLength) {
- CodeCompletionLocation = 0;
+ CodeCompletionLocation = nullptr;
Result.Kind = TokenInfo::TK_CodeCompletion;
Result.Text = Code.substr(0, TokenLength);
Code = Code.drop_front(TokenLength);
@@ -258,6 +258,10 @@
Parser::Sema::~Sema() {}
+VariantValue Parser::Sema::getNamedValue(StringRef Name) {
+ return VariantValue();
+}
+
struct Parser::ScopedContextEntry {
Parser *P;
@@ -274,12 +278,43 @@
}
};
+/// \brief Parse expressions that start with an identifier.
+///
+/// This function can parse named values and matchers.
+/// In case of failure it will try to determine the user's intent to give
+/// an appropriate error message.
+bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
+ const TokenInfo NameToken = Tokenizer->consumeNextToken();
+
+ if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
+ // Parse as a named value.
+ if (const VariantValue NamedValue = S->getNamedValue(NameToken.Text)) {
+ *Value = NamedValue;
+ return true;
+ }
+ // If the syntax is correct and the name is not a matcher either, report
+ // unknown named value.
+ if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
+ Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
+ Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
+ !S->lookupMatcherCtor(NameToken.Text)) {
+ Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
+ << NameToken.Text;
+ return false;
+ }
+ // Otherwise, fallback to the matcher parser.
+ }
+
+ // Parse as a matcher expression.
+ return parseMatcherExpressionImpl(NameToken, Value);
+}
+
/// \brief Parse and validate a matcher expression.
/// \return \c true on success, in which case \c Value has the matcher parsed.
/// If the input is malformed, or some argument has an error, it
/// returns \c false.
-bool Parser::parseMatcherExpressionImpl(VariantValue *Value) {
- const TokenInfo NameToken = Tokenizer->consumeNextToken();
+bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
+ VariantValue *Value) {
assert(NameToken.Kind == TokenInfo::TK_Ident);
const TokenInfo OpenToken = Tokenizer->consumeNextToken();
if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
@@ -288,13 +323,19 @@
return false;
}
- llvm::Optional<MatcherCtor> Ctor =
- S->lookupMatcherCtor(NameToken.Text, NameToken.Range, Error);
+ llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
+
+ if (!Ctor) {
+ Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
+ << NameToken.Text;
+ // Do not return here. We need to continue to give completion suggestions.
+ }
+
std::vector<ParserValue> Args;
TokenInfo EndToken;
{
- ScopedContextEntry SCE(this, Ctor ? *Ctor : 0);
+ ScopedContextEntry SCE(this, Ctor ? *Ctor : nullptr);
while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
@@ -425,7 +466,7 @@
return true;
case TokenInfo::TK_Ident:
- return parseMatcherExpressionImpl(Value);
+ return parseIdentifierPrefixImpl(Value);
case TokenInfo::TK_CodeCompletion:
addExpressionCompletions();
@@ -457,27 +498,23 @@
Diagnostics *Error)
: Tokenizer(Tokenizer), S(S), Error(Error) {}
-class RegistrySema : public Parser::Sema {
-public:
- virtual ~RegistrySema() {}
- llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
- const SourceRange &NameRange,
- Diagnostics *Error) {
- return Registry::lookupMatcherCtor(MatcherName, NameRange, Error);
+Parser::RegistrySema::~RegistrySema() {}
+
+llvm::Optional<MatcherCtor>
+Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
+ return Registry::lookupMatcherCtor(MatcherName);
+}
+
+VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
+ MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID,
+ ArrayRef<ParserValue> Args, Diagnostics *Error) {
+ if (BindID.empty()) {
+ return Registry::constructMatcher(Ctor, NameRange, Args, Error);
+ } else {
+ return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
+ Error);
}
- VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
- const SourceRange &NameRange,
- StringRef BindID,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error) {
- if (BindID.empty()) {
- return Registry::constructMatcher(Ctor, NameRange, Args, Error);
- } else {
- return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
- Error);
- }
- }
-};
+}
bool Parser::parseExpression(StringRef Code, VariantValue *Value,
Diagnostics *Error) {
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 6089b45..87fe043 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -325,17 +325,12 @@
} // anonymous namespace
// static
-llvm::Optional<MatcherCtor>
-Registry::lookupMatcherCtor(StringRef MatcherName, const SourceRange &NameRange,
- Diagnostics *Error) {
+llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) {
ConstructorMap::const_iterator it =
RegistryData->constructors().find(MatcherName);
- if (it == RegistryData->constructors().end()) {
- Error->addError(NameRange, Error->ET_RegistryNotFound) << MatcherName;
- return llvm::Optional<MatcherCtor>();
- }
-
- return it->second;
+ return it == RegistryData->constructors().end()
+ ? llvm::Optional<MatcherCtor>()
+ : it->second;
}
namespace {
diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp
index 9c7262e..18c9894 100644
--- a/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -71,7 +71,7 @@
virtual void makeTypedMatcher(MatcherOps &Ops) const {
bool FoundIsExact = false;
- const DynTypedMatcher *Found = NULL;
+ const DynTypedMatcher *Found = nullptr;
int NumFound = 0;
for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
bool IsExactMatch;
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp
index c90d947..90d4b13 100644
--- a/lib/Analysis/AnalysisDeclContext.cpp
+++ b/lib/Analysis/AnalysisDeclContext.cpp
@@ -41,11 +41,11 @@
: Manager(Mgr),
D(d),
cfgBuildOptions(buildOptions),
- forcedBlkExprs(0),
+ forcedBlkExprs(nullptr),
builtCFG(false),
builtCompleteCFG(false),
- ReferencedBlockVars(0),
- ManagedAnalyses(0)
+ ReferencedBlockVars(nullptr),
+ ManagedAnalyses(nullptr)
{
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
}
@@ -54,11 +54,11 @@
const Decl *d)
: Manager(Mgr),
D(d),
- forcedBlkExprs(0),
+ forcedBlkExprs(nullptr),
builtCFG(false),
builtCompleteCFG(false),
- ReferencedBlockVars(0),
- ManagedAnalyses(0)
+ ReferencedBlockVars(nullptr),
+ ManagedAnalyses(nullptr)
{
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
}
@@ -140,7 +140,7 @@
}
}
- return NULL;
+ return nullptr;
}
void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
@@ -189,6 +189,9 @@
if (PM)
addParentsForSyntheticStmts(cfg.get(), *PM);
+
+ // The Observer should only observe one build of the CFG.
+ getCFGBuildOptions().Observer = nullptr;
}
return cfg.get();
}
@@ -205,6 +208,9 @@
if (PM)
addParentsForSyntheticStmts(completeCFG.get(), *PM);
+
+ // The Observer should only observe one build of the CFG.
+ getCFGBuildOptions().Observer = nullptr;
}
return completeCFG.get();
}
@@ -217,8 +223,8 @@
cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
return cfgStmtMap.get();
}
-
- return 0;
+
+ return nullptr;
}
CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
@@ -229,8 +235,8 @@
CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
return CFA.get();
}
-
- return 0;
+
+ return nullptr;
}
void AnalysisDeclContext::dumpCFG(bool ShowColors) {
@@ -395,7 +401,7 @@
return SFC;
LC = LC->getParent();
}
- return NULL;
+ return nullptr;
}
bool LocationContext::inTopFrame() const {
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index 039911e..316a18b 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -128,20 +128,20 @@
ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,
- const_cast<Expr*>(Arg), 0, VK_RValue);
+ const_cast<Expr*>(Arg), nullptr, VK_RValue);
}
Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
if (Arg->getType() == Ty)
return const_cast<Expr*>(Arg);
-
+
return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
- const_cast<Expr*>(Arg), 0, VK_RValue);
+ const_cast<Expr*>(Arg), nullptr, VK_RValue);
}
ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean,
- const_cast<Expr*>(Arg), 0, VK_RValue);
+ const_cast<Expr*>(Arg), nullptr, VK_RValue);
}
ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
@@ -159,7 +159,8 @@
ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
- return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal), 0);
+ return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal),
+ nullptr);
}
//===----------------------------------------------------------------------===//
@@ -172,24 +173,24 @@
static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
// Check if we have at least two parameters.
if (D->param_size() != 2)
- return 0;
+ return nullptr;
// Check if the first parameter is a pointer to integer type.
const ParmVarDecl *Predicate = D->getParamDecl(0);
QualType PredicateQPtrTy = Predicate->getType();
const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
if (!PredicatePtrTy)
- return 0;
+ return nullptr;
QualType PredicateTy = PredicatePtrTy->getPointeeType();
if (!PredicateTy->isIntegerType())
- return 0;
-
+ return nullptr;
+
// Check if the second parameter is the proper block type.
const ParmVarDecl *Block = D->getParamDecl(1);
QualType Ty = Block->getType();
if (!isDispatchBlock(Ty))
- return 0;
-
+ return nullptr;
+
// Everything checks out. Create a fakse body that checks the predicate,
// sets it, and calls the block. Basically, an AST dump of:
//
@@ -242,7 +243,7 @@
SourceLocation());
// (5) Create the 'if' statement.
- IfStmt *If = new (C) IfStmt(C, SourceLocation(), 0, UO, CS);
+ IfStmt *If = new (C) IfStmt(C, SourceLocation(), nullptr, UO, CS);
return If;
}
@@ -250,14 +251,14 @@
static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
// Check if we have at least two parameters.
if (D->param_size() != 2)
- return 0;
-
+ return nullptr;
+
// Check if the second parameter is a block.
const ParmVarDecl *PV = D->getParamDecl(1);
QualType Ty = PV->getType();
if (!isDispatchBlock(Ty))
- return 0;
-
+ return nullptr;
+
// Everything checks out. Create a fake body that just calls the block.
// This is basically just an AST dump of:
//
@@ -277,8 +278,8 @@
{
// There are exactly 3 arguments.
if (D->param_size() != 3)
- return 0;
-
+ return nullptr;
+
// Signature:
// _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
// void *__newValue,
@@ -293,8 +294,8 @@
QualType ResultTy = D->getReturnType();
bool isBoolean = ResultTy->isBooleanType();
if (!isBoolean && !ResultTy->isIntegralType(C))
- return 0;
-
+ return nullptr;
+
const ParmVarDecl *OldValue = D->getParamDecl(0);
QualType OldValueTy = OldValue->getType();
@@ -307,7 +308,7 @@
QualType TheValueTy = TheValue->getType();
const PointerType *PT = TheValueTy->getAs<PointerType>();
if (!PT)
- return 0;
+ return nullptr;
QualType PointeeTy = PT->getPointeeType();
ASTMaker M(C);
@@ -346,9 +347,9 @@
/// Construct the If.
Stmt *If =
- new (C) IfStmt(C, SourceLocation(), 0, Comparison, Body,
+ new (C) IfStmt(C, SourceLocation(), nullptr, Comparison, Body,
SourceLocation(), Else);
-
+
return If;
}
@@ -358,15 +359,15 @@
Optional<Stmt *> &Val = Bodies[D];
if (Val.hasValue())
return Val.getValue();
-
- Val = 0;
-
- if (D->getIdentifier() == 0)
- return 0;
+
+ Val = nullptr;
+
+ if (D->getIdentifier() == nullptr)
+ return nullptr;
StringRef Name = D->getName();
if (Name.empty())
- return 0;
+ return nullptr;
FunctionFarmer FF;
@@ -378,7 +379,7 @@
FF = llvm::StringSwitch<FunctionFarmer>(Name)
.Case("dispatch_sync", create_dispatch_sync)
.Case("dispatch_once", create_dispatch_once)
- .Default(NULL);
+ .Default(nullptr);
}
if (FF) { Val = FF(C, D); }
@@ -390,11 +391,11 @@
// First, find the backing ivar.
const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
if (!IVar)
- return 0;
+ return nullptr;
// Ignore weak variables, which have special behavior.
if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
- return 0;
+ return nullptr;
// Look to see if Sema has synthesized a body for us. This happens in
// Objective-C++ because the return value may be a C++ class type with a
@@ -420,10 +421,10 @@
// copyable.
if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
Prop->getType().getNonReferenceType()))
- return 0;
+ return nullptr;
if (!IVar->getType()->isObjCLifetimeType() &&
!IVar->getType().isTriviallyCopyableType(Ctx))
- return 0;
+ return nullptr;
// Generate our body:
// return self->_ivar;
@@ -447,22 +448,22 @@
Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
// We currently only know how to synthesize property accessors.
if (!D->isPropertyAccessor())
- return 0;
+ return nullptr;
D = D->getCanonicalDecl();
Optional<Stmt *> &Val = Bodies[D];
if (Val.hasValue())
return Val.getValue();
- Val = 0;
+ Val = nullptr;
const ObjCPropertyDecl *Prop = D->findPropertyDecl();
if (!Prop)
- return 0;
+ return nullptr;
// For now, we only synthesize getters.
if (D->param_size() != 0)
- return 0;
+ return nullptr;
Val = createObjCPropertyGetter(C, Prop);
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 400c202..5d2926c 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -112,7 +112,7 @@
/// Incrementing invalid iterator is allowed and will result in invalid
/// iterator.
const_iterator()
- : Scope(NULL), VarIter(0) {}
+ : Scope(nullptr), VarIter(0) {}
/// Create valid iterator. In case when S.Prev is an invalid iterator and
/// I is equal to 0, this will create invalid iterator.
@@ -207,7 +207,7 @@
/// build process. It consists of CFGBlock that specifies position in CFG graph
/// and LocalScope::const_iterator that specifies position in LocalScope graph.
struct BlockScopePosPair {
- BlockScopePosPair() : block(0) {}
+ BlockScopePosPair() : block(nullptr) {}
BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)
: block(b), scopePosition(scopePos) {}
@@ -336,11 +336,11 @@
explicit CFGBuilder(ASTContext *astContext,
const CFG::BuildOptions &buildOpts)
: Context(astContext), cfg(new CFG()), // crew a new CFG
- Block(NULL), Succ(NULL),
- SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
- TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts),
- switchExclusivelyCovered(false), switchCond(0),
- cachedEntry(0), lastLookup(0) {}
+ Block(nullptr), Succ(nullptr),
+ SwitchTerminatedBlock(nullptr), DefaultCaseBlock(nullptr),
+ TryTerminatedBlock(nullptr), badCFG(false), BuildOpts(buildOpts),
+ switchExclusivelyCovered(false), switchCond(nullptr),
+ cachedEntry(nullptr), lastLookup(nullptr) {}
// buildCFG - Used by external clients to construct the CFG.
CFG* buildCFG(const Decl *D, Stmt *Statement);
@@ -443,8 +443,9 @@
LocalScope* createOrReuseLocalScope(LocalScope* Scope);
void addLocalScopeForStmt(Stmt *S);
- LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS, LocalScope* Scope = NULL);
- LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = NULL);
+ LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,
+ LocalScope* Scope = nullptr);
+ LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr);
void addLocalScopeAndDtors(Stmt *S);
@@ -495,6 +496,242 @@
cfg->getBumpVectorContext());
}
+ /// \brief Find a relational comparison with an expression evaluating to a
+ /// boolean and a constant other than 0 and 1.
+ /// e.g. if ((x < y) == 10)
+ TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) {
+ const Expr *LHSExpr = B->getLHS()->IgnoreParens();
+ const Expr *RHSExpr = B->getRHS()->IgnoreParens();
+
+ const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
+ const Expr *BoolExpr = RHSExpr;
+ bool IntFirst = true;
+ if (!IntLiteral) {
+ IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
+ BoolExpr = LHSExpr;
+ IntFirst = false;
+ }
+
+ if (!IntLiteral || !BoolExpr->isKnownToHaveBooleanValue())
+ return TryResult();
+
+ llvm::APInt IntValue = IntLiteral->getValue();
+ if ((IntValue == 1) || (IntValue == 0))
+ return TryResult();
+
+ bool IntLarger = IntLiteral->getType()->isUnsignedIntegerType() ||
+ !IntValue.isNegative();
+
+ BinaryOperatorKind Bok = B->getOpcode();
+ if (Bok == BO_GT || Bok == BO_GE) {
+ // Always true for 10 > bool and bool > -1
+ // Always false for -1 > bool and bool > 10
+ return TryResult(IntFirst == IntLarger);
+ } else {
+ // Always true for -1 < bool and bool < 10
+ // Always false for 10 < bool and bool < -1
+ return TryResult(IntFirst != IntLarger);
+ }
+ }
+
+ /// Find an incorrect equality comparison. Either with an expression
+ /// evaluating to a boolean and a constant other than 0 and 1.
+ /// e.g. if (!x == 10) or a bitwise and/or operation that always evaluates to
+ /// true/false e.q. (x & 8) == 4.
+ TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) {
+ const Expr *LHSExpr = B->getLHS()->IgnoreParens();
+ const Expr *RHSExpr = B->getRHS()->IgnoreParens();
+
+ const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
+ const Expr *BoolExpr = RHSExpr;
+
+ if (!IntLiteral) {
+ IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
+ BoolExpr = LHSExpr;
+ }
+
+ if (!IntLiteral)
+ return TryResult();
+
+ const BinaryOperator *BitOp = dyn_cast<BinaryOperator>(BoolExpr);
+ if (BitOp && (BitOp->getOpcode() == BO_And ||
+ BitOp->getOpcode() == BO_Or)) {
+ const Expr *LHSExpr2 = BitOp->getLHS()->IgnoreParens();
+ const Expr *RHSExpr2 = BitOp->getRHS()->IgnoreParens();
+
+ const IntegerLiteral *IntLiteral2 = dyn_cast<IntegerLiteral>(LHSExpr2);
+
+ if (!IntLiteral2)
+ IntLiteral2 = dyn_cast<IntegerLiteral>(RHSExpr2);
+
+ if (!IntLiteral2)
+ return TryResult();
+
+ llvm::APInt L1 = IntLiteral->getValue();
+ llvm::APInt L2 = IntLiteral2->getValue();
+ if ((BitOp->getOpcode() == BO_And && (L2 & L1) != L1) ||
+ (BitOp->getOpcode() == BO_Or && (L2 | L1) != L1)) {
+ if (BuildOpts.Observer)
+ BuildOpts.Observer->compareBitwiseEquality(B,
+ B->getOpcode() != BO_EQ);
+ TryResult(B->getOpcode() != BO_EQ);
+ }
+ } else if (BoolExpr->isKnownToHaveBooleanValue()) {
+ llvm::APInt IntValue = IntLiteral->getValue();
+ if ((IntValue == 1) || (IntValue == 0)) {
+ return TryResult();
+ }
+ return TryResult(B->getOpcode() != BO_EQ);
+ }
+
+ return TryResult();
+ }
+
+ TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation,
+ const llvm::APSInt &Value1,
+ const llvm::APSInt &Value2) {
+ assert(Value1.isSigned() == Value2.isSigned());
+ switch (Relation) {
+ default:
+ return TryResult();
+ case BO_EQ:
+ return TryResult(Value1 == Value2);
+ case BO_NE:
+ return TryResult(Value1 != Value2);
+ case BO_LT:
+ return TryResult(Value1 < Value2);
+ case BO_LE:
+ return TryResult(Value1 <= Value2);
+ case BO_GT:
+ return TryResult(Value1 > Value2);
+ case BO_GE:
+ return TryResult(Value1 >= Value2);
+ }
+ }
+
+ /// \brief Find a pair of comparison expressions with or without parentheses
+ /// with a shared variable and constants and a logical operator between them
+ /// that always evaluates to either true or false.
+ /// e.g. if (x != 3 || x != 4)
+ TryResult checkIncorrectLogicOperator(const BinaryOperator *B) {
+ assert(B->isLogicalOp());
+ const BinaryOperator *LHS =
+ dyn_cast<BinaryOperator>(B->getLHS()->IgnoreParens());
+ const BinaryOperator *RHS =
+ dyn_cast<BinaryOperator>(B->getRHS()->IgnoreParens());
+ if (!LHS || !RHS)
+ return TryResult();
+
+ if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
+ return TryResult();
+
+ BinaryOperatorKind BO1 = LHS->getOpcode();
+ const DeclRefExpr *Decl1 =
+ dyn_cast<DeclRefExpr>(LHS->getLHS()->IgnoreParenImpCasts());
+ const IntegerLiteral *Literal1 =
+ dyn_cast<IntegerLiteral>(LHS->getRHS()->IgnoreParens());
+ if (!Decl1 && !Literal1) {
+ if (BO1 == BO_GT)
+ BO1 = BO_LT;
+ else if (BO1 == BO_GE)
+ BO1 = BO_LE;
+ else if (BO1 == BO_LT)
+ BO1 = BO_GT;
+ else if (BO1 == BO_LE)
+ BO1 = BO_GE;
+ Decl1 = dyn_cast<DeclRefExpr>(LHS->getRHS()->IgnoreParenImpCasts());
+ Literal1 = dyn_cast<IntegerLiteral>(LHS->getLHS()->IgnoreParens());
+ }
+
+ if (!Decl1 || !Literal1)
+ return TryResult();
+
+ BinaryOperatorKind BO2 = RHS->getOpcode();
+ const DeclRefExpr *Decl2 =
+ dyn_cast<DeclRefExpr>(RHS->getLHS()->IgnoreParenImpCasts());
+ const IntegerLiteral *Literal2 =
+ dyn_cast<IntegerLiteral>(RHS->getRHS()->IgnoreParens());
+ if (!Decl2 && !Literal2) {
+ if (BO2 == BO_GT)
+ BO2 = BO_LT;
+ else if (BO2 == BO_GE)
+ BO2 = BO_LE;
+ else if (BO2 == BO_LT)
+ BO2 = BO_GT;
+ else if (BO2 == BO_LE)
+ BO2 = BO_GE;
+ Decl2 = dyn_cast<DeclRefExpr>(RHS->getRHS()->IgnoreParenImpCasts());
+ Literal2 = dyn_cast<IntegerLiteral>(RHS->getLHS()->IgnoreParens());
+ }
+
+ if (!Decl2 || !Literal2)
+ return TryResult();
+
+ // Check that it is the same variable on both sides.
+ if (Decl1->getDecl() != Decl2->getDecl())
+ return TryResult();
+
+ llvm::APSInt L1, L2;
+
+ if (!Literal1->EvaluateAsInt(L1, *Context) ||
+ !Literal2->EvaluateAsInt(L2, *Context))
+ return TryResult();
+
+ // Can't compare signed with unsigned or with different bit width.
+ if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
+ return TryResult();
+
+ // Values that will be used to determine if result of logical
+ // operator is always true/false
+ const llvm::APSInt Values[] = {
+ // Value less than both Value1 and Value2
+ llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
+ // L1
+ L1,
+ // Value between Value1 and Value2
+ ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
+ L1.isUnsigned()),
+ // L2
+ L2,
+ // Value greater than both Value1 and Value2
+ llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
+ };
+
+ // Check whether expression is always true/false by evaluating the following
+ // * variable x is less than the smallest literal.
+ // * variable x is equal to the smallest literal.
+ // * Variable x is between smallest and largest literal.
+ // * Variable x is equal to the largest literal.
+ // * Variable x is greater than largest literal.
+ bool AlwaysTrue = true, AlwaysFalse = true;
+ for (unsigned int ValueIndex = 0;
+ ValueIndex < sizeof(Values) / sizeof(Values[0]);
+ ++ValueIndex) {
+ llvm::APSInt Value = Values[ValueIndex];
+ TryResult Res1, Res2;
+ Res1 = analyzeLogicOperatorCondition(BO1, Value, L1);
+ Res2 = analyzeLogicOperatorCondition(BO2, Value, L2);
+
+ if (!Res1.isKnown() || !Res2.isKnown())
+ return TryResult();
+
+ if (B->getOpcode() == BO_LAnd) {
+ AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
+ AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
+ } else {
+ AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
+ AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
+ }
+ }
+
+ if (AlwaysTrue || AlwaysFalse) {
+ if (BuildOpts.Observer)
+ BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
+ return TryResult(AlwaysTrue);
+ }
+ return TryResult();
+ }
+
/// Try and evaluate an expression to an integer constant.
bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
if (!BuildOpts.PruneTriviallyFalseEdges)
@@ -577,10 +814,22 @@
// is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
return RHS.isTrue();
+ } else {
+ TryResult BopRes = checkIncorrectLogicOperator(Bop);
+ if (BopRes.isKnown())
+ return BopRes.isTrue();
}
}
return TryResult();
+ } else if (Bop->isEqualityOp()) {
+ TryResult BopRes = checkIncorrectEqualityOperator(Bop);
+ if (BopRes.isKnown())
+ return BopRes.isTrue();
+ } else if (Bop->isRelationalOp()) {
+ TryResult BopRes = checkIncorrectRelationalOperator(Bop);
+ if (BopRes.isKnown())
+ return BopRes.isTrue();
}
}
@@ -619,13 +868,13 @@
if (!fb) {
// No need to update 'cachedEntry', since it will always be null.
- assert(cachedEntry == 0);
+ assert(!cachedEntry);
return shouldAdd;
}
CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
if (itr == fb->end()) {
- cachedEntry = 0;
+ cachedEntry = nullptr;
return shouldAdd;
}
@@ -644,7 +893,7 @@
t = vt->getElementType().getTypePtr();
}
- return 0;
+ return nullptr;
}
/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an
@@ -655,14 +904,14 @@
CFG* CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
assert(cfg.get());
if (!Statement)
- return NULL;
+ return nullptr;
// Create an empty block that will serve as the exit block for the CFG. Since
// this is the first block added to the CFG, it will be implicitly registered
// as the exit block.
Succ = createBlock();
assert(Succ == &cfg->getExit());
- Block = NULL; // the EXIT block is empty. Create all other blocks lazily.
+ Block = nullptr; // the EXIT block is empty. Create all other blocks lazily.
if (BuildOpts.AddImplicitDtors)
if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))
@@ -672,7 +921,7 @@
CFGBlock *B = addStmt(Statement);
if (badCFG)
- return NULL;
+ return nullptr;
// For C++ constructor add initializers to CFG.
if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
@@ -680,7 +929,7 @@
E = CD->init_rend(); I != E; ++I) {
B = addInitializer(*I);
if (badCFG)
- return NULL;
+ return nullptr;
}
}
@@ -935,7 +1184,7 @@
if (!BuildOpts.AddImplicitDtors)
return;
- LocalScope *Scope = 0;
+ LocalScope *Scope = nullptr;
// For compound statement we will be creating explicit scope.
if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
@@ -1057,7 +1306,7 @@
CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
if (!S) {
badCFG = true;
- return 0;
+ return nullptr;
}
if (Expr *E = dyn_cast<Expr>(S))
@@ -1282,9 +1531,10 @@
appendStmt(ConfluenceBlock, B);
if (badCFG)
- return 0;
+ return nullptr;
- return VisitLogicalOperator(B, 0, ConfluenceBlock, ConfluenceBlock).first;
+ return VisitLogicalOperator(B, nullptr, ConfluenceBlock,
+ ConfluenceBlock).first;
}
std::pair<CFGBlock*, CFGBlock*>
@@ -1320,6 +1570,8 @@
else {
RHSBlock->setTerminator(Term);
TryResult KnownVal = tryEvaluateBool(RHS);
+ if (!KnownVal.isKnown())
+ KnownVal = tryEvaluateBool(B);
addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
}
@@ -1330,7 +1582,7 @@
while (false);
if (badCFG)
- return std::make_pair((CFGBlock*)0, (CFGBlock*)0);
+ return std::make_pair(nullptr, nullptr);
// Generate the blocks for evaluating the LHS.
Expr *LHS = B->getLHS()->IgnoreParens();
@@ -1357,7 +1609,7 @@
CFGBlock *EntryLHSBlock = addStmt(LHS);
if (badCFG)
- return std::make_pair((CFGBlock*)0, (CFGBlock*)0);
+ return std::make_pair(nullptr, nullptr);
// See if this is a known constant.
TryResult KnownVal = tryEvaluateBool(LHS);
@@ -1423,7 +1675,7 @@
// "break" is a control-flow statement. Thus we stop processing the current
// block.
if (badCFG)
- return 0;
+ return nullptr;
// Now create a new block that ends with the break statement.
Block = createBlock(false);
@@ -1511,7 +1763,7 @@
if (Block) {
Succ = Block;
if (badCFG)
- return 0;
+ return nullptr;
}
if (NoReturn)
@@ -1537,26 +1789,26 @@
CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
appendStmt(ConfluenceBlock, C);
if (badCFG)
- return 0;
+ return nullptr;
AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
Succ = ConfluenceBlock;
- Block = NULL;
+ Block = nullptr;
CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd);
if (badCFG)
- return 0;
+ return nullptr;
Succ = ConfluenceBlock;
- Block = NULL;
+ Block = nullptr;
CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd);
if (badCFG)
- return 0;
+ return nullptr;
Block = createBlock(false);
// See if this is a known constant.
const TryResult& KnownVal = tryEvaluateBool(C->getCond());
- addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
- addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
+ addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
+ addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
Block->setTerminator(C);
return addStmt(C->getCond());
}
@@ -1574,7 +1826,7 @@
LastBlock = newBlock;
if (badCFG)
- return NULL;
+ return nullptr;
}
return LastBlock;
@@ -1583,14 +1835,14 @@
CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
AddStmtChoice asc) {
const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C);
- const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL);
+ const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : nullptr);
// Create the confluence block that will "merge" the results of the ternary
// expression.
CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
appendStmt(ConfluenceBlock, C);
if (badCFG)
- return 0;
+ return nullptr;
AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
@@ -1599,14 +1851,14 @@
// value that is returned instead.
// e.g: x ?: y is shorthand for: x ? x : y;
Succ = ConfluenceBlock;
- Block = NULL;
- CFGBlock *LHSBlock = 0;
+ Block = nullptr;
+ CFGBlock *LHSBlock = nullptr;
const Expr *trueExpr = C->getTrueExpr();
if (trueExpr != opaqueValue) {
LHSBlock = Visit(C->getTrueExpr(), alwaysAdd);
if (badCFG)
- return 0;
- Block = NULL;
+ return nullptr;
+ Block = nullptr;
}
else
LHSBlock = ConfluenceBlock;
@@ -1615,7 +1867,7 @@
Succ = ConfluenceBlock;
CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd);
if (badCFG)
- return 0;
+ return nullptr;
// If the condition is a logical '&&' or '||', build a more accurate CFG.
if (BinaryOperator *Cond =
@@ -1657,7 +1909,7 @@
if (DS->isSingleDecl())
return VisitDeclSubExpr(DS);
- CFGBlock *B = 0;
+ CFGBlock *B = nullptr;
// Build an individual DeclStmt for each decl.
for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(),
@@ -1698,16 +1950,16 @@
bool HasTemporaries = false;
// Guard static initializers under a branch.
- CFGBlock *blockAfterStaticInit = 0;
+ CFGBlock *blockAfterStaticInit = nullptr;
if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
// For static variables, we need to create a branch to track
// whether or not they are initialized.
if (Block) {
Succ = Block;
- Block = 0;
+ Block = nullptr;
if (badCFG)
- return 0;
+ return nullptr;
}
blockAfterStaticInit = Succ;
}
@@ -1750,7 +2002,7 @@
// If the type of VD is a VLA, then we must process its size expressions.
for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr());
- VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) {
+ VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) {
if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
LastBlock = newBlock;
}
@@ -1797,7 +2049,7 @@
if (Block) {
Succ = Block;
if (badCFG)
- return 0;
+ return nullptr;
}
// Process the false branch.
@@ -1808,7 +2060,7 @@
// NULL out Block so that the recursive call to Visit will
// create a new basic block.
- Block = NULL;
+ Block = nullptr;
// If branch is not a compound statement create implicit scope
// and add destructors.
@@ -1821,7 +2073,7 @@
ElseBlock = sv.get();
else if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
}
}
@@ -1831,7 +2083,7 @@
Stmt *Then = I->getThen();
assert(Then);
SaveAndRestore<CFGBlock*> sv(Succ);
- Block = NULL;
+ Block = nullptr;
// If branch is not a compound statement create implicit scope
// and add destructors.
@@ -1848,7 +2100,7 @@
addSuccessor(ThenBlock, sv.get());
} else if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
}
}
@@ -1884,14 +2136,11 @@
// blocks will be pointed to be "Block".
CFGBlock *LastBlock = addStmt(I->getCond());
- // Finally, if the IfStmt contains a condition variable, add both the IfStmt
- // and the condition variable initialization to the CFG.
- if (VarDecl *VD = I->getConditionVariable()) {
- if (Expr *Init = VD->getInit()) {
- autoCreateBlock();
- appendStmt(Block, I->getConditionVariableDeclStmt());
- LastBlock = addStmt(Init);
- }
+ // Finally, if the IfStmt contains a condition variable, add it and its
+ // initializer to the CFG.
+ if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) {
+ autoCreateBlock();
+ LastBlock = addStmt(const_cast<DeclStmt *>(DS));
}
return LastBlock;
@@ -1939,10 +2188,10 @@
// about.
LabelBlock->setLabel(L);
if (badCFG)
- return 0;
+ return nullptr;
// We set Block to NULL to allow lazy creation of a new block (if necessary);
- Block = NULL;
+ Block = nullptr;
// This block is now the implicit successor of other blocks.
Succ = LabelBlock;
@@ -1956,7 +2205,7 @@
et = E->capture_init_end(); it != et; ++it) {
if (Expr *Init = *it) {
CFGBlock *Tmp = Visit(Init);
- if (Tmp != 0)
+ if (Tmp)
LastBlock = Tmp;
}
}
@@ -1986,7 +2235,7 @@
}
CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
- CFGBlock *LoopSuccessor = NULL;
+ CFGBlock *LoopSuccessor = nullptr;
// Save local scope position because in case of condition variable ScopePos
// won't be restored when traversing AST.
@@ -2009,7 +2258,7 @@
// block.
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
LoopSuccessor = Block;
} else
LoopSuccessor = Succ;
@@ -2019,7 +2268,7 @@
SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
- CFGBlock *BodyBlock = 0, *TransitionBlock = 0;
+ CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
// Now create the loop body.
{
@@ -2045,8 +2294,8 @@
if (Block) {
assert(Block == Succ);
if (badCFG)
- return 0;
- Block = 0;
+ return nullptr;
+ Block = nullptr;
}
// The starting block for the loop increment is the block that should
@@ -2072,13 +2321,13 @@
BodyBlock = ContinueJumpTarget.block;
}
else if (badCFG)
- return 0;
+ return nullptr;
}
// Because of short-circuit evaluation, the condition of the loop can span
// multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
// evaluate the condition.
- CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0;
+ CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
do {
Expr *C = F->getCond();
@@ -2086,7 +2335,7 @@
// Specially handle logical operators, which have a slightly
// more optimal CFG representation.
if (BinaryOperator *Cond =
- dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : 0))
+ dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : nullptr))
if (Cond->isLogicalOp()) {
std::tie(EntryConditionBlock, ExitConditionBlock) =
VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
@@ -2119,16 +2368,17 @@
}
if (Block && badCFG)
- return 0;
+ return nullptr;
KnownVal = tryEvaluateBool(C);
}
// Add the loop body entry as a successor to the condition.
- addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock);
+ addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
// Link up the condition block with the code that follows the loop. (the
// false branch).
- addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
+ addSuccessor(ExitConditionBlock,
+ KnownVal.isTrue() ? nullptr : LoopSuccessor);
} while (false);
@@ -2147,7 +2397,7 @@
// There is no loop initialization. We are thus basically a while loop.
// NULL out Block to force lazy block construction.
- Block = NULL;
+ Block = nullptr;
Succ = EntryConditionBlock;
return EntryConditionBlock;
}
@@ -2193,13 +2443,13 @@
// a DeclStmt and the other returns a DeclRefExpr.
//
- CFGBlock *LoopSuccessor = 0;
+ CFGBlock *LoopSuccessor = nullptr;
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
LoopSuccessor = Block;
- Block = 0;
+ Block = nullptr;
} else
LoopSuccessor = Succ;
@@ -2222,8 +2472,8 @@
AddStmtChoice::NotAlwaysAdd);
if (Block) {
if (badCFG)
- return 0;
- Block = 0;
+ return nullptr;
+ Block = nullptr;
}
// The condition block is the implicit successor for the loop body as well as
@@ -2240,7 +2490,7 @@
// Add an intermediate block between the BodyBlock and the
// EntryConditionBlock to represent the "loop back" transition, for looping
// back to the head of the loop.
- CFGBlock *LoopBackBlock = 0;
+ CFGBlock *LoopBackBlock = nullptr;
Succ = LoopBackBlock = createBlock();
LoopBackBlock->setLoopTarget(S);
@@ -2253,7 +2503,7 @@
BodyBlock = ContinueJumpTarget.block; // can happen for "for (X in Y) ;"
else if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
}
// This new body block is a successor to our "exit" condition block.
@@ -2285,9 +2535,9 @@
// for diagnostic clients.
if (SyncBlock) {
if (badCFG)
- return 0;
+ return nullptr;
- Block = 0;
+ Block = nullptr;
Succ = SyncBlock;
}
@@ -2330,7 +2580,7 @@
}
CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
- CFGBlock *LoopSuccessor = NULL;
+ CFGBlock *LoopSuccessor = nullptr;
// Save local scope position because in case of condition variable ScopePos
// won't be restored when traversing AST.
@@ -2348,14 +2598,14 @@
// block.
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
LoopSuccessor = Block;
- Block = 0;
+ Block = nullptr;
} else {
LoopSuccessor = Succ;
}
- CFGBlock *BodyBlock = 0, *TransitionBlock = 0;
+ CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
// Process the loop body.
{
@@ -2389,13 +2639,13 @@
if (!BodyBlock)
BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;"
else if (Block && badCFG)
- return 0;
+ return nullptr;
}
// Because of short-circuit evaluation, the condition of the loop can span
// multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
// evaluate the condition.
- CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0;
+ CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
do {
Expr *C = W->getCond();
@@ -2431,16 +2681,17 @@
}
if (Block && badCFG)
- return 0;
+ return nullptr;
// See if this is a known constant.
const TryResult& KnownVal = tryEvaluateBool(C);
// Add the loop body entry as a successor to the condition.
- addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock);
+ addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
// Link up the condition block with the code that follows the loop. (the
// false branch).
- addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
+ addSuccessor(ExitConditionBlock,
+ KnownVal.isTrue() ? nullptr : LoopSuccessor);
} while(false);
@@ -2449,7 +2700,7 @@
// There can be no more statements in the condition block since we loop back
// to this block. NULL out Block to force lazy creation of another block.
- Block = NULL;
+ Block = nullptr;
// Return the condition block, which is the dominating block for the loop.
Succ = EntryConditionBlock;
@@ -2469,7 +2720,7 @@
// If we were in the middle of a block we stop processing that block.
if (badCFG)
- return 0;
+ return nullptr;
// Create the new block.
Block = createBlock(false);
@@ -2485,7 +2736,7 @@
CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
// If we were in the middle of a block we stop processing that block.
if (badCFG)
- return 0;
+ return nullptr;
// Create the new block.
Block = createBlock(false);
@@ -2503,13 +2754,13 @@
}
CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
- CFGBlock *LoopSuccessor = NULL;
+ CFGBlock *LoopSuccessor = nullptr;
// "do...while" is a control-flow statement. Thus we stop processing the
// current block.
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
LoopSuccessor = Block;
} else
LoopSuccessor = Succ;
@@ -2530,7 +2781,7 @@
EntryConditionBlock = addStmt(C);
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
}
}
@@ -2541,7 +2792,7 @@
const TryResult &KnownVal = tryEvaluateBool(D->getCond());
// Process the loop body.
- CFGBlock *BodyBlock = NULL;
+ CFGBlock *BodyBlock = nullptr;
{
assert(D->getBody());
@@ -2557,7 +2808,7 @@
BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
// NULL out Block to force lazy instantiation of blocks for the body.
- Block = NULL;
+ Block = nullptr;
// If body is not a compound statement create implicit scope
// and add destructors.
@@ -2571,7 +2822,7 @@
BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
else if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
}
if (!KnownVal.isFalse()) {
@@ -2580,7 +2831,7 @@
// empty block to represent the transition block for looping back to the
// head of the loop.
// FIXME: Can we do this more efficiently without adding another block?
- Block = NULL;
+ Block = nullptr;
Succ = BodyBlock;
CFGBlock *LoopBackBlock = createBlock();
LoopBackBlock->setLoopTarget(D);
@@ -2589,16 +2840,16 @@
addSuccessor(ExitConditionBlock, LoopBackBlock);
}
else
- addSuccessor(ExitConditionBlock, NULL);
+ addSuccessor(ExitConditionBlock, nullptr);
}
// Link up the condition block with the code that follows the loop.
// (the false branch).
- addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
+ addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
// There can be no more statements in the body block(s) since we loop back to
// the body. NULL out Block to force lazy creation of another block.
- Block = NULL;
+ Block = nullptr;
// Return the loop body, which is the dominating block for the loop.
Succ = BodyBlock;
@@ -2609,7 +2860,7 @@
// "continue" is a control-flow statement. Thus we stop processing the
// current block.
if (badCFG)
- return 0;
+ return nullptr;
// Now create a new block that ends with the continue statement.
Block = createBlock(false);
@@ -2639,7 +2890,7 @@
if (E->isArgumentType()) {
for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr());
- VA != 0; VA = FindVA(VA->getElementType().getTypePtr()))
+ VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr()))
lastBlock = addStmt(VA->getSizeExpr());
}
return lastBlock;
@@ -2658,7 +2909,7 @@
CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
// "switch" is a control-flow statement. Thus we stop processing the current
// block.
- CFGBlock *SwitchSuccessor = NULL;
+ CFGBlock *SwitchSuccessor = nullptr;
// Save local scope position because in case of condition variable ScopePos
// won't be restored when traversing AST.
@@ -2674,7 +2925,7 @@
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
SwitchSuccessor = Block;
} else SwitchSuccessor = Succ;
@@ -2700,7 +2951,7 @@
// up to the switch. We also don't keep a pointer to the body, since all
// control-flow from the switch goes to case/default statements.
assert(Terminator->getBody() && "switch must contain a non-NULL body");
- Block = NULL;
+ Block = nullptr;
// For pruning unreachable case statements, save the current state
// for tracking the condition value.
@@ -2712,7 +2963,7 @@
Expr::EvalResult result;
bool b = tryEvaluate(Terminator->getCond(), result);
SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond,
- b ? &result : 0);
+ b ? &result : nullptr);
// If body is not a compound statement create implicit scope
// and add destructors.
@@ -2722,7 +2973,7 @@
addStmt(Terminator->getBody());
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
}
// If we have no "default:" case, the default transition is to the code
@@ -2795,7 +3046,7 @@
CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
// CaseStmts are essentially labels, so they are the first statement in a
// block.
- CFGBlock *TopBlock = 0, *LastBlock = 0;
+ CFGBlock *TopBlock = nullptr, *LastBlock = nullptr;
if (Stmt *Sub = CS->getSubStmt()) {
// For deeply nested chains of CaseStmts, instead of doing a recursion
@@ -2813,7 +3064,7 @@
addSuccessor(SwitchTerminatedBlock,
shouldAddCase(switchExclusivelyCovered, switchCond,
CS, *Context)
- ? currentBlock : 0);
+ ? currentBlock : nullptr);
LastBlock = currentBlock;
CS = cast<CaseStmt>(Sub);
@@ -2832,7 +3083,7 @@
CaseBlock->setLabel(CS);
if (badCFG)
- return 0;
+ return nullptr;
// Add this block to the list of successors for the block with the switch
// statement.
@@ -2842,7 +3093,7 @@
CS, *Context));
// We set Block to NULL to allow lazy creation of a new block (if necessary)
- Block = NULL;
+ Block = nullptr;
if (TopBlock) {
addSuccessor(LastBlock, CaseBlock);
@@ -2869,7 +3120,7 @@
DefaultCaseBlock->setLabel(Terminator);
if (badCFG)
- return 0;
+ return nullptr;
// Unlike case statements, we don't add the default block to the successors
// for the switch statement immediately. This is done when we finish
@@ -2878,7 +3129,7 @@
// be the last successor of a switch-terminated block.
// We set Block to NULL to allow lazy creation of a new block (if necessary)
- Block = NULL;
+ Block = nullptr;
// This block is now the implicit successor of other blocks.
Succ = DefaultCaseBlock;
@@ -2889,11 +3140,11 @@
CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
// "try"/"catch" is a control-flow statement. Thus we stop processing the
// current block.
- CFGBlock *TrySuccessor = NULL;
+ CFGBlock *TrySuccessor = nullptr;
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
TrySuccessor = Block;
} else TrySuccessor = Succ;
@@ -2909,13 +3160,13 @@
// The code after the try is the implicit successor.
Succ = TrySuccessor;
CXXCatchStmt *CS = Terminator->getHandler(h);
- if (CS->getExceptionDecl() == 0) {
+ if (CS->getExceptionDecl() == nullptr) {
HasCatchAll = true;
}
- Block = NULL;
+ Block = nullptr;
CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
- if (CatchBlock == 0)
- return 0;
+ if (!CatchBlock)
+ return nullptr;
// Add this block to the list of successors for the block with the try
// statement.
addSuccessor(NewTryTerminatedBlock, CatchBlock);
@@ -2935,7 +3186,7 @@
cfg->addTryDispatchBlock(TryTerminatedBlock);
assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
- Block = NULL;
+ Block = nullptr;
return addStmt(Terminator->getTryBlock());
}
@@ -2974,10 +3225,10 @@
// Bail out if the CFG is bad.
if (badCFG)
- return 0;
+ return nullptr;
// We set Block to NULL to allow lazy creation of a new block (if necessary)
- Block = NULL;
+ Block = nullptr;
return CatchBlock;
}
@@ -3010,10 +3261,10 @@
// "for" is a control-flow statement. Thus we stop processing the current
// block.
- CFGBlock *LoopSuccessor = NULL;
+ CFGBlock *LoopSuccessor = nullptr;
if (Block) {
if (badCFG)
- return 0;
+ return nullptr;
LoopSuccessor = Block;
} else
LoopSuccessor = Succ;
@@ -3032,7 +3283,7 @@
Block = ConditionBlock;
CFGBlock *BeginConditionBlock = addStmt(C);
if (badCFG)
- return 0;
+ return nullptr;
assert(BeginConditionBlock == ConditionBlock &&
"condition block in for-range was unexpectedly complex");
(void)BeginConditionBlock;
@@ -3058,7 +3309,7 @@
// Generate increment code in its own basic block. This is the target of
// continue statements.
- Block = 0;
+ Block = nullptr;
Succ = addStmt(S->getInc());
ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
@@ -3069,9 +3320,8 @@
// Finish up the increment block and prepare to start the loop body.
assert(Block);
if (badCFG)
- return 0;
- Block = 0;
-
+ return nullptr;
+ Block = nullptr;
// Add implicit scope and dtors for loop variable.
addLocalScopeAndDtors(S->getLoopVarStmt());
@@ -3079,18 +3329,19 @@
// Populate a new block to contain the loop body and loop variable.
addStmt(S->getBody());
if (badCFG)
- return 0;
+ return nullptr;
CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
if (badCFG)
- return 0;
-
+ return nullptr;
+
// This new body block is a successor to our condition block.
- addSuccessor(ConditionBlock, KnownVal.isFalse() ? 0 : LoopVarStmtBlock);
+ addSuccessor(ConditionBlock,
+ KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
}
// Link up the condition block with the code that follows the loop (the
// false branch).
- addSuccessor(ConditionBlock, KnownVal.isTrue() ? 0 : LoopSuccessor);
+ addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
// Add the initialization statements.
Block = createBlock();
@@ -3204,7 +3455,7 @@
// IndirectGoto is a control-flow statement. Thus we stop processing the
// current block and create a new one.
if (badCFG)
- return 0;
+ return nullptr;
Block = createBlock(false);
Block->setTerminator(I);
@@ -3218,7 +3469,7 @@
tryAgain:
if (!E) {
badCFG = true;
- return NULL;
+ return nullptr;
}
switch (E->getStmtClass()) {
default:
@@ -3273,15 +3524,15 @@
autoCreateBlock();
CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS());
if (badCFG)
- return NULL;
+ return nullptr;
Succ = ConfluenceBlock;
- Block = NULL;
+ Block = nullptr;
CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS());
if (RHSBlock) {
if (badCFG)
- return NULL;
+ return nullptr;
// If RHS expression did produce destructors we need to connect created
// blocks to CFG in same manner as for binary operator itself.
@@ -3301,12 +3552,12 @@
// Link LHSBlock with RHSBlock exactly the same way as for binary operator
// itself.
if (E->getOpcode() == BO_LOr) {
- addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
- addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
+ addSuccessor(LHSBlock, KnownVal.isTrue() ? nullptr : ConfluenceBlock);
+ addSuccessor(LHSBlock, KnownVal.isFalse() ? nullptr : RHSBlock);
} else {
assert (E->getOpcode() == BO_LAnd);
- addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
- addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
+ addSuccessor(LHSBlock, KnownVal.isFalse() ? nullptr : RHSBlock);
+ addSuccessor(LHSBlock, KnownVal.isTrue() ? nullptr : ConfluenceBlock);
}
Block = LHSBlock;
@@ -3366,29 +3617,29 @@
autoCreateBlock();
CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond());
if (badCFG)
- return NULL;
+ return nullptr;
if (BinaryConditionalOperator *BCO
= dyn_cast<BinaryConditionalOperator>(E)) {
ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon());
if (badCFG)
- return NULL;
+ return nullptr;
}
// Try to add block with destructors for LHS expression.
- CFGBlock *LHSBlock = NULL;
+ CFGBlock *LHSBlock = nullptr;
Succ = ConfluenceBlock;
- Block = NULL;
+ Block = nullptr;
LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary);
if (badCFG)
- return NULL;
+ return nullptr;
// Try to add block with destructors for RHS expression;
Succ = ConfluenceBlock;
- Block = NULL;
+ Block = nullptr;
CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(),
BindToTemporary);
if (badCFG)
- return NULL;
+ return nullptr;
if (!RHSBlock && !LHSBlock) {
// If neither LHS nor RHS expression had temporaries to destroy don't create
@@ -3407,7 +3658,7 @@
if (LHSBlock) {
addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
} else if (KnownVal.isFalse()) {
- addSuccessor(Block, NULL);
+ addSuccessor(Block, nullptr);
} else {
addSuccessor(Block, ConfluenceBlock);
std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end());
@@ -3488,7 +3739,7 @@
case CFGElement::MemberDtor:
// Not yet supported.
- return 0;
+ return nullptr;
}
llvm_unreachable("getKind() returned bogus value");
}
@@ -3504,13 +3755,13 @@
//===----------------------------------------------------------------------===//
CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable)
- : ReachableBlock(IsReachable ? B : 0),
- UnreachableBlock(!IsReachable ? B : 0,
+ : ReachableBlock(IsReachable ? B : nullptr),
+ UnreachableBlock(!IsReachable ? B : nullptr,
B && IsReachable ? AB_Normal : AB_Unreachable) {}
CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock)
: ReachableBlock(B),
- UnreachableBlock(B == AlternateBlock ? 0 : AlternateBlock,
+ UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
B == AlternateBlock ? AB_Alternate : AB_Normal) {}
void CFGBlock::addSuccessor(AdjacentBlock Succ,
@@ -4110,16 +4361,16 @@
/// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
void CFGBlock::printTerminator(raw_ostream &OS,
const LangOptions &LO) const {
- CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO));
+ CFGBlockTerminatorPrint TPrinter(OS, nullptr, PrintingPolicy(LO));
TPrinter.print(getTerminator());
}
Stmt *CFGBlock::getTerminatorCondition(bool StripParens) {
Stmt *Terminator = this->Terminator;
if (!Terminator)
- return NULL;
+ return nullptr;
- Expr *E = NULL;
+ Expr *E = nullptr;
switch (Terminator->getStmtClass()) {
default:
@@ -4176,7 +4427,7 @@
if (!StripParens)
return E;
- return E ? E->IgnoreParens() : NULL;
+ return E ? E->IgnoreParens() : nullptr;
}
//===----------------------------------------------------------------------===//
@@ -4193,7 +4444,7 @@
StmtPrinterHelper H(this, LO);
GraphHelper = &H;
llvm::ViewGraph(this,"CFG");
- GraphHelper = NULL;
+ GraphHelper = nullptr;
#endif
}
diff --git a/lib/Analysis/CFGStmtMap.cpp b/lib/Analysis/CFGStmtMap.cpp
index 87c2f5b..19b8019 100644
--- a/lib/Analysis/CFGStmtMap.cpp
+++ b/lib/Analysis/CFGStmtMap.cpp
@@ -42,8 +42,8 @@
X = PM->getParentIgnoreParens(X);
}
-
- return 0;
+
+ return nullptr;
}
static void Accumulate(SMap &SM, CFGBlock *B) {
@@ -77,7 +77,7 @@
CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
if (!C || !PM)
- return 0;
+ return nullptr;
SMap *SM = new SMap();
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 9630bc0..5e97ce2 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -23,6 +23,9 @@
ReachableCode.cpp
ScanfFormatString.cpp
ThreadSafety.cpp
+ ThreadSafetyCommon.cpp
+ ThreadSafetyLogical.cpp
+ ThreadSafetyTIL.cpp
UninitializedValues.cpp
LINK_LIBS
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index 649ba57..f41a96d 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -10,8 +10,6 @@
// This file defines the AST-based CallGraph.
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "CallGraph"
-
#include "clang/Analysis/CallGraph.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -22,6 +20,8 @@
using namespace clang;
+#define DEBUG_TYPE "CallGraph"
+
STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");
STATISTIC(NumBlockCallEdges, "Number of block call edges");
@@ -49,7 +49,7 @@
return Block->getBlockDecl();
}
- return 0;
+ return nullptr;
}
void addCalledDecl(Decl *D) {
@@ -70,7 +70,7 @@
Selector Sel = ME->getSelector();
// Find the callee definition within the same translation unit.
- Decl *D = 0;
+ Decl *D = nullptr;
if (ME->isInstanceMessage())
D = IDecl->lookupPrivateMethod(Sel);
else
@@ -101,7 +101,7 @@
}
CallGraph::CallGraph() {
- Root = getOrInsertNode(0);
+ Root = getOrInsertNode(nullptr);
}
CallGraph::~CallGraph() {
@@ -147,7 +147,7 @@
CallGraphNode *CallGraph::getNode(const Decl *F) const {
FunctionMapTy::const_iterator I = FunctionMap.find(F);
- if (I == FunctionMap.end()) return 0;
+ if (I == FunctionMap.end()) return nullptr;
return I->second;
}
@@ -158,7 +158,7 @@
Node = new CallGraphNode(F);
// Make Root node a parent of all functions to make sure all are reachable.
- if (F != 0)
+ if (F)
Root->addCallee(Node, this);
return Node;
}
diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index 7b6ad57..2b2da2c 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -57,11 +57,9 @@
static SourceLocation getFirstStmtLoc(const CFGBlock *Block) {
// Find the source location of the first statement in the block, if the block
// is not empty.
- for (CFGBlock::const_iterator BI = Block->begin(), BE = Block->end();
- BI != BE; ++BI) {
- if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>())
+ for (const auto &B : *Block)
+ if (Optional<CFGStmt> CS = B.getAs<CFGStmt>())
return CS->getStmt()->getLocStart();
- }
// Block is empty.
// If we have one successor, return the first statement in that block
@@ -115,14 +113,10 @@
static bool isCallableInState(const CallableWhenAttr *CWAttr,
ConsumedState State) {
- CallableWhenAttr::callableState_iterator I = CWAttr->callableState_begin(),
- E = CWAttr->callableState_end();
-
- for (; I != E; ++I) {
-
+ for (const auto &S : CWAttr->callableStates()) {
ConsumedState MappedAttrState = CS_None;
-
- switch (*I) {
+
+ switch (S) {
case CallableWhenAttr::Unknown:
MappedAttrState = CS_Unknown;
break;
@@ -716,7 +710,7 @@
LTest = LEntry->second.getVarTest();
} else {
- LTest.Var = NULL;
+ LTest.Var = nullptr;
LTest.TestsFor = CS_None;
}
@@ -724,11 +718,11 @@
RTest = REntry->second.getVarTest();
} else {
- RTest.Var = NULL;
+ RTest.Var = nullptr;
RTest.TestsFor = CS_None;
}
-
- if (!(LTest.Var == NULL && RTest.Var == NULL))
+
+ if (!(LTest.Var == nullptr && RTest.Var == nullptr))
PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
@@ -745,16 +739,6 @@
}
}
-static bool isStdNamespace(const DeclContext *DC) {
- if (!DC->isNamespace()) return false;
- while (DC->getParent()->isNamespace())
- DC = DC->getParent();
- const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
-
- return ND && ND->getName() == "std" &&
- ND->getDeclContext()->isTranslationUnit();
-}
-
void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
const FunctionDecl *FunDecl = Call->getDirectCallee();
if (!FunDecl)
@@ -762,14 +746,13 @@
// Special case for the std::move function.
// TODO: Make this more specific. (Deferred)
- if (Call->getNumArgs() == 1 &&
- FunDecl->getNameAsString() == "move" &&
- isStdNamespace(FunDecl->getDeclContext())) {
+ if (Call->getNumArgs() == 1 && FunDecl->getNameAsString() == "move" &&
+ FunDecl->isInStdNamespace()) {
copyInfo(Call->getArg(0), Call, CS_Consumed);
return;
}
- handleCall(Call, 0, FunDecl);
+ handleCall(Call, nullptr, FunDecl);
propagateReturnType(Call, FunDecl);
}
@@ -1078,9 +1061,9 @@
void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
ConsumedStateMap *StateMap) {
-
- assert(Block != NULL && "Block pointer must not be NULL");
-
+
+ assert(Block && "Block pointer must not be NULL");
+
ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
if (Entry) {
@@ -1102,7 +1085,7 @@
void ConsumedBlockInfo::discardInfo(const CFGBlock *Block) {
unsigned int BlockID = Block->getBlockID();
delete StateMapsArray[BlockID];
- StateMapsArray[BlockID] = NULL;
+ StateMapsArray[BlockID] = nullptr;
}
ConsumedStateMap* ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
@@ -1112,7 +1095,7 @@
if (isBackEdgeTarget(Block)) {
return new ConsumedStateMap(*StateMap);
} else {
- StateMapsArray[Block->getBlockID()] = NULL;
+ StateMapsArray[Block->getBlockID()] = nullptr;
return StateMap;
}
}
@@ -1125,8 +1108,8 @@
}
bool ConsumedBlockInfo::isBackEdgeTarget(const CFGBlock *Block) {
- assert(Block != NULL && "Block pointer must not be NULL");
-
+ assert(Block && "Block pointer must not be NULL");
+
// Anything with less than two predecessors can't be the target of a back
// edge.
if (Block->pred_size() < 2)
@@ -1144,21 +1127,19 @@
void ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc,
ConsumedWarningsHandlerBase &WarningsHandler) const {
- for (VarMapType::const_iterator DMI = VarMap.begin(), DME = VarMap.end();
- DMI != DME; ++DMI) {
-
- if (isa<ParmVarDecl>(DMI->first)) {
- const ParmVarDecl *Param = cast<ParmVarDecl>(DMI->first);
+ for (const auto &DM : VarMap) {
+ if (isa<ParmVarDecl>(DM.first)) {
+ const ParmVarDecl *Param = cast<ParmVarDecl>(DM.first);
const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
if (!RTA)
continue;
ConsumedState ExpectedState = mapReturnTypestateAttrState(RTA);
- if (DMI->second != ExpectedState)
+ if (DM.second != ExpectedState)
WarningsHandler.warnParamReturnTypestateMismatch(BlameLoc,
Param->getNameAsString(), stateToString(ExpectedState),
- stateToString(DMI->second));
+ stateToString(DM.second));
}
}
}
@@ -1194,16 +1175,14 @@
return;
}
- for (VarMapType::const_iterator DMI = Other->VarMap.begin(),
- DME = Other->VarMap.end(); DMI != DME; ++DMI) {
-
- LocalState = this->getState(DMI->first);
+ for (const auto &DM : Other->VarMap) {
+ LocalState = this->getState(DM.first);
if (LocalState == CS_None)
continue;
- if (LocalState != DMI->second)
- VarMap[DMI->first] = CS_Unknown;
+ if (LocalState != DM.second)
+ VarMap[DM.first] = CS_Unknown;
}
}
@@ -1214,18 +1193,16 @@
ConsumedState LocalState;
SourceLocation BlameLoc = getLastStmtLoc(LoopBack);
- for (VarMapType::const_iterator DMI = LoopBackStates->VarMap.begin(),
- DME = LoopBackStates->VarMap.end(); DMI != DME; ++DMI) {
-
- LocalState = this->getState(DMI->first);
+ for (const auto &DM : LoopBackStates->VarMap) {
+ LocalState = this->getState(DM.first);
if (LocalState == CS_None)
continue;
- if (LocalState != DMI->second) {
- VarMap[DMI->first] = CS_Unknown;
- WarningsHandler.warnLoopStateMismatch(
- BlameLoc, DMI->first->getNameAsString());
+ if (LocalState != DM.second) {
+ VarMap[DM.first] = CS_Unknown;
+ WarningsHandler.warnLoopStateMismatch(BlameLoc,
+ DM.first->getNameAsString());
}
}
}
@@ -1245,18 +1222,14 @@
TmpMap[Tmp] = State;
}
-void ConsumedStateMap::remove(const VarDecl *Var) {
- VarMap.erase(Var);
+void ConsumedStateMap::remove(const CXXBindTemporaryExpr *Tmp) {
+ TmpMap.erase(Tmp);
}
bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {
- for (VarMapType::const_iterator DMI = Other->VarMap.begin(),
- DME = Other->VarMap.end(); DMI != DME; ++DMI) {
-
- if (this->getState(DMI->first) != DMI->second)
- return true;
- }
-
+ for (const auto &DM : Other->VarMap)
+ if (this->getState(DM.first) != DM.second)
+ return true;
return false;
}
@@ -1372,7 +1345,7 @@
if (*++SI)
BlockInfo.addInfo(*SI, FalseStates.release());
- CurrStates = NULL;
+ CurrStates = nullptr;
return true;
}
@@ -1396,17 +1369,12 @@
ConsumedStmtVisitor Visitor(AC, *this, CurrStates);
// Add all trackable parameters to the state map.
- for (auto PI : D->params()) {
+ for (const auto *PI : D->params())
Visitor.VisitParmVarDecl(PI);
- }
// Visit all of the function's basic blocks.
- for (PostOrderCFGView::iterator I = SortedGraph->begin(),
- E = SortedGraph->end(); I != E; ++I) {
-
- const CFGBlock *CurrBlock = *I;
-
- if (CurrStates == NULL)
+ for (const auto *CurrBlock : *SortedGraph) {
+ if (!CurrStates)
CurrStates = BlockInfo.getInfo(CurrBlock);
if (!CurrStates) {
@@ -1414,33 +1382,32 @@
} else if (!CurrStates->isReachable()) {
delete CurrStates;
- CurrStates = NULL;
+ CurrStates = nullptr;
continue;
}
Visitor.reset(CurrStates);
// Visit all of the basic block's statements.
- for (CFGBlock::const_iterator BI = CurrBlock->begin(),
- BE = CurrBlock->end(); BI != BE; ++BI) {
-
- switch (BI->getKind()) {
+ for (const auto &B : *CurrBlock) {
+ switch (B.getKind()) {
case CFGElement::Statement:
- Visitor.Visit(BI->castAs<CFGStmt>().getStmt());
+ Visitor.Visit(B.castAs<CFGStmt>().getStmt());
break;
case CFGElement::TemporaryDtor: {
- const CFGTemporaryDtor DTor = BI->castAs<CFGTemporaryDtor>();
+ const CFGTemporaryDtor &DTor = B.castAs<CFGTemporaryDtor>();
const CXXBindTemporaryExpr *BTE = DTor.getBindTemporaryExpr();
Visitor.checkCallability(PropagationInfo(BTE),
DTor.getDestructorDecl(AC.getASTContext()),
BTE->getExprLoc());
+ CurrStates->remove(BTE);
break;
}
case CFGElement::AutomaticObjectDtor: {
- const CFGAutomaticObjDtor DTor = BI->castAs<CFGAutomaticObjDtor>();
+ const CFGAutomaticObjDtor &DTor = B.castAs<CFGAutomaticObjDtor>();
SourceLocation Loc = DTor.getTriggerStmt()->getLocEnd();
const VarDecl *Var = DTor.getVarDecl();
@@ -1455,13 +1422,11 @@
}
}
- CurrStates->clearTemporaries();
-
// TODO: Handle other forms of branching with precision, including while-
// and for-loops. (Deferred)
if (!splitState(CurrBlock, Visitor)) {
- CurrStates->setSource(NULL);
-
+ CurrStates->setSource(nullptr);
+
if (CurrBlock->succ_size() > 1 ||
(CurrBlock->succ_size() == 1 &&
(*CurrBlock->succ_begin())->pred_size() > 1)) {
@@ -1470,9 +1435,9 @@
for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
SE = CurrBlock->succ_end(); SI != SE; ++SI) {
-
- if (*SI == NULL) continue;
-
+
+ if (*SI == nullptr) continue;
+
if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(*SI, CurrBlock,
CurrStates,
@@ -1487,8 +1452,8 @@
if (!OwnershipTaken)
delete CurrStates;
-
- CurrStates = NULL;
+
+ CurrStates = nullptr;
}
}
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp
index 43ecc66..851b97e 100644
--- a/lib/Analysis/FormatString.cpp
+++ b/lib/Analysis/FormatString.cpp
@@ -507,7 +507,7 @@
case None:
return "";
}
- return NULL;
+ return nullptr;
}
//===----------------------------------------------------------------------===//
@@ -539,7 +539,7 @@
case nArg: return "n";
case PercentArg: return "%";
case ScanListArg: return "[";
- case InvalidSpecifier: return NULL;
+ case InvalidSpecifier: return nullptr;
// POSIX unicode extensions.
case CArg: return "C";
@@ -551,7 +551,7 @@
// GlibC specific specifiers.
case PrintErrno: return "m";
}
- return NULL;
+ return nullptr;
}
Optional<ConversionSpecifier>
diff --git a/lib/Analysis/FormatStringParsing.h b/lib/Analysis/FormatStringParsing.h
index 6b25123..fba3180 100644
--- a/lib/Analysis/FormatStringParsing.h
+++ b/lib/Analysis/FormatStringParsing.h
@@ -53,14 +53,14 @@
bool Stop;
public:
SpecifierResult(bool stop = false)
- : Start(0), Stop(stop) {}
+ : Start(nullptr), Stop(stop) {}
SpecifierResult(const char *start,
const T &fs)
: FS(fs), Start(start), Stop(false) {}
const char *getStart() const { return Start; }
bool shouldStop() const { return Stop; }
- bool hasValue() const { return Start != 0; }
+ bool hasValue() const { return Start != nullptr; }
const T &getValue() const {
assert(hasValue());
return FS;
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index b26d4fb..3d6fc03 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -72,7 +72,7 @@
const CFGBlock *DataflowWorklist::dequeue() {
if (worklist.empty())
- return 0;
+ return nullptr;
const CFGBlock *b = worklist.pop_back_val();
enqueuedBlocks[b->getBlockID()] = false;
return b;
@@ -94,10 +94,10 @@
LiveVariables::LivenessValues
merge(LiveVariables::LivenessValues valsA,
LiveVariables::LivenessValues valsB);
-
- LiveVariables::LivenessValues runOnBlock(const CFGBlock *block,
- LiveVariables::LivenessValues val,
- LiveVariables::Observer *obs = 0);
+
+ LiveVariables::LivenessValues
+ runOnBlock(const CFGBlock *block, LiveVariables::LivenessValues val,
+ LiveVariables::Observer *obs = nullptr);
void dumpBlockLiveness(const SourceManager& M);
@@ -224,8 +224,8 @@
ty = VT->getElementType().getTypePtr();
}
-
- return 0;
+
+ return nullptr;
}
static const Stmt *LookThroughStmt(const Stmt *S) {
@@ -291,7 +291,7 @@
const DeclStmt *DS = cast<DeclStmt>(S);
if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) {
for (const VariableArrayType* VA = FindVA(VD->getType());
- VA != 0; VA = FindVA(VA->getElementType())) {
+ VA != nullptr; VA = FindVA(VA->getElementType())) {
AddLiveStmt(val.liveStmts, LV.SSetFact, VA->getSizeExpr());
}
}
@@ -384,8 +384,8 @@
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
// Kill the iteration variable.
- DeclRefExpr *DR = 0;
- const VarDecl *VD = 0;
+ DeclRefExpr *DR = nullptr;
+ const VarDecl *VD = nullptr;
Stmt *element = OS->getElement();
if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
@@ -493,12 +493,12 @@
// No CFG? Bail out.
CFG *cfg = AC.getCFG();
if (!cfg)
- return 0;
+ return nullptr;
// The analysis currently has scalability issues for very large CFGs.
// Bail out if it looks too large.
if (cfg->getNumBlockIDs() > 300000)
- return 0;
+ return nullptr;
LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);
diff --git a/lib/Analysis/PostOrderCFGView.cpp b/lib/Analysis/PostOrderCFGView.cpp
index cfd66f7..5a3c8182 100644
--- a/lib/Analysis/PostOrderCFGView.cpp
+++ b/lib/Analysis/PostOrderCFGView.cpp
@@ -31,7 +31,7 @@
PostOrderCFGView *PostOrderCFGView::create(AnalysisDeclContext &ctx) {
const CFG *cfg = ctx.getCFG();
if (!cfg)
- return 0;
+ return nullptr;
return new PostOrderCFGView(cfg);
}
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index f21b407..082a832 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -60,7 +60,7 @@
using namespace clang::analyze_printf;
const char *I = Beg;
- const char *Start = 0;
+ const char *Start = nullptr;
UpdateOnReturn <const char*> UpdateBeg(Beg, I);
// Look for a '%' character that indicates the start of a format specifier.
@@ -124,7 +124,7 @@
// Look for the field width (if any).
if (ParseFieldWidth(H, FS, Start, I, E,
- FS.usesPositionalArg() ? 0 : &argIndex))
+ FS.usesPositionalArg() ? nullptr : &argIndex))
return true;
if (I == E) {
@@ -142,7 +142,7 @@
}
if (ParsePrecision(H, FS, Start, I, E,
- FS.usesPositionalArg() ? 0 : &argIndex))
+ FS.usesPositionalArg() ? nullptr : &argIndex))
return true;
if (I == E) {
diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp
index 314ce7c..3f96ca8 100644
--- a/lib/Analysis/PseudoConstantAnalysis.cpp
+++ b/lib/Analysis/PseudoConstantAnalysis.cpp
@@ -70,7 +70,7 @@
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
return DR->getDecl();
else
- return 0;
+ return nullptr;
}
void PseudoConstantAnalysis::RunAnalysis() {
diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index 3cc8ae4..b4a72a7 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/lib/Analysis/ReachableCode.cpp
@@ -59,32 +59,57 @@
}
static bool isDeadReturn(const CFGBlock *B, const Stmt *S) {
- // Look to see if the block ends with a 'return', and see if 'S'
- // is a substatement. The 'return' may not be the last element in
- // the block because of destructors.
- for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
- I != E; ++I) {
- if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
- if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
- if (RS == S)
- return true;
- if (const Expr *RE = RS->getRetValue()) {
- RE = RE->IgnoreParenCasts();
- if (RE == S)
+ // Look to see if the current control flow ends with a 'return', and see if
+ // 'S' is a substatement. The 'return' may not be the last element in the
+ // block, or may be in a subsequent block because of destructors.
+ const CFGBlock *Current = B;
+ while (true) {
+ for (CFGBlock::const_reverse_iterator I = Current->rbegin(),
+ E = Current->rend();
+ I != E; ++I) {
+ if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
+ if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
+ if (RS == S)
return true;
- ParentMap PM(const_cast<Expr*>(RE));
- // If 'S' is in the ParentMap, it is a subexpression of
- // the return statement. Note also that we are restricting
- // to looking at return statements in the same CFGBlock,
- // so this will intentionally not catch cases where the
- // return statement contains nested control-flow.
- return PM.getParent(S);
+ if (const Expr *RE = RS->getRetValue()) {
+ RE = RE->IgnoreParenCasts();
+ if (RE == S)
+ return true;
+ ParentMap PM(const_cast<Expr *>(RE));
+ // If 'S' is in the ParentMap, it is a subexpression of
+ // the return statement.
+ return PM.getParent(S);
+ }
}
+ break;
}
- break;
+ }
+ // Note also that we are restricting the search for the return statement
+ // to stop at control-flow; only part of a return statement may be dead,
+ // without the whole return statement being dead.
+ if (Current->getTerminator().isTemporaryDtorsBranch()) {
+ // Temporary destructors have a predictable control flow, thus we want to
+ // look into the next block for the return statement.
+ // We look into the false branch, as we know the true branch only contains
+ // the call to the destructor.
+ assert(Current->succ_size() == 2);
+ Current = *(Current->succ_begin() + 1);
+ } else if (!Current->getTerminator() && Current->succ_size() == 1) {
+ // If there is only one successor, we're not dealing with outgoing control
+ // flow. Thus, look into the next block.
+ Current = *Current->succ_begin();
+ if (Current->pred_size() > 1) {
+ // If there is more than one predecessor, we're dealing with incoming
+ // control flow - if the return statement is in that block, it might
+ // well be reachable via a different control flow, thus it's not dead.
+ return false;
+ }
+ } else {
+ // We hit control flow or a dead end. Stop searching.
+ return false;
}
}
- return false;
+ llvm_unreachable("Broke out of infinite loop.");
}
static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM) {
@@ -139,6 +164,9 @@
if (!S)
return false;
+ if (const Expr *Ex = dyn_cast<Expr>(S))
+ S = Ex->IgnoreCasts();
+
// Special case looking for the sigil '()' around an integer literal.
if (const ParenExpr *PE = dyn_cast<ParenExpr>(S))
if (!PE->getLocStart().isMacroID())
@@ -146,7 +174,7 @@
IncludeIntegers, true);
if (const Expr *Ex = dyn_cast<Expr>(S))
- S = Ex->IgnoreParenCasts();
+ S = Ex->IgnoreCasts();
bool IgnoreYES_NO = false;
@@ -399,7 +427,7 @@
}
}
- return 0;
+ return nullptr;
}
static int SrcCmp(const std::pair<const CFGBlock *, const Stmt *> *p1,
@@ -603,7 +631,7 @@
unsigned ScanReachableFromBlock(const CFGBlock *Start,
llvm::BitVector &Reachable) {
- return scanFromBlock(Start, Reachable, /* SourceManager* */ 0, false);
+ return scanFromBlock(Start, Reachable, /* SourceManager* */ nullptr, false);
}
void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp
index 3ff7f0a..ed28627 100644
--- a/lib/Analysis/ScanfFormatString.cpp
+++ b/lib/Analysis/ScanfFormatString.cpp
@@ -50,6 +50,15 @@
}
}
+ // Special case: "^]" are the first characters.
+ if (I + 1 != E && I[0] == '^' && I[1] == ']') {
+ I += 2;
+ if (I == E) {
+ H.HandleIncompleteScanList(start, I - 1);
+ return true;
+ }
+ }
+
// Look for a ']' character which denotes the end of the scan list.
while (*I != ']') {
if (++I == E) {
@@ -73,7 +82,7 @@
using namespace clang::analyze_scanf;
const char *I = Beg;
- const char *Start = 0;
+ const char *Start = nullptr;
UpdateOnReturn <const char*> UpdateBeg(Beg, I);
// Look for a '%' character that indicates the start of a format specifier.
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index fd804eb..11df61f 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -10,18 +10,22 @@
// A intra-procedural analysis for thread safety (e.g. deadlocks and race
// conditions), based off of an annotation system.
//
-// See http://clang.llvm.org/docs/LanguageExtensions.html#thread-safety-annotation-checking
+// See http://clang.llvm.org/docs/ThreadSafetyAnalysis.html
// for more information.
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/Analyses/ThreadSafety.h"
+#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
@@ -173,8 +177,8 @@
CallingContext* PrevCtx; // The previous context; or 0 if none.
CallingContext(const NamedDecl *D)
- : AttrDecl(D), SelfArg(0), SelfArrow(false), NumArgs(0), FunArgs(0),
- PrevCtx(0) {}
+ : AttrDecl(D), SelfArg(nullptr), SelfArrow(false), NumArgs(0),
+ FunArgs(nullptr), PrevCtx(nullptr) {}
};
typedef SmallVector<SExprNode, 4> NodeVector;
@@ -185,7 +189,7 @@
NodeVector NodeVec;
private:
- unsigned make(ExprOp O, unsigned F = 0, const void *D = 0) {
+ unsigned make(ExprOp O, unsigned F = 0, const void *D = nullptr) {
NodeVec.push_back(SExprNode(O, F, D));
return NodeVec.size() - 1;
}
@@ -232,7 +236,7 @@
return D; // Method does not override anything
D = *I; // FIXME: this does not work with multiple inheritance.
}
- return 0;
+ return nullptr;
}
unsigned makeMCall(unsigned NumArgs, const CXXMethodDecl *D) {
@@ -268,8 +272,8 @@
/// NDeref returns the number of Derefence and AddressOf operations
/// preceding the Expr; this is used to decide whether to pretty-print
/// SExprs with . or ->.
- unsigned buildSExpr(const Expr *Exp, CallingContext* CallCtx,
- int* NDeref = 0) {
+ unsigned buildSExpr(const Expr *Exp, CallingContext *CallCtx,
+ int *NDeref = nullptr) {
if (!Exp)
return 0;
@@ -366,7 +370,7 @@
}
}
unsigned NumCallArgs = CE->getNumArgs();
- unsigned Root = makeCall(NumCallArgs, 0);
+ unsigned Root = makeCall(NumCallArgs, nullptr);
unsigned Sz = buildSExpr(CE->getCallee(), CallCtx);
const Expr* const* CallArgs = CE->getArgs();
for (unsigned i = 0; i < NumCallArgs; ++i) {
@@ -459,7 +463,7 @@
/// occurs.
/// \param D The declaration to which the lock/unlock attribute is attached.
void buildSExprFromExpr(const Expr *MutexExp, const Expr *DeclExp,
- const NamedDecl *D, VarDecl *SelfDecl = 0) {
+ const NamedDecl *D, VarDecl *SelfDecl = nullptr) {
CallingContext CallCtx(D);
if (MutexExp) {
@@ -476,8 +480,8 @@
}
// If we are processing a raw attribute expression, with no substitutions.
- if (DeclExp == 0) {
- buildSExpr(MutexExp, 0);
+ if (!DeclExp) {
+ buildSExpr(MutexExp, nullptr);
return;
}
@@ -497,7 +501,7 @@
CallCtx.FunArgs = CE->getArgs();
} else if (const CXXConstructExpr *CE =
dyn_cast<CXXConstructExpr>(DeclExp)) {
- CallCtx.SelfArg = 0; // Will be set below
+ CallCtx.SelfArg = nullptr; // Will be set below
CallCtx.NumArgs = CE->getNumArgs();
CallCtx.FunArgs = CE->getArgs();
} else if (D && isa<CXXDestructorDecl>(D)) {
@@ -513,16 +517,16 @@
CallCtx.SelfArg = &SelfDRE;
// If the attribute has no arguments, then assume the argument is "this".
- if (MutexExp == 0)
- buildSExpr(CallCtx.SelfArg, 0);
+ if (!MutexExp)
+ buildSExpr(CallCtx.SelfArg, nullptr);
else // For most attributes.
buildSExpr(MutexExp, &CallCtx);
return;
}
// If the attribute has no arguments, then assume the argument is "this".
- if (MutexExp == 0)
- buildSExpr(CallCtx.SelfArg, 0);
+ if (!MutexExp)
+ buildSExpr(CallCtx.SelfArg, nullptr);
else // For most attributes.
buildSExpr(MutexExp, &CallCtx);
}
@@ -540,8 +544,8 @@
/// occurs.
/// \param D The declaration to which the lock/unlock attribute is attached.
/// Caller must check isValid() after construction.
- SExpr(const Expr* MutexExp, const Expr *DeclExp, const NamedDecl* D,
- VarDecl *SelfDecl=0) {
+ SExpr(const Expr *MutexExp, const Expr *DeclExp, const NamedDecl *D,
+ VarDecl *SelfDecl = nullptr) {
buildSExprFromExpr(MutexExp, DeclExp, D, SelfDecl);
}
@@ -845,45 +849,38 @@
return false;
}
- // Returns an iterator
iterator findLockIter(FactManager &FM, const SExpr &M) {
- for (iterator I = begin(), E = end(); I != E; ++I) {
- const SExpr &Exp = FM[*I].MutID;
- if (Exp.matches(M))
- return I;
- }
- return end();
+ return std::find_if(begin(), end(), [&](FactID ID) {
+ return FM[ID].MutID.matches(M);
+ });
}
- LockData* findLock(FactManager &FM, const SExpr &M) const {
- for (const_iterator I = begin(), E = end(); I != E; ++I) {
- const SExpr &Exp = FM[*I].MutID;
- if (Exp.matches(M))
- return &FM[*I].LDat;
- }
- return 0;
+ LockData *findLock(FactManager &FM, const SExpr &M) const {
+ auto I = std::find_if(begin(), end(), [&](FactID ID) {
+ return FM[ID].MutID.matches(M);
+ });
+
+ return I != end() ? &FM[*I].LDat : nullptr;
}
- LockData* findLockUniv(FactManager &FM, const SExpr &M) const {
- for (const_iterator I = begin(), E = end(); I != E; ++I) {
- const SExpr &Exp = FM[*I].MutID;
- if (Exp.matches(M) || Exp.isUniversal())
- return &FM[*I].LDat;
- }
- return 0;
+ LockData *findLockUniv(FactManager &FM, const SExpr &M) const {
+ auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool {
+ const SExpr &Expr = FM[ID].MutID;
+ return Expr.isUniversal() || Expr.matches(M);
+ });
+
+ return I != end() ? &FM[*I].LDat : nullptr;
}
- FactEntry* findPartialMatch(FactManager &FM, const SExpr &M) const {
- for (const_iterator I=begin(), E=end(); I != E; ++I) {
- const SExpr& Exp = FM[*I].MutID;
- if (Exp.partiallyMatches(M)) return &FM[*I];
- }
- return 0;
+ FactEntry *findPartialMatch(FactManager &FM, const SExpr &M) const {
+ auto I = std::find_if(begin(), end(), [&](FactID ID) {
+ return FM[ID].MutID.partiallyMatches(M);
+ });
+
+ return I != end() ? &FM[*I] : nullptr;
}
};
-
-
/// A Lockset maps each SExpr (defined above) to information about how it has
/// been locked.
typedef llvm::ImmutableMap<SExpr, LockData> Lockset;
@@ -965,7 +962,7 @@
// Create reference to previous definition
VarDefinition(const NamedDecl *D, unsigned R, Context C)
- : Dec(D), Exp(0), Ref(R), Ctx(C)
+ : Dec(D), Exp(nullptr), Ref(R), Ctx(C)
{ }
};
@@ -978,14 +975,14 @@
public:
LocalVariableMap() {
// index 0 is a placeholder for undefined variables (aka phi-nodes).
- VarDefinitions.push_back(VarDefinition(0, 0u, getEmptyContext()));
+ VarDefinitions.push_back(VarDefinition(nullptr, 0u, getEmptyContext()));
}
/// Look up a definition, within the given context.
const VarDefinition* lookup(const NamedDecl *D, Context Ctx) {
const unsigned *i = Ctx.lookup(D);
if (!i)
- return 0;
+ return nullptr;
assert(*i < VarDefinitions.size());
return &VarDefinitions[*i];
}
@@ -996,7 +993,7 @@
const Expr* lookupExpr(const NamedDecl *D, Context &Ctx) {
const unsigned *P = Ctx.lookup(D);
if (!P)
- return 0;
+ return nullptr;
unsigned i = *P;
while (i > 0) {
@@ -1006,7 +1003,7 @@
}
i = VarDefinitions[i].Ref;
}
- return 0;
+ return nullptr;
}
Context getEmptyContext() { return ContextFactory.getEmptyMap(); }
@@ -1066,8 +1063,8 @@
}
/// Builds the variable map.
- void traverseCFG(CFG *CFGraph, PostOrderCFGView *SortedGraph,
- std::vector<CFGBlockInfo> &BlockInfo);
+ void traverseCFG(CFG *CFGraph, const PostOrderCFGView *SortedGraph,
+ std::vector<CFGBlockInfo> &BlockInfo);
protected:
// Get the current context index
@@ -1080,7 +1077,7 @@
// Adds a new definition to the given context, and returns a new context.
// This method should be called when declaring a new variable.
- Context addDefinition(const NamedDecl *D, Expr *Exp, Context Ctx) {
+ Context addDefinition(const NamedDecl *D, const Expr *Exp, Context Ctx) {
assert(!Ctx.contains(D));
unsigned newID = VarDefinitions.size();
Context NewCtx = ContextFactory.add(Ctx, D, newID);
@@ -1161,9 +1158,9 @@
void VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
bool modifiedCtx = false;
DeclGroupRef DGrp = S->getDeclGroup();
- for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
- if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
- Expr *E = VD->getInit();
+ for (const auto *D : DGrp) {
+ if (const auto *VD = dyn_cast_or_null<VarDecl>(D)) {
+ const Expr *E = VD->getInit();
// Add local variables with trivial type to the variable map
QualType T = VD->getType();
@@ -1205,13 +1202,12 @@
LocalVariableMap::Context
LocalVariableMap::intersectContexts(Context C1, Context C2) {
Context Result = C1;
- for (Context::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
- const NamedDecl *Dec = I.getKey();
- unsigned i1 = I.getData();
+ for (const auto &P : C1) {
+ const NamedDecl *Dec = P.first;
const unsigned *i2 = C2.lookup(Dec);
if (!i2) // variable doesn't exist on second path
Result = removeDefinition(Dec, Result);
- else if (*i2 != i1) // variable exists, but has different definition
+ else if (*i2 != P.second) // variable exists, but has different definition
Result = clearDefinition(Dec, Result);
}
return Result;
@@ -1222,11 +1218,8 @@
// (We use this for a naive implementation of SSA on loop back-edges.)
LocalVariableMap::Context LocalVariableMap::createReferenceContext(Context C) {
Context Result = getEmptyContext();
- for (Context::iterator I = C.begin(), E = C.end(); I != E; ++I) {
- const NamedDecl *Dec = I.getKey();
- unsigned i = I.getData();
- Result = addReference(Dec, i, Result);
- }
+ for (const auto &P : C)
+ Result = addReference(P.first, P.second, Result);
return Result;
}
@@ -1234,13 +1227,12 @@
// altering the VarDefinitions. C1 must be the result of an earlier call to
// createReferenceContext.
void LocalVariableMap::intersectBackEdge(Context C1, Context C2) {
- for (Context::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
- const NamedDecl *Dec = I.getKey();
- unsigned i1 = I.getData();
+ for (const auto &P : C1) {
+ unsigned i1 = P.second;
VarDefinition *VDef = &VarDefinitions[i1];
assert(VDef->isReference());
- const unsigned *i2 = C2.lookup(Dec);
+ const unsigned *i2 = C2.lookup(P.first);
if (!i2 || (*i2 != i1))
VDef->Ref = 0; // Mark this variable as undefined
}
@@ -1286,15 +1278,13 @@
// ... { y -> y1 | x3 = 2, x2 = 1, ... }
//
void LocalVariableMap::traverseCFG(CFG *CFGraph,
- PostOrderCFGView *SortedGraph,
+ const PostOrderCFGView *SortedGraph,
std::vector<CFGBlockInfo> &BlockInfo) {
PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
CtxIndices.resize(CFGraph->getNumBlockIDs());
- for (PostOrderCFGView::iterator I = SortedGraph->begin(),
- E = SortedGraph->end(); I!= E; ++I) {
- const CFGBlock *CurrBlock = *I;
+ for (const auto *CurrBlock : *SortedGraph) {
int CurrBlockID = CurrBlock->getBlockID();
CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
@@ -1306,7 +1296,7 @@
for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
PE = CurrBlock->pred_end(); PI != PE; ++PI) {
// if *PI -> CurrBlock is a back edge, so skip it
- if (*PI == 0 || !VisitedBlocks.alreadySet(*PI)) {
+ if (*PI == nullptr || !VisitedBlocks.alreadySet(*PI)) {
HasBackEdges = true;
continue;
}
@@ -1332,7 +1322,7 @@
createReferenceContext(CurrBlockInfo->EntryContext);
// Create a starting context index for the current block
- saveContext(0, CurrBlockInfo->EntryContext);
+ saveContext(nullptr, CurrBlockInfo->EntryContext);
CurrBlockInfo->EntryIndex = getContextIndex();
// Visit all the statements in the basic block.
@@ -1355,7 +1345,7 @@
for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
SE = CurrBlock->succ_end(); SI != SE; ++SI) {
// if CurrBlock -> *SI is *not* a back edge
- if (*SI == 0 || !VisitedBlocks.alreadySet(*SI))
+ if (*SI == nullptr || !VisitedBlocks.alreadySet(*SI))
continue;
CFGBlock *FirstLoopBlock = *SI;
@@ -1367,17 +1357,15 @@
// Put an extra entry at the end of the indexed context array
unsigned exitID = CFGraph->getExit().getBlockID();
- saveContext(0, BlockInfo[exitID].ExitContext);
+ saveContext(nullptr, BlockInfo[exitID].ExitContext);
}
/// Find the appropriate source locations to use when producing diagnostics for
/// each block in the CFG.
static void findBlockLocations(CFG *CFGraph,
- PostOrderCFGView *SortedGraph,
+ const PostOrderCFGView *SortedGraph,
std::vector<CFGBlockInfo> &BlockInfo) {
- for (PostOrderCFGView::iterator I = SortedGraph->begin(),
- E = SortedGraph->end(); I!= E; ++I) {
- const CFGBlock *CurrBlock = *I;
+ for (const auto *CurrBlock : *SortedGraph) {
CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlock->getBlockID()];
// Find the source location of the last statement in the block, if the
@@ -1435,7 +1423,7 @@
template <typename AttrType>
void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
- const NamedDecl *D, VarDecl *SelfDecl=0);
+ const NamedDecl *D, VarDecl *SelfDecl = nullptr);
template <class AttrType>
void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
@@ -1479,12 +1467,12 @@
}
template <typename Ty>
-class has_arg_iterator {
+class has_arg_iterator_range {
typedef char yes[1];
typedef char no[2];
template <typename Inner>
- static yes& test(Inner *I, decltype(I->args_begin()) * = nullptr);
+ static yes& test(Inner *I, decltype(I->args()) * = nullptr);
template <typename>
static no& test(...);
@@ -1523,7 +1511,7 @@
}
template <typename AttrTy>
-static typename std::enable_if<!has_arg_iterator<AttrTy>::value,
+static typename std::enable_if<!has_arg_iterator_range<AttrTy>::value,
StringRef>::type
ClassifyDiagnostic(const AttrTy *A) {
if (const ValueDecl *VD = getValueDecl(A->getArg()))
@@ -1532,11 +1520,11 @@
}
template <typename AttrTy>
-static typename std::enable_if<has_arg_iterator<AttrTy>::value,
+static typename std::enable_if<has_arg_iterator_range<AttrTy>::value,
StringRef>::type
ClassifyDiagnostic(const AttrTy *A) {
- for (auto I = A->args_begin(), E = A->args_end(); I != E; ++I) {
- if (const ValueDecl *VD = getValueDecl(*I))
+ for (const auto *Arg : A->args()) {
+ if (const ValueDecl *VD = getValueDecl(Arg))
return ClassifyDiagnostic(VD);
}
return "mutex";
@@ -1613,22 +1601,21 @@
void ThreadSafetyAnalyzer::getMutexIDs(MutexIDList &Mtxs, AttrType *Attr,
Expr *Exp, const NamedDecl *D,
VarDecl *SelfDecl) {
- typedef typename AttrType::args_iterator iterator_type;
-
if (Attr->args_size() == 0) {
// The mutex held is the "this" object.
- SExpr Mu(0, Exp, D, SelfDecl);
+ SExpr Mu(nullptr, Exp, D, SelfDecl);
if (!Mu.isValid())
- SExpr::warnInvalidLock(Handler, 0, Exp, D, ClassifyDiagnostic(Attr));
+ SExpr::warnInvalidLock(Handler, nullptr, Exp, D,
+ ClassifyDiagnostic(Attr));
else
Mtxs.push_back_nodup(Mu);
return;
}
- for (iterator_type I=Attr->args_begin(), E=Attr->args_end(); I != E; ++I) {
- SExpr Mu(*I, Exp, D, SelfDecl);
+ for (const auto *Arg : Attr->args()) {
+ SExpr Mu(Arg, Exp, D, SelfDecl);
if (!Mu.isValid())
- SExpr::warnInvalidLock(Handler, *I, Exp, D, ClassifyDiagnostic(Attr));
+ SExpr::warnInvalidLock(Handler, Arg, Exp, D, ClassifyDiagnostic(Attr));
else
Mtxs.push_back_nodup(Mu);
}
@@ -1645,23 +1632,22 @@
const CFGBlock *CurrBlock,
Expr *BrE, bool Neg) {
// Find out which branch has the lock
- bool branch = 0;
- if (CXXBoolLiteralExpr *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE)) {
+ bool branch = false;
+ if (CXXBoolLiteralExpr *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE))
branch = BLE->getValue();
- }
- else if (IntegerLiteral *ILE = dyn_cast_or_null<IntegerLiteral>(BrE)) {
+ else if (IntegerLiteral *ILE = dyn_cast_or_null<IntegerLiteral>(BrE))
branch = ILE->getValue().getBoolValue();
- }
+
int branchnum = branch ? 0 : 1;
- if (Neg) branchnum = !branchnum;
+ if (Neg)
+ branchnum = !branchnum;
// If we've taken the trylock branch, then add the lock
int i = 0;
for (CFGBlock::const_succ_iterator SI = PredBlock->succ_begin(),
SE = PredBlock->succ_end(); SI != SE && i < 2; ++SI, ++i) {
- if (*SI == CurrBlock && i == branchnum) {
+ if (*SI == CurrBlock && i == branchnum)
getMutexIDs(Mtxs, Attr, Exp, D);
- }
}
}
@@ -1690,7 +1676,7 @@
LocalVarContext C,
bool &Negate) {
if (!Cond)
- return 0;
+ return nullptr;
if (const CallExpr *CallExp = dyn_cast<CallExpr>(Cond)) {
return CallExp;
@@ -1713,7 +1699,7 @@
Negate = !Negate;
return getTrylockCallExpr(UOP->getSubExpr(), C, Negate);
}
- return 0;
+ return nullptr;
}
else if (const BinaryOperator *BOP = dyn_cast<BinaryOperator>(Cond)) {
if (BOP->getOpcode() == BO_EQ || BOP->getOpcode() == BO_NE) {
@@ -1730,7 +1716,7 @@
if (!TCond) Negate = !Negate;
return getTrylockCallExpr(BOP->getRHS(), C, Negate);
}
- return 0;
+ return nullptr;
}
if (BOP->getOpcode() == BO_LAnd) {
// LHS must have been evaluated in a different block.
@@ -1739,9 +1725,9 @@
if (BOP->getOpcode() == BO_LOr) {
return getTrylockCallExpr(BOP->getRHS(), C, Negate);
}
- return 0;
+ return nullptr;
}
- return 0;
+ return nullptr;
}
@@ -1776,9 +1762,7 @@
MutexIDList SharedLocksToAdd;
// If the condition is a call to a Trylock function, then grab the attributes
- AttrVec &ArgAttrs = FunDecl->getAttrs();
- for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
- Attr *Attr = ArgAttrs[i];
+ for (auto *Attr : FunDecl->getAttrs()) {
switch (Attr->getKind()) {
case attr::ExclusiveTrylockFunction: {
ExclusiveTrylockFunctionAttr *A =
@@ -1834,7 +1818,7 @@
void checkAccess(const Expr *Exp, AccessKind AK);
void checkPtAccess(const Expr *Exp, AccessKind AK);
- void handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD = 0);
+ void handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD = nullptr);
public:
BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
@@ -2059,21 +2043,16 @@
case attr::RequiresCapability: {
RequiresCapabilityAttr *A = cast<RequiresCapabilityAttr>(At);
-
- for (RequiresCapabilityAttr::args_iterator I = A->args_begin(),
- E = A->args_end(); I != E; ++I)
- warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, *I,
+ for (auto *Arg : A->args())
+ warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, Arg,
POK_FunctionCall, ClassifyDiagnostic(A));
break;
}
case attr::LocksExcluded: {
LocksExcludedAttr *A = cast<LocksExcludedAttr>(At);
-
- for (LocksExcludedAttr::args_iterator I = A->args_begin(),
- E = A->args_end(); I != E; ++I) {
- warnIfMutexHeld(D, Exp, *I, ClassifyDiagnostic(A));
- }
+ for (auto *Arg : A->args())
+ warnIfMutexHeld(D, Exp, Arg, ClassifyDiagnostic(A));
break;
}
@@ -2106,7 +2085,7 @@
if (isScopedVar) {
SourceLocation MLoc = VD->getLocation();
DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation());
- SExpr SMutex(&DRE, 0, 0);
+ SExpr SMutex(&DRE, nullptr, nullptr);
for (const auto &M : ExclusiveLocksToAdd)
Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Exclusive, M),
@@ -2232,9 +2211,7 @@
// adjust the context
LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
- DeclGroupRef DGrp = S->getDeclGroup();
- for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
- Decl *D = *I;
+ for (auto *D : S->getDeclGroup()) {
if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) {
Expr *E = VD->getInit();
// handle constructors that involve temporaries
@@ -2276,10 +2253,9 @@
FactSet FSet1Orig = FSet1;
// Find locks in FSet2 that conflict or are not in FSet1, and warn.
- for (FactSet::const_iterator I = FSet2.begin(), E = FSet2.end();
- I != E; ++I) {
- const SExpr &FSet2Mutex = FactMan[*I].MutID;
- const LockData &LDat2 = FactMan[*I].LDat;
+ for (const auto &Fact : FSet2) {
+ const SExpr &FSet2Mutex = FactMan[Fact].MutID;
+ const LockData &LDat2 = FactMan[Fact].LDat;
FactSet::iterator I1 = FSet1.findLockIter(FactMan, FSet2Mutex);
if (I1 != FSet1.end()) {
@@ -2289,12 +2265,12 @@
LDat2.AcquireLoc, LDat1->AcquireLoc);
if (Modify && LDat1->LKind != LK_Exclusive) {
// Take the exclusive lock, which is the one in FSet2.
- *I1 = *I;
+ *I1 = Fact;
}
}
else if (LDat1->Asserted && !LDat2.Asserted) {
// The non-asserted lock in FSet2 is the one we want to track.
- *I1 = *I;
+ *I1 = Fact;
}
} else {
if (LDat2.UnderlyingMutex.isValid()) {
@@ -2314,10 +2290,9 @@
}
// Find locks in FSet1 that are not in FSet2, and remove them.
- for (FactSet::const_iterator I = FSet1Orig.begin(), E = FSet1Orig.end();
- I != E; ++I) {
- const SExpr &FSet1Mutex = FactMan[*I].MutID;
- const LockData &LDat1 = FactMan[*I].LDat;
+ for (const auto &Fact : FSet1Orig) {
+ const SExpr &FSet1Mutex = FactMan[Fact].MutID;
+ const LockData &LDat1 = FactMan[Fact].LDat;
if (!FSet2.findLock(FactMan, FSet1Mutex)) {
if (LDat1.UnderlyingMutex.isValid()) {
@@ -2362,16 +2337,21 @@
/// at the end of each block, and issue warnings for thread safety violations.
/// Each block in the CFG is traversed exactly once.
void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
- CFG *CFGraph = AC.getCFG();
- if (!CFGraph) return;
- const NamedDecl *D = dyn_cast_or_null<NamedDecl>(AC.getDecl());
+ // TODO: this whole function needs be rewritten as a visitor for CFGWalker.
+ // For now, we just use the walker to set things up.
+ threadSafety::CFGWalker walker;
+ if (!walker.init(AC))
+ return;
// AC.dumpCFG(true);
+ // threadSafety::printSCFG(walker);
- if (!D)
- return; // Ignore anonymous functions for now.
+ CFG *CFGraph = walker.getGraph();
+ const NamedDecl *D = walker.getDecl();
+
if (D->hasAttr<NoThreadSafetyAnalysisAttr>())
return;
+
// FIXME: Do something a bit more intelligent inside constructor and
// destructor code. Constructors and destructors must assume unique access
// to 'this', so checks on member variable access is disabled, but we should
@@ -2387,7 +2367,7 @@
// We need to explore the CFG via a "topological" ordering.
// That way, we will be guaranteed to have information about required
// predecessor locksets when exploring a new block.
- PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
+ const PostOrderCFGView *SortedGraph = walker.getSortedGraph();
PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
// Mark entry block as reachable
@@ -2416,23 +2396,22 @@
StringRef CapDiagKind = "mutex";
SourceLocation Loc = D->getLocation();
- for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
- Attr *Attr = ArgAttrs[i];
+ for (const auto *Attr : ArgAttrs) {
Loc = Attr->getLocation();
- if (RequiresCapabilityAttr *A = dyn_cast<RequiresCapabilityAttr>(Attr)) {
+ if (const auto *A = dyn_cast<RequiresCapabilityAttr>(Attr)) {
getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
- 0, D);
+ nullptr, D);
CapDiagKind = ClassifyDiagnostic(A);
- } else if (auto *A = dyn_cast<ReleaseCapabilityAttr>(Attr)) {
+ } else if (const auto *A = dyn_cast<ReleaseCapabilityAttr>(Attr)) {
// UNLOCK_FUNCTION() is used to hide the underlying lock implementation.
// We must ignore such methods.
if (A->args_size() == 0)
return;
// FIXME -- deal with exclusive vs. shared unlock functions?
- getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
- getMutexIDs(LocksReleased, A, (Expr*) 0, D);
+ getMutexIDs(ExclusiveLocksToAdd, A, nullptr, D);
+ getMutexIDs(LocksReleased, A, nullptr, D);
CapDiagKind = ClassifyDiagnostic(A);
- } else if (auto *A = dyn_cast<AcquireCapabilityAttr>(Attr)) {
+ } else if (const auto *A = dyn_cast<AcquireCapabilityAttr>(Attr)) {
if (A->args_size() == 0)
return;
getMutexIDs(A->isShared() ? SharedLocksAcquired
@@ -2457,9 +2436,7 @@
CapDiagKind);
}
- for (PostOrderCFGView::iterator I = SortedGraph->begin(),
- E = SortedGraph->end(); I!= E; ++I) {
- const CFGBlock *CurrBlock = *I;
+ for (const auto *CurrBlock : *SortedGraph) {
int CurrBlockID = CurrBlock->getBlockID();
CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
@@ -2485,7 +2462,7 @@
PE = CurrBlock->pred_end(); PI != PE; ++PI) {
// if *PI -> CurrBlock is a back edge
- if (*PI == 0 || !VisitedBlocks.alreadySet(*PI))
+ if (*PI == nullptr || !VisitedBlocks.alreadySet(*PI))
continue;
int PrevBlockID = (*PI)->getBlockID();
@@ -2528,9 +2505,7 @@
// Process continue and break blocks. Assume that the lockset for the
// resulting block is unaffected by any discrepancies in them.
- for (unsigned SpecialI = 0, SpecialN = SpecialBlocks.size();
- SpecialI < SpecialN; ++SpecialI) {
- CFGBlock *PrevBlock = SpecialBlocks[SpecialI];
+ for (const auto *PrevBlock : SpecialBlocks) {
int PrevBlockID = PrevBlock->getBlockID();
CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
@@ -2599,7 +2574,7 @@
SE = CurrBlock->succ_end(); SI != SE; ++SI) {
// if CurrBlock -> *SI is *not* a back edge
- if (*SI == 0 || !VisitedBlocks.alreadySet(*SI))
+ if (*SI == nullptr || !VisitedBlocks.alreadySet(*SI))
continue;
CFGBlock *FirstLoopBlock = *SI;
@@ -2626,17 +2601,14 @@
// by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then
// issue the appropriate warning.
// FIXME: the location here is not quite right.
- for (unsigned i=0,n=ExclusiveLocksAcquired.size(); i<n; ++i) {
- ExpectedExitSet.addLock(FactMan, ExclusiveLocksAcquired[i],
+ for (const auto &Lock : ExclusiveLocksAcquired)
+ ExpectedExitSet.addLock(FactMan, Lock,
LockData(D->getLocation(), LK_Exclusive));
- }
- for (unsigned i=0,n=SharedLocksAcquired.size(); i<n; ++i) {
- ExpectedExitSet.addLock(FactMan, SharedLocksAcquired[i],
+ for (const auto &Lock : SharedLocksAcquired)
+ ExpectedExitSet.addLock(FactMan, Lock,
LockData(D->getLocation(), LK_Shared));
- }
- for (unsigned i=0,n=LocksReleased.size(); i<n; ++i) {
- ExpectedExitSet.removeLock(FactMan, LocksReleased[i]);
- }
+ for (const auto &Lock : LocksReleased)
+ ExpectedExitSet.removeLock(FactMan, Lock);
// FIXME: Should we call this function for all blocks which exit the function?
intersectAndWarn(ExpectedExitSet, Final->ExitSet,
diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
new file mode 100644
index 0000000..91cf849
--- /dev/null
+++ b/lib/Analysis/ThreadSafetyCommon.cpp
@@ -0,0 +1,791 @@
+//===- ThreadSafetyCommon.cpp ----------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the interfaces declared in ThreadSafetyCommon.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <algorithm>
+#include <climits>
+#include <vector>
+
+
+namespace clang {
+namespace threadSafety {
+
+// From ThreadSafetyUtil.h
+std::string getSourceLiteralString(const clang::Expr *CE) {
+ switch (CE->getStmtClass()) {
+ case Stmt::IntegerLiteralClass:
+ return cast<IntegerLiteral>(CE)->getValue().toString(10, true);
+ case Stmt::StringLiteralClass: {
+ std::string ret("\"");
+ ret += cast<StringLiteral>(CE)->getString();
+ ret += "\"";
+ return ret;
+ }
+ case Stmt::CharacterLiteralClass:
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::GNUNullExprClass:
+ case Stmt::CXXBoolLiteralExprClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::ObjCStringLiteralClass:
+ default:
+ return "#lit";
+ }
+}
+
+namespace til {
+
+// Return true if E is a variable that points to an incomplete Phi node.
+static bool isIncompleteVar(const SExpr *E) {
+ if (const auto *V = dyn_cast<Variable>(E)) {
+ if (const auto *Ph = dyn_cast<Phi>(V->definition()))
+ return Ph->status() == Phi::PH_Incomplete;
+ }
+ return false;
+}
+
+} // end namespace til
+
+
+typedef SExprBuilder::CallingContext CallingContext;
+
+
+til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) {
+ auto It = SMap.find(S);
+ if (It != SMap.end())
+ return It->second;
+ return nullptr;
+}
+
+
+til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) {
+ Walker.walk(*this);
+ return Scfg;
+}
+
+
+// Translate a clang statement or expression to a TIL expression.
+// Also performs substitution of variables; Ctx provides the context.
+// Dispatches on the type of S.
+til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
+ if (!S)
+ return nullptr;
+
+ // Check if S has already been translated and cached.
+ // This handles the lookup of SSA names for DeclRefExprs here.
+ if (til::SExpr *E = lookupStmt(S))
+ return E;
+
+ switch (S->getStmtClass()) {
+ case Stmt::DeclRefExprClass:
+ return translateDeclRefExpr(cast<DeclRefExpr>(S), Ctx);
+ case Stmt::CXXThisExprClass:
+ return translateCXXThisExpr(cast<CXXThisExpr>(S), Ctx);
+ case Stmt::MemberExprClass:
+ return translateMemberExpr(cast<MemberExpr>(S), Ctx);
+ case Stmt::CallExprClass:
+ return translateCallExpr(cast<CallExpr>(S), Ctx);
+ case Stmt::CXXMemberCallExprClass:
+ return translateCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), Ctx);
+ case Stmt::CXXOperatorCallExprClass:
+ return translateCXXOperatorCallExpr(cast<CXXOperatorCallExpr>(S), Ctx);
+ case Stmt::UnaryOperatorClass:
+ return translateUnaryOperator(cast<UnaryOperator>(S), Ctx);
+ case Stmt::BinaryOperatorClass:
+ case Stmt::CompoundAssignOperatorClass:
+ return translateBinaryOperator(cast<BinaryOperator>(S), Ctx);
+
+ case Stmt::ArraySubscriptExprClass:
+ return translateArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Ctx);
+ case Stmt::ConditionalOperatorClass:
+ return translateConditionalOperator(cast<ConditionalOperator>(S), Ctx);
+ case Stmt::BinaryConditionalOperatorClass:
+ return translateBinaryConditionalOperator(
+ cast<BinaryConditionalOperator>(S), Ctx);
+
+ // We treat these as no-ops
+ case Stmt::ParenExprClass:
+ return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
+ case Stmt::ExprWithCleanupsClass:
+ return translate(cast<ExprWithCleanups>(S)->getSubExpr(), Ctx);
+ case Stmt::CXXBindTemporaryExprClass:
+ return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
+
+ // Collect all literals
+ case Stmt::CharacterLiteralClass:
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::GNUNullExprClass:
+ case Stmt::CXXBoolLiteralExprClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::IntegerLiteralClass:
+ case Stmt::StringLiteralClass:
+ case Stmt::ObjCStringLiteralClass:
+ return new (Arena) til::Literal(cast<Expr>(S));
+
+ case Stmt::DeclStmtClass:
+ return translateDeclStmt(cast<DeclStmt>(S), Ctx);
+ default:
+ break;
+ }
+ if (const CastExpr *CE = dyn_cast<CastExpr>(S))
+ return translateCastExpr(CE, Ctx);
+
+ return new (Arena) til::Undefined(S);
+}
+
+
+til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
+ CallingContext *Ctx) {
+ const ValueDecl *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
+
+ // Function parameters require substitution and/or renaming.
+ if (const ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(VD)) {
+ const FunctionDecl *FD =
+ cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
+ unsigned I = PV->getFunctionScopeIndex();
+
+ if (Ctx && Ctx->FunArgs && FD == Ctx->AttrDecl->getCanonicalDecl()) {
+ // Substitute call arguments for references to function parameters
+ assert(I < Ctx->NumArgs);
+ return translate(Ctx->FunArgs[I], Ctx->Prev);
+ }
+ // Map the param back to the param of the original function declaration
+ // for consistent comparisons.
+ VD = FD->getParamDecl(I);
+ }
+
+ // For non-local variables, treat it as a referenced to a named object.
+ return new (Arena) til::LiteralPtr(VD);
+}
+
+
+til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE,
+ CallingContext *Ctx) {
+ // Substitute for 'this'
+ if (Ctx && Ctx->SelfArg)
+ return translate(Ctx->SelfArg, Ctx->Prev);
+ assert(SelfVar && "We have no variable for 'this'!");
+ return SelfVar;
+}
+
+
+til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,
+ CallingContext *Ctx) {
+ til::SExpr *E = translate(ME->getBase(), Ctx);
+ E = new (Arena) til::SApply(E);
+ return new (Arena) til::Project(E, ME->getMemberDecl());
+}
+
+
+til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,
+ CallingContext *Ctx) {
+ // TODO -- Lock returned
+ til::SExpr *E = translate(CE->getCallee(), Ctx);
+ for (const auto *Arg : CE->arguments()) {
+ til::SExpr *A = translate(Arg, Ctx);
+ E = new (Arena) til::Apply(E, A);
+ }
+ return new (Arena) til::Call(E, CE);
+}
+
+
+til::SExpr *SExprBuilder::translateCXXMemberCallExpr(
+ const CXXMemberCallExpr *ME, CallingContext *Ctx) {
+ return translateCallExpr(cast<CallExpr>(ME), Ctx);
+}
+
+
+til::SExpr *SExprBuilder::translateCXXOperatorCallExpr(
+ const CXXOperatorCallExpr *OCE, CallingContext *Ctx) {
+ return translateCallExpr(cast<CallExpr>(OCE), Ctx);
+}
+
+
+til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO,
+ CallingContext *Ctx) {
+ switch (UO->getOpcode()) {
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec:
+ return new (Arena) til::Undefined(UO);
+
+ // We treat these as no-ops
+ case UO_AddrOf:
+ case UO_Deref:
+ case UO_Plus:
+ return translate(UO->getSubExpr(), Ctx);
+
+ case UO_Minus:
+ return new (Arena)
+ til::UnaryOp(til::UOP_Minus, translate(UO->getSubExpr(), Ctx));
+ case UO_Not:
+ return new (Arena)
+ til::UnaryOp(til::UOP_BitNot, translate(UO->getSubExpr(), Ctx));
+ case UO_LNot:
+ return new (Arena)
+ til::UnaryOp(til::UOP_LogicNot, translate(UO->getSubExpr(), Ctx));
+
+ // Currently unsupported
+ case UO_Real:
+ case UO_Imag:
+ case UO_Extension:
+ return new (Arena) til::Undefined(UO);
+ }
+ return new (Arena) til::Undefined(UO);
+}
+
+
+til::SExpr *SExprBuilder::translateBinOp(til::TIL_BinaryOpcode Op,
+ const BinaryOperator *BO,
+ CallingContext *Ctx, bool Reverse) {
+ til::SExpr *E0 = translate(BO->getLHS(), Ctx);
+ til::SExpr *E1 = translate(BO->getRHS(), Ctx);
+ if (Reverse)
+ return new (Arena) til::BinaryOp(Op, E1, E0);
+ else
+ return new (Arena) til::BinaryOp(Op, E0, E1);
+}
+
+
+til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op,
+ const BinaryOperator *BO,
+ CallingContext *Ctx,
+ bool Assign) {
+ const Expr *LHS = BO->getLHS();
+ const Expr *RHS = BO->getRHS();
+ til::SExpr *E0 = translate(LHS, Ctx);
+ til::SExpr *E1 = translate(RHS, Ctx);
+
+ const ValueDecl *VD = nullptr;
+ til::SExpr *CV = nullptr;
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHS)) {
+ VD = DRE->getDecl();
+ CV = lookupVarDecl(VD);
+ }
+
+ if (!Assign) {
+ til::SExpr *Arg = CV ? CV : new (Arena) til::Load(E0);
+ E1 = new (Arena) til::BinaryOp(Op, Arg, E1);
+ E1 = addStatement(E1, nullptr, VD);
+ }
+ if (VD && CV)
+ return updateVarDecl(VD, E1);
+ return new (Arena) til::Store(E0, E1);
+}
+
+
+til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,
+ CallingContext *Ctx) {
+ switch (BO->getOpcode()) {
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ return new (Arena) til::Undefined(BO);
+
+ case BO_Mul: return translateBinOp(til::BOP_Mul, BO, Ctx);
+ case BO_Div: return translateBinOp(til::BOP_Div, BO, Ctx);
+ case BO_Rem: return translateBinOp(til::BOP_Rem, BO, Ctx);
+ case BO_Add: return translateBinOp(til::BOP_Add, BO, Ctx);
+ case BO_Sub: return translateBinOp(til::BOP_Sub, BO, Ctx);
+ case BO_Shl: return translateBinOp(til::BOP_Shl, BO, Ctx);
+ case BO_Shr: return translateBinOp(til::BOP_Shr, BO, Ctx);
+ case BO_LT: return translateBinOp(til::BOP_Lt, BO, Ctx);
+ case BO_GT: return translateBinOp(til::BOP_Lt, BO, Ctx, true);
+ case BO_LE: return translateBinOp(til::BOP_Leq, BO, Ctx);
+ case BO_GE: return translateBinOp(til::BOP_Leq, BO, Ctx, true);
+ case BO_EQ: return translateBinOp(til::BOP_Eq, BO, Ctx);
+ case BO_NE: return translateBinOp(til::BOP_Neq, BO, Ctx);
+ case BO_And: return translateBinOp(til::BOP_BitAnd, BO, Ctx);
+ case BO_Xor: return translateBinOp(til::BOP_BitXor, BO, Ctx);
+ case BO_Or: return translateBinOp(til::BOP_BitOr, BO, Ctx);
+ case BO_LAnd: return translateBinOp(til::BOP_LogicAnd, BO, Ctx);
+ case BO_LOr: return translateBinOp(til::BOP_LogicOr, BO, Ctx);
+
+ case BO_Assign: return translateBinAssign(til::BOP_Eq, BO, Ctx, true);
+ case BO_MulAssign: return translateBinAssign(til::BOP_Mul, BO, Ctx);
+ case BO_DivAssign: return translateBinAssign(til::BOP_Div, BO, Ctx);
+ case BO_RemAssign: return translateBinAssign(til::BOP_Rem, BO, Ctx);
+ case BO_AddAssign: return translateBinAssign(til::BOP_Add, BO, Ctx);
+ case BO_SubAssign: return translateBinAssign(til::BOP_Sub, BO, Ctx);
+ case BO_ShlAssign: return translateBinAssign(til::BOP_Shl, BO, Ctx);
+ case BO_ShrAssign: return translateBinAssign(til::BOP_Shr, BO, Ctx);
+ case BO_AndAssign: return translateBinAssign(til::BOP_BitAnd, BO, Ctx);
+ case BO_XorAssign: return translateBinAssign(til::BOP_BitXor, BO, Ctx);
+ case BO_OrAssign: return translateBinAssign(til::BOP_BitOr, BO, Ctx);
+
+ case BO_Comma:
+ // The clang CFG should have already processed both sides.
+ return translate(BO->getRHS(), Ctx);
+ }
+ return new (Arena) til::Undefined(BO);
+}
+
+
+til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
+ CallingContext *Ctx) {
+ clang::CastKind K = CE->getCastKind();
+ switch (K) {
+ case CK_LValueToRValue: {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
+ til::SExpr *E0 = lookupVarDecl(DRE->getDecl());
+ if (E0)
+ return E0;
+ }
+ til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
+ return new (Arena) til::Load(E0);
+ }
+ case CK_NoOp:
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay: {
+ til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
+ return E0;
+ }
+ default: {
+ // FIXME: handle different kinds of casts.
+ til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
+ return new (Arena) til::Cast(til::CAST_none, E0);
+ }
+ }
+}
+
+
+til::SExpr *
+SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,
+ CallingContext *Ctx) {
+ til::SExpr *E0 = translate(E->getBase(), Ctx);
+ til::SExpr *E1 = translate(E->getIdx(), Ctx);
+ auto *AA = new (Arena) til::ArrayAdd(E0, E1);
+ return new (Arena) til::ArrayFirst(AA);
+}
+
+
+til::SExpr *
+SExprBuilder::translateConditionalOperator(const ConditionalOperator *C,
+ CallingContext *Ctx) {
+ return new (Arena) til::Undefined(C);
+}
+
+
+til::SExpr *SExprBuilder::translateBinaryConditionalOperator(
+ const BinaryConditionalOperator *C, CallingContext *Ctx) {
+ return new (Arena) til::Undefined(C);
+}
+
+
+til::SExpr *
+SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
+ DeclGroupRef DGrp = S->getDeclGroup();
+ for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
+ if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
+ Expr *E = VD->getInit();
+ til::SExpr* SE = translate(E, Ctx);
+
+ // Add local variables with trivial type to the variable map
+ QualType T = VD->getType();
+ if (T.isTrivialType(VD->getASTContext())) {
+ return addVarDecl(VD, SE);
+ }
+ else {
+ // TODO: add alloca
+ }
+ }
+ }
+ return nullptr;
+}
+
+
+
+// If (E) is non-trivial, then add it to the current basic block, and
+// update the statement map so that S refers to E. Returns a new variable
+// that refers to E.
+// If E is trivial returns E.
+til::SExpr *SExprBuilder::addStatement(til::SExpr* E, const Stmt *S,
+ const ValueDecl *VD) {
+ if (!E)
+ return nullptr;
+ if (til::ThreadSafetyTIL::isTrivial(E))
+ return E;
+
+ til::Variable *V = new (Arena) til::Variable(E, VD);
+ CurrentInstructions.push_back(V);
+ if (S)
+ insertStmt(S, V);
+ return V;
+}
+
+
+// Returns the current value of VD, if known, and nullptr otherwise.
+til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
+ auto It = LVarIdxMap.find(VD);
+ if (It != LVarIdxMap.end()) {
+ assert(CurrentLVarMap[It->second].first == VD);
+ return CurrentLVarMap[It->second].second;
+ }
+ return nullptr;
+}
+
+
+// if E is a til::Variable, update its clangDecl.
+inline void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
+ if (!E)
+ return;
+ if (til::Variable *V = dyn_cast<til::Variable>(E)) {
+ if (!V->clangDecl())
+ V->setClangDecl(VD);
+ }
+}
+
+// Adds a new variable declaration.
+til::SExpr *SExprBuilder::addVarDecl(const ValueDecl *VD, til::SExpr *E) {
+ maybeUpdateVD(E, VD);
+ LVarIdxMap.insert(std::make_pair(VD, CurrentLVarMap.size()));
+ CurrentLVarMap.makeWritable();
+ CurrentLVarMap.push_back(std::make_pair(VD, E));
+ return E;
+}
+
+
+// Updates a current variable declaration. (E.g. by assignment)
+til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) {
+ maybeUpdateVD(E, VD);
+ auto It = LVarIdxMap.find(VD);
+ if (It == LVarIdxMap.end()) {
+ til::SExpr *Ptr = new (Arena) til::LiteralPtr(VD);
+ til::SExpr *St = new (Arena) til::Store(Ptr, E);
+ return St;
+ }
+ CurrentLVarMap.makeWritable();
+ CurrentLVarMap.elem(It->second).second = E;
+ return E;
+}
+
+
+// Make a Phi node in the current block for the i^th variable in CurrentVarMap.
+// If E != null, sets Phi[CurrentBlockInfo->ArgIndex] = E.
+// If E == null, this is a backedge and will be set later.
+void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) {
+ unsigned ArgIndex = CurrentBlockInfo->ProcessedPredecessors;
+ assert(ArgIndex > 0 && ArgIndex < NPreds);
+
+ til::Variable *V = dyn_cast<til::Variable>(CurrentLVarMap[i].second);
+ if (V && V->getBlockID() == CurrentBB->blockID()) {
+ // We already have a Phi node in the current block,
+ // so just add the new variable to the Phi node.
+ til::Phi *Ph = dyn_cast<til::Phi>(V->definition());
+ assert(Ph && "Expecting Phi node.");
+ if (E)
+ Ph->values()[ArgIndex] = E;
+ return;
+ }
+
+ // Make a new phi node: phi(..., E)
+ // All phi args up to the current index are set to the current value.
+ til::SExpr *CurrE = CurrentLVarMap[i].second;
+ til::Phi *Ph = new (Arena) til::Phi(Arena, NPreds);
+ Ph->values().setValues(NPreds, nullptr);
+ for (unsigned PIdx = 0; PIdx < ArgIndex; ++PIdx)
+ Ph->values()[PIdx] = CurrE;
+ if (E)
+ Ph->values()[ArgIndex] = E;
+ // If E is from a back-edge, or either E or CurrE are incomplete, then
+ // mark this node as incomplete; we may need to remove it later.
+ if (!E || isIncompleteVar(E) || isIncompleteVar(CurrE)) {
+ Ph->setStatus(til::Phi::PH_Incomplete);
+ }
+
+ // Add Phi node to current block, and update CurrentLVarMap[i]
+ auto *Var = new (Arena) til::Variable(Ph, CurrentLVarMap[i].first);
+ CurrentArguments.push_back(Var);
+ if (Ph->status() == til::Phi::PH_Incomplete)
+ IncompleteArgs.push_back(Var);
+
+ CurrentLVarMap.makeWritable();
+ CurrentLVarMap.elem(i).second = Var;
+}
+
+
+// Merge values from Map into the current variable map.
+// This will construct Phi nodes in the current basic block as necessary.
+void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) {
+ assert(CurrentBlockInfo && "Not processing a block!");
+
+ if (!CurrentLVarMap.valid()) {
+ // Steal Map, using copy-on-write.
+ CurrentLVarMap = std::move(Map);
+ return;
+ }
+ if (CurrentLVarMap.sameAs(Map))
+ return; // Easy merge: maps from different predecessors are unchanged.
+
+ unsigned NPreds = CurrentBB->numPredecessors();
+ unsigned ESz = CurrentLVarMap.size();
+ unsigned MSz = Map.size();
+ unsigned Sz = std::min(ESz, MSz);
+
+ for (unsigned i=0; i<Sz; ++i) {
+ if (CurrentLVarMap[i].first != Map[i].first) {
+ // We've reached the end of variables in common.
+ CurrentLVarMap.makeWritable();
+ CurrentLVarMap.downsize(i);
+ break;
+ }
+ if (CurrentLVarMap[i].second != Map[i].second)
+ makePhiNodeVar(i, NPreds, Map[i].second);
+ }
+ if (ESz > MSz) {
+ CurrentLVarMap.makeWritable();
+ CurrentLVarMap.downsize(Map.size());
+ }
+}
+
+
+// Merge a back edge into the current variable map.
+// This will create phi nodes for all variables in the variable map.
+void SExprBuilder::mergeEntryMapBackEdge() {
+ // We don't have definitions for variables on the backedge, because we
+ // haven't gotten that far in the CFG. Thus, when encountering a back edge,
+ // we conservatively create Phi nodes for all variables. Unnecessary Phi
+ // nodes will be marked as incomplete, and stripped out at the end.
+ //
+ // An Phi node is unnecessary if it only refers to itself and one other
+ // variable, e.g. x = Phi(y, y, x) can be reduced to x = y.
+
+ assert(CurrentBlockInfo && "Not processing a block!");
+
+ if (CurrentBlockInfo->HasBackEdges)
+ return;
+ CurrentBlockInfo->HasBackEdges = true;
+
+ CurrentLVarMap.makeWritable();
+ unsigned Sz = CurrentLVarMap.size();
+ unsigned NPreds = CurrentBB->numPredecessors();
+
+ for (unsigned i=0; i < Sz; ++i) {
+ makePhiNodeVar(i, NPreds, nullptr);
+ }
+}
+
+
+// Update the phi nodes that were initially created for a back edge
+// once the variable definitions have been computed.
+// I.e., merge the current variable map into the phi nodes for Blk.
+void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) {
+ til::BasicBlock *BB = lookupBlock(Blk);
+ unsigned ArgIndex = BBInfo[Blk->getBlockID()].ProcessedPredecessors;
+ assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors());
+
+ for (til::Variable *V : BB->arguments()) {
+ til::Phi *Ph = dyn_cast_or_null<til::Phi>(V->definition());
+ assert(Ph && "Expecting Phi Node.");
+ assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge.");
+ assert(V->clangDecl() && "No local variable for Phi node.");
+
+ til::SExpr *E = lookupVarDecl(V->clangDecl());
+ assert(E && "Couldn't find local variable for Phi node.");
+
+ Ph->values()[ArgIndex] = E;
+ }
+}
+
+void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D,
+ const CFGBlock *First) {
+ // Perform initial setup operations.
+ unsigned NBlocks = Cfg->getNumBlockIDs();
+ Scfg = new (Arena) til::SCFG(Arena, NBlocks);
+
+ // allocate all basic blocks immediately, to handle forward references.
+ BBInfo.resize(NBlocks);
+ BlockMap.resize(NBlocks, nullptr);
+ // create map from clang blockID to til::BasicBlocks
+ for (auto *B : *Cfg) {
+ auto *BB = new (Arena) til::BasicBlock(Arena, 0, B->size());
+ BlockMap[B->getBlockID()] = BB;
+ }
+ CallCtx.reset(new SExprBuilder::CallingContext(D));
+
+ CurrentBB = lookupBlock(&Cfg->getEntry());
+ auto Parms = isa<ObjCMethodDecl>(D) ? cast<ObjCMethodDecl>(D)->parameters()
+ : cast<FunctionDecl>(D)->parameters();
+ for (auto *Pm : Parms) {
+ QualType T = Pm->getType();
+ if (!T.isTrivialType(Pm->getASTContext()))
+ continue;
+
+ // Add parameters to local variable map.
+ // FIXME: right now we emulate params with loads; that should be fixed.
+ til::SExpr *Lp = new (Arena) til::LiteralPtr(Pm);
+ til::SExpr *Ld = new (Arena) til::Load(Lp);
+ til::SExpr *V = addStatement(Ld, nullptr, Pm);
+ addVarDecl(Pm, V);
+ }
+}
+
+
+void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
+ // Intialize TIL basic block and add it to the CFG.
+ CurrentBB = lookupBlock(B);
+ CurrentBB->setNumPredecessors(B->pred_size());
+ Scfg->add(CurrentBB);
+
+ CurrentBlockInfo = &BBInfo[B->getBlockID()];
+
+ // CurrentLVarMap is moved to ExitMap on block exit.
+ // FIXME: the entry block will hold function parameters.
+ // assert(!CurrentLVarMap.valid() && "CurrentLVarMap already initialized.");
+}
+
+
+void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {
+ // Compute CurrentLVarMap on entry from ExitMaps of predecessors
+
+ BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()];
+ assert(PredInfo->UnprocessedSuccessors > 0);
+
+ if (--PredInfo->UnprocessedSuccessors == 0)
+ mergeEntryMap(std::move(PredInfo->ExitMap));
+ else
+ mergeEntryMap(PredInfo->ExitMap.clone());
+
+ ++CurrentBlockInfo->ProcessedPredecessors;
+}
+
+
+void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) {
+ mergeEntryMapBackEdge();
+}
+
+
+void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) {
+ // The merge*() methods have created arguments.
+ // Push those arguments onto the basic block.
+ CurrentBB->arguments().reserve(
+ static_cast<unsigned>(CurrentArguments.size()), Arena);
+ for (auto *V : CurrentArguments)
+ CurrentBB->addArgument(V);
+}
+
+
+void SExprBuilder::handleStatement(const Stmt *S) {
+ til::SExpr *E = translate(S, CallCtx.get());
+ addStatement(E, S);
+}
+
+
+void SExprBuilder::handleDestructorCall(const VarDecl *VD,
+ const CXXDestructorDecl *DD) {
+ til::SExpr *Sf = new (Arena) til::LiteralPtr(VD);
+ til::SExpr *Dr = new (Arena) til::LiteralPtr(DD);
+ til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf);
+ til::SExpr *E = new (Arena) til::Call(Ap);
+ addStatement(E, nullptr);
+}
+
+
+
+void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
+ CurrentBB->instructions().reserve(
+ static_cast<unsigned>(CurrentInstructions.size()), Arena);
+ for (auto *V : CurrentInstructions)
+ CurrentBB->addInstruction(V);
+
+ // Create an appropriate terminator
+ unsigned N = B->succ_size();
+ auto It = B->succ_begin();
+ if (N == 1) {
+ til::BasicBlock *BB = *It ? lookupBlock(*It) : nullptr;
+ // TODO: set index
+ til::SExpr *Tm = new (Arena) til::Goto(BB, 0);
+ CurrentBB->setTerminator(Tm);
+ }
+ else if (N == 2) {
+ til::SExpr *C = translate(B->getTerminatorCondition(true), CallCtx.get());
+ til::BasicBlock *BB1 = *It ? lookupBlock(*It) : nullptr;
+ ++It;
+ til::BasicBlock *BB2 = *It ? lookupBlock(*It) : nullptr;
+ // TODO: set conditional, set index
+ til::SExpr *Tm = new (Arena) til::Branch(C, BB1, BB2);
+ CurrentBB->setTerminator(Tm);
+ }
+}
+
+
+void SExprBuilder::handleSuccessor(const CFGBlock *Succ) {
+ ++CurrentBlockInfo->UnprocessedSuccessors;
+}
+
+
+void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) {
+ mergePhiNodesBackEdge(Succ);
+ ++BBInfo[Succ->getBlockID()].ProcessedPredecessors;
+}
+
+
+void SExprBuilder::exitCFGBlock(const CFGBlock *B) {
+ CurrentArguments.clear();
+ CurrentInstructions.clear();
+ CurrentBlockInfo->ExitMap = std::move(CurrentLVarMap);
+ CurrentBB = nullptr;
+ CurrentBlockInfo = nullptr;
+}
+
+
+void SExprBuilder::exitCFG(const CFGBlock *Last) {
+ for (auto *V : IncompleteArgs) {
+ til::Phi *Ph = dyn_cast<til::Phi>(V->definition());
+ if (Ph && Ph->status() == til::Phi::PH_Incomplete)
+ simplifyIncompleteArg(V, Ph);
+ }
+
+ CurrentArguments.clear();
+ CurrentInstructions.clear();
+ IncompleteArgs.clear();
+}
+
+
+
+class TILPrinter : public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
+
+
+void printSCFG(CFGWalker &Walker) {
+ llvm::BumpPtrAllocator Bpa;
+ til::MemRegionRef Arena(&Bpa);
+ SExprBuilder builder(Arena);
+ til::SCFG *Cfg = builder.buildCFG(Walker);
+ TILPrinter::print(Cfg, llvm::errs());
+}
+
+
+
+} // end namespace threadSafety
+
+} // end namespace clang
diff --git a/lib/Analysis/ThreadSafetyLogical.cpp b/lib/Analysis/ThreadSafetyLogical.cpp
new file mode 100644
index 0000000..51a8077
--- /dev/null
+++ b/lib/Analysis/ThreadSafetyLogical.cpp
@@ -0,0 +1,112 @@
+//===- ThreadSafetyLogical.cpp ---------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file defines a representation for logical expressions with SExpr leaves
+// that are used as part of fact-checking capability expressions.
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
+
+using namespace llvm;
+using namespace clang::threadSafety::lexpr;
+
+// Implication. We implement De Morgan's Laws by maintaining LNeg and RNeg
+// to keep track of whether LHS and RHS are negated.
+static bool implies(const LExpr *LHS, bool LNeg, const LExpr *RHS, bool RNeg) {
+ // In comments below, we write => for implication.
+
+ // Calculates the logical AND implication operator.
+ const auto LeftAndOperator = [=](const BinOp *A) {
+ return implies(A->left(), LNeg, RHS, RNeg) &&
+ implies(A->right(), LNeg, RHS, RNeg);
+ };
+ const auto RightAndOperator = [=](const BinOp *A) {
+ return implies(LHS, LNeg, A->left(), RNeg) &&
+ implies(LHS, LNeg, A->right(), RNeg);
+ };
+
+ // Calculates the logical OR implication operator.
+ const auto LeftOrOperator = [=](const BinOp *A) {
+ return implies(A->left(), LNeg, RHS, RNeg) ||
+ implies(A->right(), LNeg, RHS, RNeg);
+ };
+ const auto RightOrOperator = [=](const BinOp *A) {
+ return implies(LHS, LNeg, A->left(), RNeg) ||
+ implies(LHS, LNeg, A->right(), RNeg);
+ };
+
+ // Recurse on right.
+ switch (RHS->kind()) {
+ case LExpr::And:
+ // When performing right recursion:
+ // C => A & B [if] C => A and C => B
+ // When performing right recursion (negated):
+ // C => !(A & B) [if] C => !A | !B [===] C => !A or C => !B
+ return RNeg ? RightOrOperator(cast<And>(RHS))
+ : RightAndOperator(cast<And>(RHS));
+ case LExpr::Or:
+ // When performing right recursion:
+ // C => (A | B) [if] C => A or C => B
+ // When performing right recursion (negated):
+ // C => !(A | B) [if] C => !A & !B [===] C => !A and C => !B
+ return RNeg ? RightAndOperator(cast<Or>(RHS))
+ : RightOrOperator(cast<Or>(RHS));
+ case LExpr::Not:
+ // Note that C => !A is very different from !(C => A). It would be incorrect
+ // to return !implies(LHS, RHS).
+ return implies(LHS, LNeg, cast<Not>(RHS)->exp(), !RNeg);
+ case LExpr::Terminal:
+ // After reaching the terminal, it's time to recurse on the left.
+ break;
+ }
+
+ // RHS is now a terminal. Recurse on Left.
+ switch (LHS->kind()) {
+ case LExpr::And:
+ // When performing left recursion:
+ // A & B => C [if] A => C or B => C
+ // When performing left recursion (negated):
+ // !(A & B) => C [if] !A | !B => C [===] !A => C and !B => C
+ return LNeg ? LeftAndOperator(cast<And>(LHS))
+ : LeftOrOperator(cast<And>(LHS));
+ case LExpr::Or:
+ // When performing left recursion:
+ // A | B => C [if] A => C and B => C
+ // When performing left recursion (negated):
+ // !(A | B) => C [if] !A & !B => C [===] !A => C or !B => C
+ return LNeg ? LeftOrOperator(cast<Or>(LHS))
+ : LeftAndOperator(cast<Or>(LHS));
+ case LExpr::Not:
+ // Note that A => !C is very different from !(A => C). It would be incorrect
+ // to return !implies(LHS, RHS).
+ return implies(cast<Not>(LHS)->exp(), !LNeg, RHS, RNeg);
+ case LExpr::Terminal:
+ // After reaching the terminal, it's time to perform identity comparisons.
+ break;
+ }
+
+ // A => A
+ // !A => !A
+ if (LNeg != RNeg)
+ return false;
+
+ // FIXME -- this should compare SExprs for equality, not pointer equality.
+ return cast<Terminal>(LHS)->expr() == cast<Terminal>(RHS)->expr();
+}
+
+namespace clang {
+namespace threadSafety {
+namespace lexpr {
+
+bool implies(const LExpr *LHS, const LExpr *RHS) {
+ // Start out by assuming that LHS and RHS are not negated.
+ return ::implies(LHS, false, RHS, false);
+}
+}
+}
+}
diff --git a/lib/Analysis/ThreadSafetyTIL.cpp b/lib/Analysis/ThreadSafetyTIL.cpp
new file mode 100644
index 0000000..f4da8d4
--- /dev/null
+++ b/lib/Analysis/ThreadSafetyTIL.cpp
@@ -0,0 +1,113 @@
+//===- ThreadSafetyTIL.cpp -------------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT in the llvm repository for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+
+namespace clang {
+namespace threadSafety {
+namespace til {
+
+
+StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op) {
+ switch (Op) {
+ case UOP_Minus: return "-";
+ case UOP_BitNot: return "~";
+ case UOP_LogicNot: return "!";
+ }
+ return "";
+}
+
+
+StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op) {
+ switch (Op) {
+ case BOP_Mul: return "*";
+ case BOP_Div: return "/";
+ case BOP_Rem: return "%";
+ case BOP_Add: return "+";
+ case BOP_Sub: return "-";
+ case BOP_Shl: return "<<";
+ case BOP_Shr: return ">>";
+ case BOP_BitAnd: return "&";
+ case BOP_BitXor: return "^";
+ case BOP_BitOr: return "|";
+ case BOP_Eq: return "==";
+ case BOP_Neq: return "!=";
+ case BOP_Lt: return "<";
+ case BOP_Leq: return "<=";
+ case BOP_LogicAnd: return "&&";
+ case BOP_LogicOr: return "||";
+ }
+ return "";
+}
+
+
+
+// If E is a variable, then trace back through any aliases or redundant
+// Phi nodes to find the canonical definition.
+SExpr *getCanonicalVal(SExpr *E) {
+ while (auto *V = dyn_cast<Variable>(E)) {
+ SExpr *D;
+ do {
+ if (V->kind() != Variable::VK_Let)
+ return V;
+ D = V->definition();
+ auto *V2 = dyn_cast<Variable>(D);
+ if (V2)
+ V = V2;
+ else
+ break;
+ } while (true);
+
+ if (ThreadSafetyTIL::isTrivial(D))
+ return D;
+
+ if (Phi *Ph = dyn_cast<Phi>(D)) {
+ if (Ph->status() == Phi::PH_Incomplete)
+ simplifyIncompleteArg(V, Ph);
+
+ if (Ph->status() == Phi::PH_SingleVal) {
+ E = Ph->values()[0];
+ continue;
+ }
+ }
+ return V;
+ }
+ return E;
+}
+
+
+// Trace the arguments of an incomplete Phi node to see if they have the same
+// canonical definition. If so, mark the Phi node as redundant.
+// getCanonicalVal() will recursively call simplifyIncompletePhi().
+void simplifyIncompleteArg(Variable *V, til::Phi *Ph) {
+ assert(Ph && Ph->status() == Phi::PH_Incomplete);
+
+ // eliminate infinite recursion -- assume that this node is not redundant.
+ Ph->setStatus(Phi::PH_MultiVal);
+
+ SExpr *E0 = getCanonicalVal(Ph->values()[0]);
+ for (unsigned i=1, n=Ph->values().size(); i<n; ++i) {
+ SExpr *Ei = getCanonicalVal(Ph->values()[i]);
+ if (Ei == V)
+ continue; // Recursive reference to itself. Don't count.
+ if (Ei != E0) {
+ return; // Status is already set to MultiVal.
+ }
+ }
+ Ph->setStatus(Phi::PH_SingleVal);
+ // Eliminate Redundant Phi node.
+ V->setDefinition(Ph->values()[0]);
+}
+
+
+} // end namespace til
+} // end namespace threadSafety
+} // end namespace clang
+
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index 29c17c3..4b8a59c 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -236,7 +236,7 @@
}
const CFGBlock *DataflowWorklist::dequeue() {
- const CFGBlock *B = 0;
+ const CFGBlock *B = nullptr;
// First dequeue from the worklist. This can represent
// updates along backedges that we want propagated as quickly as possible.
@@ -250,7 +250,7 @@
++PO_I;
}
else {
- return 0;
+ return nullptr;
}
assert(enqueuedBlocks[B->getBlockID()] == true);
@@ -295,7 +295,7 @@
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
if (isTrackedVar(VD, DC))
return FindVarResult(VD, DRE);
- return FindVarResult(0, 0);
+ return FindVarResult(nullptr, nullptr);
}
/// \brief Classify each DeclRefExpr as an initialization or a use. Any
@@ -353,7 +353,7 @@
if (DRE && DRE->getDecl() == VD)
return DRE;
}
- return 0;
+ return nullptr;
}
void ClassifyRefs::classify(const Expr *E, Class C) {
@@ -542,7 +542,7 @@
// This block initializes the variable.
continue;
if (AtPredExit == MayUninitialized &&
- vals.getValue(B, 0, vd) == Uninitialized) {
+ vals.getValue(B, nullptr, vd) == Uninitialized) {
// This block declares the variable (uninitialized), and is reachable
// from a block that initializes the variable. We can't guarantee to
// give an earlier location for the diagnostic (and it appears that
diff --git a/lib/Basic/Android.mk b/lib/Basic/Android.mk
index 54e61c2..03b131c 100644
--- a/lib/Basic/Android.mk
+++ b/lib/Basic/Android.mk
@@ -42,7 +42,8 @@
TokenKinds.cpp \
Version.cpp \
VersionTuple.cpp \
- VirtualFileSystem.cpp
+ VirtualFileSystem.cpp \
+ Warnings.cpp
LOCAL_SRC_FILES := $(clang_basic_SRC_FILES)
diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
index 2fd00dd0..6c78dc3 100644
--- a/lib/Basic/Builtins.cpp
+++ b/lib/Basic/Builtins.cpp
@@ -20,7 +20,7 @@
using namespace clang;
static const Builtin::Info BuiltinInfo[] = {
- { "not a builtin function", 0, 0, 0, ALL_LANGUAGES },
+ { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES},
#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
#define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) { #ID, TYPE, ATTRS, 0, BUILTIN_LANG },
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) { #ID, TYPE, ATTRS, HEADER,\
@@ -37,7 +37,7 @@
Builtin::Context::Context() {
// Get the target specific builtins from the target.
- TSRecords = 0;
+ TSRecords = nullptr;
NumTSRecords = 0;
}
@@ -116,7 +116,7 @@
++Like;
assert(::strchr(Like, ':') && "Format specifier must end with a ':'");
- FormatIdx = ::strtol(Like, 0, 10);
+ FormatIdx = ::strtol(Like, nullptr, 10);
return true;
}
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index 0448fdb..0df82b3 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -25,6 +25,7 @@
Version.cpp
VersionTuple.cpp
VirtualFileSystem.cpp
+ Warnings.cpp
)
# Determine Subversion revision.
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index f507548..13d2524 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -41,9 +41,9 @@
DiagnosticOptions *DiagOpts,
DiagnosticConsumer *client, bool ShouldOwnClient)
: Diags(diags), DiagOpts(DiagOpts), Client(client),
- OwnsDiagClient(ShouldOwnClient), SourceMgr(0) {
+ OwnsDiagClient(ShouldOwnClient), SourceMgr(nullptr) {
ArgToStringFn = DummyArgToStringFn;
- ArgToStringCookie = 0;
+ ArgToStringCookie = nullptr;
AllExtensionsSilenced = 0;
IgnoreAllWarnings = false;
@@ -157,7 +157,7 @@
if (LastStateChangePos.isValid() &&
Loc.isBeforeInTranslationUnitThan(LastStateChangePos))
Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(),
- DiagStatePoint(0, Loc));
+ DiagStatePoint(nullptr, Loc));
--Pos;
return Pos;
}
@@ -323,22 +323,19 @@
CurDiagID = storedDiag.getID();
NumDiagArgs = 0;
- NumDiagRanges = storedDiag.range_size();
- assert(NumDiagRanges < DiagnosticsEngine::MaxRanges &&
- "Too many arguments to diagnostic!");
- unsigned i = 0;
+ DiagRanges.clear();
+ DiagRanges.reserve(storedDiag.range_size());
for (StoredDiagnostic::range_iterator
RI = storedDiag.range_begin(),
RE = storedDiag.range_end(); RI != RE; ++RI)
- DiagRanges[i++] = *RI;
+ DiagRanges.push_back(*RI);
- assert(NumDiagRanges < DiagnosticsEngine::MaxFixItHints &&
- "Too many arguments to diagnostic!");
- NumDiagFixItHints = 0;
+ DiagFixItHints.clear();
+ DiagFixItHints.reserve(storedDiag.fixit_size());
for (StoredDiagnostic::fixit_iterator
FI = storedDiag.fixit_begin(),
FE = storedDiag.fixit_end(); FI != FE; ++FI)
- DiagFixItHints[NumDiagFixItHints++] = *FI;
+ DiagFixItHints.push_back(*FI);
assert(Client && "DiagnosticConsumer not set!");
Level DiagLevel = storedDiag.getLevel();
@@ -612,7 +609,7 @@
case tok::identifier:
return "identifier";
default:
- return 0;
+ return nullptr;
}
}
@@ -672,7 +669,7 @@
// The digit is a number from 0-9 indicating which argument this comes from.
// The modifier is a string of digits from the set [-a-z]+, arguments is a
// brace enclosed string.
- const char *Modifier = 0, *Argument = 0;
+ const char *Modifier = nullptr, *Argument = nullptr;
unsigned ModifierLen = 0, ArgumentLen = 0;
// Check to see if we have a modifier. If so eat it.
diff --git a/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp
index cf6933a..4779859 100644
--- a/lib/Basic/DiagnosticIDs.cpp
+++ b/lib/Basic/DiagnosticIDs.cpp
@@ -109,7 +109,7 @@
// Out of bounds diag. Can't be in the table.
using namespace diag;
if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
- return 0;
+ return nullptr;
// Compute the index of the requested diagnostic in the static table.
// 1. Add the number of diagnostics in each category preceding the
@@ -139,7 +139,7 @@
// Avoid out of bounds reads.
if (ID + Offset >= StaticDiagInfoSize)
- return 0;
+ return nullptr;
assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize);
@@ -148,7 +148,7 @@
// happen when this function is called with an ID that points into a hole in
// the diagID space.
if (Found->DiagID != DiagID)
- return 0;
+ return nullptr;
return Found;
}
@@ -216,7 +216,7 @@
#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_CATEGORY_TABLE
- { 0, 0 }
+ { nullptr, 0 }
};
/// getNumberOfCategories - Return the number of categories
@@ -301,9 +301,7 @@
// Common Diagnostic implementation
//===----------------------------------------------------------------------===//
-DiagnosticIDs::DiagnosticIDs() {
- CustomDiagInfo = 0;
-}
+DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; }
DiagnosticIDs::~DiagnosticIDs() {
delete CustomDiagInfo;
@@ -316,7 +314,7 @@
/// \param FormatString A fixed diagnostic format string that will be hashed and
/// mapped to a unique DiagID.
unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
- if (CustomDiagInfo == 0)
+ if (!CustomDiagInfo)
CustomDiagInfo = new diag::CustomDiagInfo();
return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
}
@@ -361,6 +359,11 @@
return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR;
}
+bool DiagnosticIDs::isRemark(unsigned DiagID) {
+ return DiagID < diag::DIAG_UPPER_LIMIT &&
+ getBuiltinDiagClass(DiagID) == CLASS_REMARK;
+}
+
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index 579c818..14731f6 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -70,7 +70,7 @@
void FileManager::addStatCache(FileSystemStatCache *statCache,
bool AtBeginning) {
assert(statCache && "No stat cache provided?");
- if (AtBeginning || StatCache.get() == 0) {
+ if (AtBeginning || !StatCache.get()) {
statCache->setNextStatCache(StatCache.release());
StatCache.reset(statCache);
return;
@@ -103,7 +103,7 @@
}
void FileManager::clearStatCaches() {
- StatCache.reset(0);
+ StatCache.reset(nullptr);
}
/// \brief Retrieve the directory that the given file name resides in.
@@ -112,10 +112,10 @@
StringRef Filename,
bool CacheFailure) {
if (Filename.empty())
- return NULL;
+ return nullptr;
if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
- return NULL; // If Filename is a directory.
+ return nullptr; // If Filename is a directory.
StringRef DirName = llvm::sys::path::parent_path(Filename);
// Use the current directory if file has no path component.
@@ -179,8 +179,8 @@
// See if there was already an entry in the map. Note that the map
// contains both virtual and real directories.
if (NamedDirEnt.getValue())
- return NamedDirEnt.getValue() == NON_EXISTENT_DIR
- ? 0 : NamedDirEnt.getValue();
+ return NamedDirEnt.getValue() == NON_EXISTENT_DIR ? nullptr
+ : NamedDirEnt.getValue();
++NumDirCacheMisses;
@@ -193,11 +193,11 @@
// Check to see if the directory exists.
FileData Data;
- if (getStatValue(InterndDirName, Data, false, 0 /*directory lookup*/)) {
+ if (getStatValue(InterndDirName, Data, false, nullptr /*directory lookup*/)) {
// There's no real directory at the given path.
if (!CacheFailure)
SeenDirEntries.erase(DirName);
- return 0;
+ return nullptr;
}
// It exists. See if we have already opened a directory with the
@@ -227,7 +227,7 @@
// See if there is already an entry in the map.
if (NamedFileEnt.getValue())
return NamedFileEnt.getValue() == NON_EXISTENT_FILE
- ? 0 : NamedFileEnt.getValue();
+ ? nullptr : NamedFileEnt.getValue();
++NumFileCacheMisses;
@@ -245,25 +245,25 @@
// without a 'sys' subdir will get a cached failure result.
const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename,
CacheFailure);
- if (DirInfo == 0) { // Directory doesn't exist, file can't exist.
+ if (DirInfo == nullptr) { // Directory doesn't exist, file can't exist.
if (!CacheFailure)
SeenFileEntries.erase(Filename);
-
- return 0;
+
+ return nullptr;
}
// FIXME: Use the directory info to prune this, before doing the stat syscall.
// FIXME: This will reduce the # syscalls.
// Nope, there isn't. Check to see if the file exists.
- vfs::File *F = 0;
+ vfs::File *F = nullptr;
FileData Data;
- if (getStatValue(InterndFileName, Data, true, openFile ? &F : 0)) {
+ if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) {
// There's no real file at the given path.
if (!CacheFailure)
SeenFileEntries.erase(Filename);
-
- return 0;
+
+ return nullptr;
}
assert((openFile || !F) && "undesired open file");
@@ -274,6 +274,16 @@
NamedFileEnt.setValue(&UFE);
if (UFE.isValid()) { // Already have an entry with this inode, return it.
+
+ // FIXME: this hack ensures that if we look up a file by a virtual path in
+ // the VFS that the getDir() will have the virtual path, even if we found
+ // the file by a 'real' path first. This is required in order to find a
+ // module's structure when its headers/module map are mapped in the VFS.
+ // We should remove this as soon as we can properly support a file having
+ // multiple names.
+ if (DirInfo != UFE.Dir && Data.IsVFSMapped)
+ UFE.Dir = DirInfo;
+
// If the stat process opened the file, close it to avoid a FD leak.
if (F)
delete F;
@@ -314,7 +324,7 @@
NamedFileEnt.setValue(NON_EXISTENT_FILE);
addAncestorsAsVirtualDirs(Filename);
- FileEntry *UFE = 0;
+ FileEntry *UFE = nullptr;
// Now that all ancestors of Filename are in the cache, the
// following call is guaranteed to find the DirectoryEntry from the
@@ -327,7 +337,7 @@
// Check to see if the file exists. If so, drop the virtual file
FileData Data;
const char *InterndFileName = NamedFileEnt.getKeyData();
- if (getStatValue(InterndFileName, Data, true, 0) == 0) {
+ if (getStatValue(InterndFileName, Data, true, nullptr) == 0) {
Data.Size = Size;
Data.ModTime = ModificationTime;
UFE = &UniqueRealFiles[Data.UniqueID];
@@ -391,7 +401,8 @@
const char *Filename = Entry->getName();
// If the file is already open, use the open file descriptor.
if (Entry->File) {
- ec = Entry->File->getBuffer(Filename, Result, FileSize);
+ ec = Entry->File->getBuffer(Filename, Result, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
if (ErrorStr)
*ErrorStr = ec.message();
Entry->closeFile();
@@ -401,7 +412,8 @@
// Otherwise, open the file.
if (FileSystemOpts.WorkingDir.empty()) {
- ec = FS->getBufferForFile(Filename, Result, FileSize);
+ ec = FS->getBufferForFile(Filename, Result, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
if (ec && ErrorStr)
*ErrorStr = ec.message();
return Result.release();
@@ -409,7 +421,8 @@
SmallString<128> FilePath(Entry->getName());
FixupRelativePath(FilePath);
- ec = FS->getBufferForFile(FilePath.str(), Result, FileSize);
+ ec = FS->getBufferForFile(FilePath.str(), Result, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
if (ec && ErrorStr)
*ErrorStr = ec.message();
return Result.release();
diff --git a/lib/Basic/FileSystemStatCache.cpp b/lib/Basic/FileSystemStatCache.cpp
index 9d87999..0f16e94 100644
--- a/lib/Basic/FileSystemStatCache.cpp
+++ b/lib/Basic/FileSystemStatCache.cpp
@@ -39,6 +39,7 @@
Data.IsDirectory = Status.isDirectory();
Data.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
Data.InPCH = false;
+ Data.IsVFSMapped = Status.IsVFSMapped;
}
/// FileSystemStatCache::get - Get the 'stat' information for the specified
@@ -96,7 +97,7 @@
// fstat rarely fails. If it does, claim the initial open didn't
// succeed.
R = CacheMissing;
- *F = 0;
+ *F = nullptr;
}
}
}
@@ -110,7 +111,7 @@
// If not, close the file if opened.
if (F && *F) {
(*F)->close();
- *F = 0;
+ *F = nullptr;
}
return true;
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 3b8aeec..2198459 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -12,11 +12,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
@@ -42,8 +44,8 @@
RevertedTokenID = false;
OutOfDate = false;
IsModulesImport = false;
- FETokenInfo = 0;
- Entry = 0;
+ FETokenInfo = nullptr;
+ Entry = nullptr;
}
//===----------------------------------------------------------------------===//
@@ -527,7 +529,7 @@
llvm::FoldingSetNodeID ID;
MultiKeywordSelector::Profile(ID, IIV, nKeys);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (MultiKeywordSelector *SI =
SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
return Selector(SI);
@@ -555,7 +557,7 @@
switch (Operator) {
case OO_None:
case NUM_OVERLOADED_OPERATORS:
- return 0;
+ return nullptr;
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
case OO_##Name: return Spelling;
diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 237c789..f689c73 100644
--- a/lib/Basic/Module.cpp
+++ b/lib/Basic/Module.cpp
@@ -25,13 +25,14 @@
using namespace clang;
Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
- bool IsFramework, bool IsExplicit)
- : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
- Umbrella(), ASTFile(0), IsAvailable(true), IsFromModuleFile(false),
- IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
- IsExternC(false), InferSubmodules(false), InferExplicitSubmodules(false),
- InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NameVisibility(Hidden) {
+ const FileEntry *File, bool IsFramework, bool IsExplicit)
+ : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), ModuleMap(File),
+ Umbrella(), ASTFile(nullptr), IsMissingRequirement(false),
+ IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
+ IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
+ IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
+ InferExportWildcard(false), ConfigMacrosExhaustive(false),
+ NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
@@ -39,6 +40,7 @@
IsSystem = true;
if (Parent->IsExternC)
IsExternC = true;
+ IsMissingRequirement = Parent->IsMissingRequirement;
Parent->SubModuleIndex[Name] = Parent->SubModules.size();
Parent->SubModules.push_back(this);
@@ -91,7 +93,7 @@
llvm_unreachable("could not find a reason why module is unavailable");
}
-bool Module::isSubModuleOf(Module *Other) const {
+bool Module::isSubModuleOf(const Module *Other) const {
const Module *This = this;
do {
if (This == Other)
@@ -160,6 +162,10 @@
if (hasFeature(Feature, LangOpts, Target) == RequiredState)
return;
+ markUnavailable(/*MissingRequirement*/true);
+}
+
+void Module::markUnavailable(bool MissingRequirement) {
if (!IsAvailable)
return;
@@ -173,6 +179,7 @@
continue;
Current->IsAvailable = false;
+ Current->IsMissingRequirement |= MissingRequirement;
for (submodule_iterator Sub = Current->submodule_begin(),
SubEnd = Current->submodule_end();
Sub != SubEnd; ++Sub) {
@@ -185,8 +192,8 @@
Module *Module::findSubmodule(StringRef Name) const {
llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
if (Pos == SubModuleIndex.end())
- return 0;
-
+ return nullptr;
+
return SubModules[Pos->getValue()];
}
@@ -354,7 +361,8 @@
for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end();
MI != MIEnd; ++MI)
- (*MI)->print(OS, Indent + 2);
+ if (!(*MI)->IsInferred)
+ (*MI)->print(OS, Indent + 2);
for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
OS.indent(Indent + 2);
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index ec09de1..c014241 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -29,14 +29,13 @@
}
const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) {
- assert(Kind < NUM_OPENMP_DIRECTIVES);
+ assert(Kind <= OMPD_unknown);
switch (Kind) {
case OMPD_unknown:
return "unknown";
#define OPENMP_DIRECTIVE(Name) \
case OMPD_##Name : return #Name;
#include "clang/Basic/OpenMPKinds.def"
- case NUM_OPENMP_DIRECTIVES:
break;
}
llvm_unreachable("Invalid OpenMP directive kind");
@@ -51,7 +50,7 @@
}
const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) {
- assert(Kind < NUM_OPENMP_CLAUSES);
+ assert(Kind <= OMPC_unknown);
switch (Kind) {
case OMPC_unknown:
return "unknown";
@@ -60,8 +59,6 @@
#include "clang/Basic/OpenMPKinds.def"
case OMPC_threadprivate:
return "threadprivate or thread local";
- case NUM_OPENMP_CLAUSES:
- break;
}
llvm_unreachable("Invalid OpenMP clause kind");
}
@@ -75,16 +72,23 @@
.Case(#Name, OMPC_DEFAULT_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_DEFAULT_unknown);
+ case OMPC_proc_bind:
+ return llvm::StringSwitch<OpenMPProcBindClauseKind>(Str)
+#define OPENMP_PROC_BIND_KIND(Name) \
+ .Case(#Name, OMPC_PROC_BIND_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_PROC_BIND_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_linear:
case OMPC_copyin:
- case NUM_OPENMP_CLAUSES:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -102,16 +106,26 @@
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'default' clause type");
+ case OMPC_proc_bind:
+ switch (Type) {
+ case OMPC_PROC_BIND_unknown:
+ return "unknown";
+#define OPENMP_PROC_BIND_KIND(Name) \
+ case OMPC_PROC_BIND_##Name : return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'proc_bind' clause type");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_linear:
case OMPC_copyin:
- case NUM_OPENMP_CLAUSES:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -119,8 +133,8 @@
bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind) {
- assert(DKind < NUM_OPENMP_DIRECTIVES);
- assert(CKind < NUM_OPENMP_CLAUSES);
+ assert(DKind <= OMPD_unknown);
+ assert(CKind <= OMPC_unknown);
switch (DKind) {
case OMPD_parallel:
switch (CKind) {
@@ -143,7 +157,6 @@
case OMPD_unknown:
case OMPD_threadprivate:
case OMPD_task:
- case NUM_OPENMP_DIRECTIVES:
break;
}
return false;
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index b78e9f5..d2d5562 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -89,7 +89,7 @@
bool *Invalid) const {
// Lazily create the Buffer for ContentCaches that wrap files. If we already
// computed it, just return what we have.
- if (Buffer.getPointer() || ContentsEntry == 0) {
+ if (Buffer.getPointer() || !ContentsEntry) {
if (Invalid)
*Invalid = isBufferInvalid();
@@ -163,7 +163,7 @@
.StartsWith("\x0E\xFE\xFF", "SDSU")
.StartsWith("\xFB\xEE\x28", "BOCU-1")
.StartsWith("\x84\x31\x95\x33", "GB-18030")
- .Default(0);
+ .Default(nullptr);
if (InvalidBOM) {
Diag.Report(Loc, diag::err_unsupported_bom)
@@ -272,7 +272,7 @@
// Do a binary search to find the maximal element that is still before Offset.
std::vector<LineEntry>::const_iterator I =
std::upper_bound(Entries.begin(), Entries.end(), Offset);
- if (I == Entries.begin()) return 0;
+ if (I == Entries.begin()) return nullptr;
return &*--I;
}
@@ -286,7 +286,7 @@
/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
///
unsigned SourceManager::getLineTableFilenameID(StringRef Name) {
- if (LineTable == 0)
+ if (!LineTable)
LineTable = new LineTableInfo();
return LineTable->getLineTableFilenameID(Name);
}
@@ -309,7 +309,7 @@
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
- if (LineTable == 0)
+ if (!LineTable)
LineTable = new LineTableInfo();
LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID);
}
@@ -339,7 +339,7 @@
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
- if (LineTable == 0)
+ if (!LineTable)
LineTable = new LineTableInfo();
SrcMgr::CharacteristicKind FileKind;
@@ -361,7 +361,7 @@
}
LineTableInfo &SourceManager::getLineTable() {
- if (LineTable == 0)
+ if (!LineTable)
LineTable = new LineTableInfo();
return *LineTable;
}
@@ -374,9 +374,9 @@
bool UserFilesAreVolatile)
: Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true),
UserFilesAreVolatile(UserFilesAreVolatile),
- ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
- NumBinaryProbes(0), FakeBufferForRecovery(0),
- FakeContentCacheForRecovery(0) {
+ ExternalSLocEntries(nullptr), LineTable(nullptr), NumLinearScans(0),
+ NumBinaryProbes(0), FakeBufferForRecovery(nullptr),
+ FakeContentCacheForRecovery(nullptr) {
clearIDTables();
Diag.setSourceManager(this);
}
@@ -413,7 +413,7 @@
LoadedSLocEntryTable.clear();
SLocEntryLoaded.clear();
LastLineNoFileIDQuery = FileID();
- LastLineNoContentCache = 0;
+ LastLineNoContentCache = nullptr;
LastFileIDLookup = FileID();
if (LineTable)
@@ -436,12 +436,8 @@
ContentCache *&Entry = FileInfos[FileEnt];
if (Entry) return Entry;
- // Nope, create a new Cache entry. Make sure it is at least 8-byte aligned
- // so that FileInfo can use the low 3 bits of the pointer for its own
- // nefarious purposes.
- unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
- EntryAlign = std::max(8U, EntryAlign);
- Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
+ // Nope, create a new Cache entry.
+ Entry = ContentCacheAlloc.Allocate<ContentCache>();
if (OverriddenFilesInfo) {
// If the file contents are overridden with contents from another file,
@@ -468,12 +464,8 @@
/// memory buffer. This does no caching.
const ContentCache*
SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
- // Add a new ContentCache to the MemBufferInfos list and return it. Make sure
- // it is at least 8-byte aligned so that FileInfo can use the low 3 bits of
- // the pointer for its own nefarious purposes.
- unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
- EntryAlign = std::max(8U, EntryAlign);
- ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
+ // Add a new ContentCache to the MemBufferInfos list and return it.
+ ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
new (Entry) ContentCache();
MemBufferInfos.push_back(Entry);
Entry->setBuffer(Buffer);
@@ -688,7 +680,7 @@
return;
const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
- const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(0);
+ const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(nullptr);
const_cast<SrcMgr::ContentCache *>(IR)->ContentsEntry = IR->OrigEntry;
assert(OverriddenFilesInfo);
@@ -1156,7 +1148,7 @@
// See if we just calculated the line number for this FilePos and can use
// that to lookup the start of the line instead of searching for it.
if (LastLineNoFileIDQuery == FID &&
- LastLineNoContentCache->SourceLineCache != 0 &&
+ LastLineNoContentCache->SourceLineCache != nullptr &&
LastLineNoResult < LastLineNoContentCache->NumLines) {
unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache;
unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
@@ -1320,7 +1312,7 @@
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
- if (Content->SourceLineCache == 0) {
+ if (!Content->SourceLineCache) {
bool MyInvalid = false;
ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
if (Invalid)
@@ -1704,7 +1696,8 @@
if (SLoc.isFile()) {
const ContentCache *FileContentCache
= SLoc.getFile().getContentCache();
- const FileEntry *Entry =FileContentCache? FileContentCache->OrigEntry : 0;
+ const FileEntry *Entry = FileContentCache ? FileContentCache->OrigEntry
+ : nullptr;
if (Entry &&
*SourceFileName == llvm::sys::path::filename(Entry->getName())) {
if (Optional<llvm::sys::fs::UniqueID> EntryUID =
@@ -1756,7 +1749,7 @@
// If this is the first use of line information for this buffer, compute the
// SourceLineCache for it on demand.
- if (Content->SourceLineCache == 0) {
+ if (!Content->SourceLineCache) {
bool MyInvalid = false;
ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
if (MyInvalid)
@@ -2132,7 +2125,7 @@
unsigned NumLineNumsComputed = 0;
unsigned NumFileBytesMapped = 0;
for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
- NumLineNumsComputed += I->second->SourceLineCache != 0;
+ NumLineNumsComputed += I->second->SourceLineCache != nullptr;
NumFileBytesMapped += I->second->getSizeBytesMapped();
}
unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 01eced2..4d06648 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -69,7 +69,7 @@
FloatFormat = &llvm::APFloat::IEEEsingle;
DoubleFormat = &llvm::APFloat::IEEEdouble;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
- DescriptionString = 0;
+ DescriptionString = nullptr;
UserLabelPrefix = "_";
MCountName = "mcount";
RegParmMax = 0;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index fd59c00..9343542 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -384,6 +384,17 @@
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_POSIX_THREADS");
+
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ Builder.defineMacro("__ARM_DWARF_EH__");
+ break;
+ }
}
public:
NetBSDTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
@@ -445,7 +456,6 @@
public:
BitrigTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
this->UserLabelPrefix = "";
- this->TLSSupported = false;
this->MCountName = "__mcount";
}
};
@@ -1346,7 +1356,7 @@
void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const override {
// No aliases.
- Aliases = 0;
+ Aliases = nullptr;
NumAliases = 0;
}
bool validateAsmConstraint(const char *&Name,
@@ -1439,7 +1449,7 @@
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
static const char *DescriptionStringSI =
- "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:32:32-p5:64:64"
+ "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-p24:64:64"
"-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
@@ -1473,13 +1483,13 @@
void getGCCRegNames(const char * const *&Names,
unsigned &numNames) const override {
- Names = NULL;
+ Names = nullptr;
numNames = 0;
}
void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const override {
- Aliases = NULL;
+ Aliases = nullptr;
NumAliases = 0;
}
@@ -1490,7 +1500,7 @@
void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const override {
- Records = NULL;
+ Records = nullptr;
NumRecords = 0;
}
@@ -1769,6 +1779,7 @@
CK_BDVER1,
CK_BDVER2,
CK_BDVER3,
+ CK_BDVER4,
//@}
/// This specification is deprecated and will be removed in the future.
@@ -1818,7 +1829,7 @@
}
void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const override {
- Aliases = 0;
+ Aliases = nullptr;
NumAliases = 0;
}
void getGCCAddlRegNames(const AddlRegName *&Names,
@@ -1912,6 +1923,7 @@
.Case("bdver1", CK_BDVER1)
.Case("bdver2", CK_BDVER2)
.Case("bdver3", CK_BDVER3)
+ .Case("bdver4", CK_BDVER4)
.Case("x86-64", CK_x86_64)
.Case("geode", CK_Geode)
.Default(CK_Generic);
@@ -1981,6 +1993,7 @@
case CK_BDVER1:
case CK_BDVER2:
case CK_BDVER3:
+ case CK_BDVER4:
case CK_x86_64:
return true;
}
@@ -2183,6 +2196,10 @@
setFeatureEnabledImpl(Features, "prfchw", true);
setFeatureEnabledImpl(Features, "cx16", true);
break;
+ case CK_BDVER4:
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ // FALLTHROUGH
case CK_BDVER2:
case CK_BDVER3:
setFeatureEnabledImpl(Features, "xop", true);
@@ -2686,6 +2703,9 @@
case CK_BDVER3:
defineCPUMacros(Builder, "bdver3");
break;
+ case CK_BDVER4:
+ defineCPUMacros(Builder, "bdver4");
+ break;
case CK_Geode:
defineCPUMacros(Builder, "geode");
break;
@@ -3051,7 +3071,6 @@
public:
WindowsX86_32TargetInfo(const llvm::Triple &Triple)
: WindowsTargetInfo<X86_32TargetInfo>(Triple) {
- TLSSupported = false;
WCharType = UnsignedShort;
DoubleAlign = LongLongAlign = 64;
DescriptionString = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32";
@@ -3066,9 +3085,9 @@
namespace {
// x86-32 Windows Visual Studio target
-class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo {
+class MicrosoftX86_32TargetInfo : public WindowsX86_32TargetInfo {
public:
- VisualStudioWindowsX86_32TargetInfo(const llvm::Triple &Triple)
+ MicrosoftX86_32TargetInfo(const llvm::Triple &Triple)
: WindowsX86_32TargetInfo(Triple) {
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
@@ -3085,6 +3104,33 @@
};
} // end anonymous namespace
+static void addMinGWDefines(const LangOptions &Opts, MacroBuilder &Builder) {
+ Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW32__");
+
+ // Mingw defines __declspec(a) to __attribute__((a)). Clang supports
+ // __declspec natively under -fms-extensions, but we define a no-op __declspec
+ // macro anyway for pre-processor compatibility.
+ if (Opts.MicrosoftExt)
+ Builder.defineMacro("__declspec", "__declspec");
+ else
+ Builder.defineMacro("__declspec(a)", "__attribute__((a))");
+
+ if (!Opts.MicrosoftExt) {
+ // Provide macros for all the calling convention keywords. Provide both
+ // single and double underscore prefixed variants. These are available on
+ // x64 as well as x86, even though they have no effect.
+ const char *CCs[] = {"cdecl", "stdcall", "fastcall", "thiscall", "pascal"};
+ for (const char *CC : CCs) {
+ std::string GCCSpelling = "__attribute__((__";
+ GCCSpelling += CC;
+ GCCSpelling += "__))";
+ Builder.defineMacro(Twine("_") + CC, GCCSpelling);
+ Builder.defineMacro(Twine("__") + CC, GCCSpelling);
+ }
+ }
+}
+
namespace {
// x86-32 MinGW target
class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo {
@@ -3097,17 +3143,7 @@
DefineStd(Builder, "WIN32", Opts);
DefineStd(Builder, "WINNT", Opts);
Builder.defineMacro("_X86_");
- Builder.defineMacro("__MSVCRT__");
- Builder.defineMacro("__MINGW32__");
-
- // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)).
- // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions.
- if (Opts.MicrosoftExt)
- // Provide "as-is" __declspec.
- Builder.defineMacro("__declspec", "__declspec");
- else
- // Provide alias of __attribute__ like mingw32-gcc.
- Builder.defineMacro("__declspec(a)", "__attribute__((a))");
+ addMinGWDefines(Opts, Builder);
}
};
} // end anonymous namespace
@@ -3270,7 +3306,6 @@
public:
WindowsX86_64TargetInfo(const llvm::Triple &Triple)
: WindowsTargetInfo<X86_64TargetInfo>(Triple) {
- TLSSupported = false;
WCharType = UnsignedShort;
LongWidth = LongAlign = 32;
DoubleAlign = LongLongAlign = 64;
@@ -3300,9 +3335,9 @@
namespace {
// x86-64 Windows Visual Studio target
-class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo {
+class MicrosoftX86_64TargetInfo : public WindowsX86_64TargetInfo {
public:
- VisualStudioWindowsX86_64TargetInfo(const llvm::Triple &Triple)
+ MicrosoftX86_64TargetInfo(const llvm::Triple &Triple)
: WindowsX86_64TargetInfo(Triple) {
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
@@ -3327,18 +3362,8 @@
MacroBuilder &Builder) const override {
WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
DefineStd(Builder, "WIN64", Opts);
- Builder.defineMacro("__MSVCRT__");
- Builder.defineMacro("__MINGW32__");
Builder.defineMacro("__MINGW64__");
-
- // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)).
- // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions.
- if (Opts.MicrosoftExt)
- // Provide "as-is" __declspec.
- Builder.defineMacro("__declspec", "__declspec");
- else
- // Provide alias of __attribute__ like mingw32-gcc.
- Builder.defineMacro("__declspec(a)", "__attribute__((a))");
+ addMinGWDefines(Opts, Builder);
}
};
} // end anonymous namespace
@@ -3383,282 +3408,6 @@
};
}
-namespace {
-class AArch64TargetInfo : public TargetInfo {
- virtual void setDescriptionString() = 0;
- static const char * const GCCRegNames[];
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
-
- enum FPUModeEnum {
- FPUMode,
- NeonMode
- };
-
- unsigned FPU;
- unsigned Crypto;
- static const Builtin::Info BuiltinInfo[];
-
-public:
- AArch64TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
- LongWidth = LongAlign = 64;
- LongDoubleWidth = LongDoubleAlign = 128;
- PointerWidth = PointerAlign = 64;
- SuitableAlign = 128;
-
- WCharType = UnsignedInt;
- if (getTriple().getOS() == llvm::Triple::NetBSD) {
- WCharType = SignedInt;
- Int64Type = SignedLongLong;
- IntMaxType = SignedLongLong;
- UIntMaxType = UnsignedLongLong;
- } else {
- WCharType = UnsignedInt;
- Int64Type = SignedLong;
- IntMaxType = SignedLong;
- UIntMaxType = UnsignedLong;
- }
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
-
- // AArch64 backend supports 64-bit operations at the moment. In principle
- // 128-bit is possible if register-pairs are used.
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
-
- TheCXXABI.set(TargetCXXABI::GenericAArch64);
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- // GCC defines theses currently
- Builder.defineMacro("__aarch64__");
-
- // ACLE predefines. Many can only have one possible value on v8 AArch64.
- Builder.defineMacro("__ARM_ACLE", "200");
- Builder.defineMacro("__ARM_ARCH", "8");
- Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
-
- Builder.defineMacro("__ARM_64BIT_STATE");
- Builder.defineMacro("__ARM_PCS_AAPCS64");
- Builder.defineMacro("__ARM_ARCH_ISA_A64");
-
- Builder.defineMacro("__ARM_FEATURE_UNALIGNED");
- Builder.defineMacro("__ARM_FEATURE_CLZ");
- Builder.defineMacro("__ARM_FEATURE_FMA");
- Builder.defineMacro("__ARM_FEATURE_DIV");
-
- Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
-
- // 0xe implies support for half, single and double precision operations.
- Builder.defineMacro("__ARM_FP", "0xe");
-
- // PCS specifies this for SysV variants, which is all we support. Other ABIs
- // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
- Builder.defineMacro("__ARM_FP16_FORMAT_IEEE");
-
- if (Opts.FastMath || Opts.FiniteMathOnly)
- Builder.defineMacro("__ARM_FP_FAST");
-
- if ((Opts.C99 || Opts.C11) && !Opts.Freestanding)
- Builder.defineMacro("__ARM_FP_FENV_ROUNDING");
-
- Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
- Opts.ShortWChar ? "2" : "4");
-
- Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM",
- Opts.ShortEnums ? "1" : "4");
-
- if (FPU == NeonMode) {
- Builder.defineMacro("__ARM_NEON");
- // 64-bit NEON supports half, single and double precision operations.
- Builder.defineMacro("__ARM_NEON_FP", "7");
- }
-
- if (Crypto) {
- Builder.defineMacro("__ARM_FEATURE_CRYPTO");
- }
- }
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::AArch64::LastTSBuiltin-Builtin::FirstTSBuiltin;
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "aarch64" || (Feature == "neon" && FPU == NeonMode);
- }
-
- bool setCPU(const std::string &Name) override {
- return llvm::StringSwitch<bool>(Name)
- .Case("generic", true)
- .Cases("cortex-a53", "cortex-a57", true)
- .Default(false);
- }
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override {
- FPU = FPUMode;
- Crypto = 0;
- for (unsigned i = 0, e = Features.size(); i != e; ++i) {
- if (Features[i] == "+neon")
- FPU = NeonMode;
- if (Features[i] == "+crypto")
- Crypto = 1;
- }
-
- setDescriptionString();
-
- return true;
- }
-
- void getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
-
- bool isCLZForZeroUndef() const override { return false; }
-
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default: return false;
- case 'w': // An FP/SIMD vector register
- Info.setAllowsRegister();
- return true;
- case 'I': // Constant that can be used with an ADD instruction
- case 'J': // Constant that can be used with a SUB instruction
- case 'K': // Constant that can be used with a 32-bit logical instruction
- case 'L': // Constant that can be used with a 64-bit logical instruction
- case 'M': // Constant that can be used as a 32-bit MOV immediate
- case 'N': // Constant that can be used as a 64-bit MOV immediate
- case 'Y': // Floating point constant zero
- case 'Z': // Integer constant zero
- return true;
- case 'Q': // A memory reference with base register and no offset
- Info.setAllowsMemory();
- return true;
- case 'S': // A symbolic address
- Info.setAllowsRegister();
- return true;
- case 'U':
- // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes, whatever they may be
- // Utf: A memory address suitable for ldp/stp in TF mode, whatever it may be
- // Usa: An absolute symbolic address
- // Ush: The high part (bits 32:12) of a pc-relative symbolic address
- llvm_unreachable("FIXME: Unimplemented support for bizarre constraints");
- }
- }
-
- const char *getClobbers() const override {
- // There are no AArch64 clobbers shared by all asm statements.
- return "";
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::AArch64ABIBuiltinVaList;
- }
-};
-
-const char * const AArch64TargetInfo::GCCRegNames[] = {
- "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
- "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
- "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
- "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", "wzr",
-
- "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
- "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
- "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
- "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", "xzr",
-
- "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
- "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15",
- "b16", "b17", "b18", "b19", "b20", "b21", "b22", "b23",
- "b24", "b25", "b26", "b27", "b28", "b29", "b30", "b31",
-
- "h0", "h1", "h2", "h3", "h4", "h5", "h6", "h7",
- "h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15",
- "h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23",
- "h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31",
-
- "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",
-
- "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
- "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
- "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
- "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
-
- "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
- "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
- "q16", "q17", "q18", "q19", "q20", "q21", "q22", "q23",
- "q24", "q25", "q26", "q27", "q28", "q29", "q30", "q31"
-};
-
-void AArch64TargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
- { { "x16" }, "ip0"},
- { { "x17" }, "ip1"},
- { { "x29" }, "fp" },
- { { "x30" }, "lr" }
-};
-
-void AArch64TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
-
-}
-
-const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
-#include "clang/Basic/BuiltinsNEON.def"
-
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
-#include "clang/Basic/BuiltinsAArch64.def"
-};
-
-class AArch64leTargetInfo : public AArch64TargetInfo {
- void setDescriptionString() override {
- DescriptionString = "e-m:e-i64:64-i128:128-n32:64-S128";
- }
-
-public:
- AArch64leTargetInfo(const llvm::Triple &Triple)
- : AArch64TargetInfo(Triple) {
- BigEndian = false;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__AARCH64EL__");
- AArch64TargetInfo::getTargetDefines(Opts, Builder);
- }
-};
-
-class AArch64beTargetInfo : public AArch64TargetInfo {
- void setDescriptionString() override {
- DescriptionString = "E-m:e-i64:64-i128:128-n32:64-S128";
- }
-
-public:
- AArch64beTargetInfo(const llvm::Triple &Triple)
- : AArch64TargetInfo(Triple) { }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__AARCH64EB__");
- Builder.defineMacro("__AARCH_BIG_ENDIAN");
- Builder.defineMacro("__ARM_BIG_ENDIAN");
- AArch64TargetInfo::getTargetDefines(Opts, Builder);
- }
-};
-
-} // end anonymous namespace
namespace {
class ARMTargetInfo : public TargetInfo {
@@ -3708,6 +3457,9 @@
static const Builtin::Info BuiltinInfo[];
static bool shouldUseInlineAtomic(const llvm::Triple &T) {
+ if (T.isOSWindows())
+ return true;
+
// On linux, binaries targeting old cpus call functions in libgcc to
// perform atomic operations. The implementation in libgcc then calls into
// the kernel which on armv6 and newer uses ldrex and strex. The net result
@@ -3760,11 +3512,18 @@
else
SizeType = UnsignedInt;
- if (T.getOS() == llvm::Triple::NetBSD) {
+ switch (T.getOS()) {
+ case llvm::Triple::NetBSD:
WCharType = SignedInt;
- } else {
+ break;
+ case llvm::Triple::Win32:
+ WCharType = UnsignedShort;
+ break;
+ case llvm::Triple::Linux:
+ default:
// AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int.
WCharType = UnsignedInt;
+ break;
}
UseBitFieldTypeAlignment = true;
@@ -3774,19 +3533,30 @@
if (IsThumb) {
// Thumb1 add sp, #imm requires the immediate value be multiple of 4,
// so set preferred for small types to 32.
- if (T.isOSBinFormatMachO())
+ if (T.isOSBinFormatMachO()) {
DescriptionString = BigEndian ?
"E-m:o-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-"
"v128:64:128-a:0:32-n32-S64" :
"e-m:o-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-"
"v128:64:128-a:0:32-n32-S64";
- else
+ } else if (T.isOSWindows()) {
+ // FIXME: this is invalid for WindowsCE
+ assert(!BigEndian && "Windows on ARM does not support big endian");
+ DescriptionString = "e"
+ "-m:e"
+ "-p:32:32"
+ "-i1:8:32-i8:8:32-i16:16:32-i64:64"
+ "-v128:64:128"
+ "-a:0:32"
+ "-n32"
+ "-S64";
+ } else {
DescriptionString = BigEndian ?
"E-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-"
"v128:64:128-a:0:32-n32-S64" :
"e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-"
"v128:64:128-a:0:32-n32-S64";
-
+ }
} else {
if (T.isOSBinFormatMachO())
DescriptionString = BigEndian ?
@@ -4052,7 +3822,7 @@
.Cases("cortex-m3", "cortex-m4", "7M")
.Case("cortex-m0", "6M")
.Cases("cortex-a53", "cortex-a57", "8A")
- .Default(0);
+ .Default(nullptr);
}
static const char *getCPUProfile(StringRef Name) {
return llvm::StringSwitch<const char*>(Name)
@@ -4095,12 +3865,14 @@
// FIXME: It's more complicated than this and we don't really support
// interworking.
- if (5 <= CPUArchVer && CPUArchVer <= 8)
+ // Windows on ARM does not "support" interworking
+ if (5 <= CPUArchVer && CPUArchVer <= 8 && !getTriple().isOSWindows())
Builder.defineMacro("__THUMB_INTERWORK__");
if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
// Embedded targets on Darwin follow AAPCS, but not EABI.
- if (!getTriple().isOSDarwin())
+ // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
+ if (!getTriple().isOSDarwin() && !getTriple().isOSWindows())
Builder.defineMacro("__ARM_EABI__");
Builder.defineMacro("__ARM_PCS", "1");
@@ -4373,6 +4145,72 @@
} // end anonymous namespace.
namespace {
+class WindowsARMTargetInfo : public WindowsTargetInfo<ARMleTargetInfo> {
+ const llvm::Triple Triple;
+public:
+ WindowsARMTargetInfo(const llvm::Triple &Triple)
+ : WindowsTargetInfo<ARMleTargetInfo>(Triple), Triple(Triple) {
+ TLSSupported = false;
+ WCharType = UnsignedShort;
+ SizeType = UnsignedInt;
+ UserLabelPrefix = "";
+ }
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
+
+ // FIXME: this is invalid for WindowsCE
+ Builder.defineMacro("_M_ARM_NT", "1");
+ Builder.defineMacro("_M_ARMT", "_M_ARM");
+ Builder.defineMacro("_M_THUMB", "_M_ARM");
+
+ assert((Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb) &&
+ "invalid architecture for Windows ARM target info");
+ unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
+ Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
+
+ // TODO map the complete set of values
+ // 31: VFPv3 40: VFPv4
+ Builder.defineMacro("_M_ARM_FP", "31");
+ }
+};
+
+// Windows ARM + Itanium C++ ABI Target
+class ItaniumWindowsARMleTargetInfo : public WindowsARMTargetInfo {
+public:
+ ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple)
+ : WindowsARMTargetInfo(Triple) {
+ TheCXXABI.set(TargetCXXABI::GenericARM);
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+
+ if (Opts.MSVCCompat)
+ WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+ }
+};
+
+// Windows ARM, MS (C++) ABI
+class MicrosoftARMleTargetInfo : public WindowsARMTargetInfo {
+public:
+ MicrosoftARMleTargetInfo(const llvm::Triple &Triple)
+ : WindowsARMTargetInfo(Triple) {
+ TheCXXABI.set(TargetCXXABI::Microsoft);
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+ WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+ }
+};
+}
+
+
+namespace {
class DarwinARMTargetInfo :
public DarwinTargetInfo<ARMleTargetInfo> {
protected:
@@ -4397,23 +4235,44 @@
namespace {
-class ARM64TargetInfo : public TargetInfo {
+class AArch64TargetInfo : public TargetInfo {
+ virtual void setDescriptionString() = 0;
static const TargetInfo::GCCRegAlias GCCRegAliases[];
static const char *const GCCRegNames[];
+ enum FPUModeEnum {
+ FPUMode,
+ NeonMode
+ };
+
+ unsigned FPU;
+ unsigned CRC;
+ unsigned Crypto;
+
static const Builtin::Info BuiltinInfo[];
std::string ABI;
public:
- ARM64TargetInfo(const llvm::Triple &Triple)
+ AArch64TargetInfo(const llvm::Triple &Triple)
: TargetInfo(Triple), ABI("aapcs") {
- BigEndian = false;
+
+ if (getTriple().getOS() == llvm::Triple::NetBSD) {
+ WCharType = SignedInt;
+
+ // NetBSD apparently prefers consistency across ARM targets to consistency
+ // across 64-bit targets.
+ Int64Type = SignedLongLong;
+ IntMaxType = SignedLongLong;
+ UIntMaxType = UnsignedLongLong;
+ } else {
+ WCharType = UnsignedInt;
+ Int64Type = SignedLong;
+ IntMaxType = SignedLong;
+ UIntMaxType = UnsignedLong;
+ }
+
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
- IntMaxType = SignedLong;
- UIntMaxType = UnsignedLong;
- Int64Type = SignedLong;
- WCharType = UnsignedInt;
MaxVectorAlign = 128;
RegParmMax = 8;
MaxAtomicInlineWidth = 128;
@@ -4422,16 +4281,11 @@
LongDoubleWidth = LongDoubleAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad;
- if (Triple.isOSBinFormatMachO())
- DescriptionString = "e-m:o-i64:64-i128:128-n32:64-S128";
- else
- DescriptionString = "e-m:e-i64:64-i128:128-n32:64-S128";
-
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;
- // ARM64 targets default to using the ARM C++ ABI.
+ // AArch64 targets default to using the ARM C++ ABI.
TheCXXABI.set(TargetCXXABI::GenericAArch64);
}
@@ -4446,7 +4300,8 @@
virtual bool setCPU(const std::string &Name) {
bool CPUKnown = llvm::StringSwitch<bool>(Name)
- .Case("arm64-generic", true)
+ .Case("generic", true)
+ .Cases("cortex-a53", "cortex-a57", true)
.Case("cyclone", true)
.Default(false);
return CPUKnown;
@@ -4455,23 +4310,11 @@
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Target identification.
- Builder.defineMacro("__arm64");
- Builder.defineMacro("__arm64__");
Builder.defineMacro("__aarch64__");
- Builder.defineMacro("__ARM64_ARCH_8__");
- Builder.defineMacro("__AARCH64_SIMD__");
- Builder.defineMacro("__ARM_NEON__");
// Target properties.
Builder.defineMacro("_LP64");
Builder.defineMacro("__LP64__");
- Builder.defineMacro("__LITTLE_ENDIAN__");
-
- // Subtarget options.
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- Builder.defineMacro("__aarch64__");
- Builder.defineMacro("__AARCH64EL__");
// ACLE predefines. Many can only have one possible value on v8 AArch64.
Builder.defineMacro("__ARM_ACLE", "200");
@@ -4507,31 +4350,48 @@
Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM",
Opts.ShortEnums ? "1" : "4");
- if (BigEndian)
- Builder.defineMacro("__ARM_BIG_ENDIAN");
+ if (FPU == NeonMode) {
+ Builder.defineMacro("__ARM_NEON");
+ // 64-bit NEON supports half, single and double precision operations.
+ Builder.defineMacro("__ARM_NEON_FP", "0xe");
+ }
- // FIXME: the target should support NEON as an optional extension, like
- // the OSS AArch64.
- Builder.defineMacro("__ARM_NEON");
- // 64-bit NEON supports half, single and double precision operations.
- Builder.defineMacro("__ARM_NEON_FP", "7");
+ if (CRC)
+ Builder.defineMacro("__ARM_FEATURE_CRC32");
- // FIXME: the target should support crypto as an optional extension, like
- // the OSS AArch64
- Builder.defineMacro("__ARM_FEATURE_CRYPTO");
+ if (Crypto)
+ Builder.defineMacro("__ARM_FEATURE_CRYPTO");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {
Records = BuiltinInfo;
- NumRecords = clang::ARM64::LastTSBuiltin - Builtin::FirstTSBuiltin;
+ NumRecords = clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin;
}
virtual bool hasFeature(StringRef Feature) const {
- return llvm::StringSwitch<bool>(Feature)
- .Case("arm64", true)
- .Case("neon", true)
- .Default(false);
+ return Feature == "aarch64" ||
+ Feature == "arm64" ||
+ (Feature == "neon" && FPU == NeonMode);
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ FPU = FPUMode;
+ CRC = 0;
+ Crypto = 0;
+ for (unsigned i = 0, e = Features.size(); i != e; ++i) {
+ if (Features[i] == "+neon")
+ FPU = NeonMode;
+ if (Features[i] == "+crc")
+ CRC = 1;
+ if (Features[i] == "+crypto")
+ Crypto = 1;
+ }
+
+ setDescriptionString();
+
+ return true;
}
virtual bool isCLZForZeroUndef() const { return false; }
@@ -4553,46 +4413,37 @@
case 'w': // Floating point and SIMD registers (V0-V31)
Info.setAllowsRegister();
return true;
+ case 'I': // Constant that can be used with an ADD instruction
+ case 'J': // Constant that can be used with a SUB instruction
+ case 'K': // Constant that can be used with a 32-bit logical instruction
+ case 'L': // Constant that can be used with a 64-bit logical instruction
+ case 'M': // Constant that can be used as a 32-bit MOV immediate
+ case 'N': // Constant that can be used as a 64-bit MOV immediate
+ case 'Y': // Floating point constant zero
+ case 'Z': // Integer constant zero
+ return true;
+ case 'Q': // A memory reference with base register and no offset
+ Info.setAllowsMemory();
+ return true;
+ case 'S': // A symbolic address
+ Info.setAllowsRegister();
+ return true;
+ case 'U':
+ // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes, whatever they may be
+ // Utf: A memory address suitable for ldp/stp in TF mode, whatever it may be
+ // Usa: An absolute symbolic address
+ // Ush: The high part (bits 32:12) of a pc-relative symbolic address
+ llvm_unreachable("FIXME: Unimplemented support for bizarre constraints");
case 'z': // Zero register, wzr or xzr
Info.setAllowsRegister();
return true;
case 'x': // Floating point and SIMD registers (V0-V15)
Info.setAllowsRegister();
return true;
- case 'Q': // A memory address that is a single base register.
- Info.setAllowsMemory();
- return true;
}
return false;
}
- virtual bool validateConstraintModifier(StringRef Constraint,
- const char Modifier,
- unsigned Size) const {
- // Strip off constraint modifiers.
- while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
- Constraint = Constraint.substr(1);
-
- switch (Constraint[0]) {
- default:
- return true;
- case 'z':
- case 'r': {
- switch (Modifier) {
- case 'x':
- case 'w':
- // For now assume that the person knows what they're
- // doing with the modifier.
- return true;
- default:
- // By default an 'r' constraint will be in the 'x'
- // registers.
- return (Size == 64);
- }
- }
- }
- }
-
virtual const char *getClobbers() const { return ""; }
int getEHDataRegisterNumber(unsigned RegNo) const {
@@ -4604,7 +4455,7 @@
}
};
-const char *const ARM64TargetInfo::GCCRegNames[] = {
+const char *const AArch64TargetInfo::GCCRegNames[] = {
// 32-bit Integer registers
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10",
"w11", "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21",
@@ -4631,13 +4482,13 @@
"v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
};
-void ARM64TargetInfo::getGCCRegNames(const char *const *&Names,
+void AArch64TargetInfo::getGCCRegNames(const char *const *&Names,
unsigned &NumNames) const {
Names = GCCRegNames;
NumNames = llvm::array_lengthof(GCCRegNames);
}
-const TargetInfo::GCCRegAlias ARM64TargetInfo::GCCRegAliases[] = {
+const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
{ { "w31" }, "wsp" },
{ { "x29" }, "fp" },
{ { "x30" }, "lr" },
@@ -4646,28 +4497,80 @@
// don't want to substitute one of these for a different-sized one.
};
-void ARM64TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+void AArch64TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const {
Aliases = GCCRegAliases;
NumAliases = llvm::array_lengthof(GCCRegAliases);
}
-const Builtin::Info ARM64TargetInfo::BuiltinInfo[] = {
+const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{ #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
#include "clang/Basic/BuiltinsNEON.def"
#define BUILTIN(ID, TYPE, ATTRS) \
{ #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#include "clang/Basic/BuiltinsARM64.def"
+#include "clang/Basic/BuiltinsAArch64.def"
+};
+
+class AArch64leTargetInfo : public AArch64TargetInfo {
+ void setDescriptionString() override {
+ if (getTriple().isOSBinFormatMachO())
+ DescriptionString = "e-m:o-i64:64-i128:128-n32:64-S128";
+ else
+ DescriptionString = "e-m:e-i64:64-i128:128-n32:64-S128";
+ }
+
+public:
+ AArch64leTargetInfo(const llvm::Triple &Triple)
+ : AArch64TargetInfo(Triple) {
+ BigEndian = false;
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__AARCH64EL__");
+ AArch64TargetInfo::getTargetDefines(Opts, Builder);
+ }
+};
+
+class AArch64beTargetInfo : public AArch64TargetInfo {
+ void setDescriptionString() override {
+ assert(!getTriple().isOSBinFormatMachO());
+ DescriptionString = "E-m:e-i64:64-i128:128-n32:64-S128";
+ }
+
+public:
+ AArch64beTargetInfo(const llvm::Triple &Triple)
+ : AArch64TargetInfo(Triple) { }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__AARCH64EB__");
+ Builder.defineMacro("__AARCH_BIG_ENDIAN");
+ Builder.defineMacro("__ARM_BIG_ENDIAN");
+ AArch64TargetInfo::getTargetDefines(Opts, Builder);
+ }
};
} // end anonymous namespace.
namespace {
-class DarwinARM64TargetInfo : public DarwinTargetInfo<ARM64TargetInfo> {
+class DarwinAArch64TargetInfo : public DarwinTargetInfo<AArch64leTargetInfo> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__AARCH64_SIMD__");
+ Builder.defineMacro("__ARM64_ARCH_8__");
+ Builder.defineMacro("__ARM_NEON__");
+ Builder.defineMacro("__LITTLE_ENDIAN__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+ Builder.defineMacro("__arm64", "1");
+ Builder.defineMacro("__arm64__", "1");
+
+ getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
+ }
+
public:
- DarwinARM64TargetInfo(const llvm::Triple &Triple)
- : DarwinTargetInfo<ARM64TargetInfo>(Triple) {
+ DarwinAArch64TargetInfo(const llvm::Triple &Triple)
+ : DarwinTargetInfo<AArch64leTargetInfo>(Triple) {
Int64Type = SignedLongLong;
WCharType = SignedInt;
UseSignedCharForObjCBool = false;
@@ -4734,7 +4637,7 @@
return llvm::StringSwitch<const char*>(Name)
.Case("hexagonv4", "4")
.Case("hexagonv5", "5")
- .Default(0);
+ .Default(nullptr);
}
bool setCPU(const std::string &Name) override {
@@ -5040,107 +4943,107 @@
} // end anonymous namespace.
namespace {
- class SystemZTargetInfo : public TargetInfo {
- static const char *const GCCRegNames[];
+class SystemZTargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
- public:
- SystemZTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
- TLSSupported = true;
- IntWidth = IntAlign = 32;
- LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
- PointerWidth = PointerAlign = 64;
- LongDoubleWidth = 128;
- LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
- MinGlobalAlign = 16;
- DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64";
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__s390__");
- Builder.defineMacro("__s390x__");
- Builder.defineMacro("__zarch__");
- Builder.defineMacro("__LONG_DOUBLE_128__");
- }
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- // FIXME: Implement.
- Records = 0;
- NumRecords = 0;
- }
-
- void getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
- // No aliases.
- Aliases = 0;
- NumAliases = 0;
- }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override;
- const char *getClobbers() const override {
- // FIXME: Is this really right?
- return "";
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::SystemZBuiltinVaList;
- }
- bool setCPU(const std::string &Name) override {
- 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;
- }
- };
-
- const char *const SystemZTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "f0", "f2", "f4", "f6", "f1", "f3", "f5", "f7",
- "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15"
- };
-
- void SystemZTargetInfo::getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+public:
+ SystemZTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ TLSSupported = true;
+ IntWidth = IntAlign = 32;
+ LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ MinGlobalAlign = 16;
+ DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64";
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__s390__");
+ Builder.defineMacro("__s390x__");
+ Builder.defineMacro("__zarch__");
+ Builder.defineMacro("__LONG_DOUBLE_128__");
+ }
+ void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const override {
+ // FIXME: Implement.
+ Records = nullptr;
+ NumRecords = 0;
}
- bool SystemZTargetInfo::
- validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- switch (*Name) {
- default:
- return false;
-
- case 'a': // Address register
- case 'd': // Data register (equivalent to 'r')
- case 'f': // Floating-point register
- Info.setAllowsRegister();
- return true;
-
- case 'I': // Unsigned 8-bit constant
- case 'J': // Unsigned 12-bit constant
- case 'K': // Signed 16-bit constant
- case 'L': // Signed 20-bit displacement (on all targets we support)
- case 'M': // 0x7fffffff
- return true;
-
- case 'Q': // Memory with base and unsigned 12-bit displacement
- case 'R': // Likewise, plus an index
- case 'S': // Memory with base and signed 20-bit displacement
- case 'T': // Likewise, plus an index
- Info.setAllowsMemory();
- return true;
- }
+ void getGCCRegNames(const char *const *&Names,
+ unsigned &NumNames) const override;
+ void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const override {
+ // No aliases.
+ Aliases = nullptr;
+ NumAliases = 0;
}
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override;
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::SystemZBuiltinVaList;
+ }
+ bool setCPU(const std::string &Name) override {
+ 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;
+ }
+};
+
+const char *const SystemZTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "f0", "f2", "f4", "f6", "f1", "f3", "f5", "f7",
+ "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15"
+};
+
+void SystemZTargetInfo::getGCCRegNames(const char *const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
+
+bool SystemZTargetInfo::
+validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+
+ case 'a': // Address register
+ case 'd': // Data register (equivalent to 'r')
+ case 'f': // Floating-point register
+ Info.setAllowsRegister();
+ return true;
+
+ case 'I': // Unsigned 8-bit constant
+ case 'J': // Unsigned 12-bit constant
+ case 'K': // Signed 16-bit constant
+ case 'L': // Signed 20-bit displacement (on all targets we support)
+ case 'M': // 0x7fffffff
+ return true;
+
+ case 'Q': // Memory with base and unsigned 12-bit displacement
+ case 'R': // Likewise, plus an index
+ case 'S': // Memory with base and signed 20-bit displacement
+ case 'T': // Likewise, plus an index
+ Info.setAllowsMemory();
+ return true;
+ }
+}
}
namespace {
@@ -5172,7 +5075,7 @@
void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const override {
// FIXME: Implement.
- Records = 0;
+ Records = nullptr;
NumRecords = 0;
}
bool hasFeature(StringRef Feature) const override {
@@ -5183,7 +5086,7 @@
void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const override {
// No aliases.
- Aliases = 0;
+ Aliases = nullptr;
NumAliases = 0;
}
bool validateAsmConstraint(const char *&Name,
@@ -5508,9 +5411,6 @@
std::find(Features.begin(), Features.end(), "+soft-float");
if (it != Features.end())
Features.erase(it);
- it = std::find(Features.begin(), Features.end(), "+nan2008");
- if (it != Features.end())
- Features.erase(it);
setDescriptionString();
@@ -5644,32 +5544,44 @@
public:
Mips64TargetInfoBase(const llvm::Triple &Triple)
: MipsTargetInfoBase(Triple, "n64", "mips64r2") {
- LongWidth = LongAlign = 64;
- PointerWidth = PointerAlign = 64;
LongDoubleWidth = LongDoubleAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad;
if (getTriple().getOS() == llvm::Triple::FreeBSD) {
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
}
+ setN64ABITypes();
SuitableAlign = 128;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
}
+
+ void setN64ABITypes() {
+ LongWidth = LongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ }
+
+ void setN32ABITypes() {
+ LongWidth = LongAlign = 32;
+ PointerWidth = PointerAlign = 32;
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ }
+
bool setABI(const std::string &Name) override {
if (Name == "n32") {
- LongWidth = LongAlign = 32;
- PointerWidth = PointerAlign = 32;
+ setN32ABITypes();
ABI = Name;
return true;
- } else if (Name == "n64") {
- ABI = Name;
- return true;
- } else if (Name == "64") {
+ } else if (Name == "n64" || Name == "64") {
+ setN64ABITypes();
ABI = "n64";
return true;
- } else
- return false;
+ }
+ return false;
}
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
MipsTargetInfoBase::getTargetDefines(Opts, Builder);
@@ -5729,6 +5641,8 @@
Aliases = GCCRegAliases;
NumAliases = llvm::array_lengthof(GCCRegAliases);
}
+
+ bool hasInt128Type() const override { return true; }
};
class Mips64EBTargetInfo : public Mips64TargetInfoBase {
@@ -5830,13 +5744,13 @@
void PNaClTargetInfo::getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const {
- Names = NULL;
+ Names = nullptr;
NumNames = 0;
}
void PNaClTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const {
- Aliases = NULL;
+ Aliases = nullptr;
NumAliases = 0;
}
} // end anonymous namespace.
@@ -5970,7 +5884,7 @@
}
void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const override {
- Aliases = NULL;
+ Aliases = nullptr;
NumAliases = 0;
}
bool validateAsmConstraint(const char *&Name,
@@ -6001,17 +5915,29 @@
switch (Triple.getArch()) {
default:
- return NULL;
+ return nullptr;
case llvm::Triple::arm64:
if (Triple.isOSDarwin())
- return new DarwinARM64TargetInfo(Triple);
+ return new DarwinAArch64TargetInfo(Triple);
switch (os) {
case llvm::Triple::Linux:
- return new LinuxTargetInfo<ARM64TargetInfo>(Triple);
+ return new LinuxTargetInfo<AArch64leTargetInfo>(Triple);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<AArch64leTargetInfo>(Triple);
default:
- return new ARM64TargetInfo(Triple);
+ return new AArch64leTargetInfo(Triple);
+ }
+
+ case llvm::Triple::arm64_be:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<AArch64beTargetInfo>(Triple);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<AArch64beTargetInfo>(Triple);
+ default:
+ return new AArch64beTargetInfo(Triple);
}
case llvm::Triple::xcore:
@@ -6060,6 +5986,15 @@
return new RTEMSTargetInfo<ARMleTargetInfo>(Triple);
case llvm::Triple::NaCl:
return new NaClTargetInfo<ARMleTargetInfo>(Triple);
+ case llvm::Triple::Win32:
+ switch (Triple.getEnvironment()) {
+ default:
+ return new ARMleTargetInfo(Triple);
+ case llvm::Triple::Itanium:
+ return new ItaniumWindowsARMleTargetInfo(Triple);
+ case llvm::Triple::MSVC:
+ return new MicrosoftARMleTargetInfo(Triple);
+ }
default:
return new ARMleTargetInfo(Triple);
}
@@ -6158,7 +6093,7 @@
case llvm::Triple::NaCl:
return new NaClTargetInfo<PNaClTargetInfo>(Triple);
default:
- return NULL;
+ return nullptr;
}
case llvm::Triple::ppc:
@@ -6292,7 +6227,7 @@
case llvm::Triple::GNU:
return new MinGWX86_32TargetInfo(Triple);
case llvm::Triple::MSVC:
- return new VisualStudioWindowsX86_32TargetInfo(Triple);
+ return new MicrosoftX86_32TargetInfo(Triple);
}
}
case llvm::Triple::Haiku:
@@ -6335,7 +6270,7 @@
case llvm::Triple::GNU:
return new MinGWX86_64TargetInfo(Triple);
case llvm::Triple::MSVC:
- return new VisualStudioWindowsX86_64TargetInfo(Triple);
+ return new MicrosoftX86_64TargetInfo(Triple);
}
}
case llvm::Triple::NaCl:
@@ -6347,13 +6282,13 @@
case llvm::Triple::spir: {
if (Triple.getOS() != llvm::Triple::UnknownOS ||
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
- return NULL;
+ return nullptr;
return new SPIR32TargetInfo(Triple);
}
case llvm::Triple::spir64: {
if (Triple.getOS() != llvm::Triple::UnknownOS ||
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
- return NULL;
+ return nullptr;
return new SPIR64TargetInfo(Triple);
}
}
@@ -6369,26 +6304,26 @@
std::unique_ptr<TargetInfo> Target(AllocateTarget(Triple));
if (!Target) {
Diags.Report(diag::err_target_unknown_triple) << Triple.str();
- return 0;
+ return nullptr;
}
Target->setTargetOpts(Opts);
// Set the target CPU if specified.
if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) {
Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU;
- return 0;
+ return nullptr;
}
// Set the target ABI if specified.
if (!Opts->ABI.empty() && !Target->setABI(Opts->ABI)) {
Diags.Report(diag::err_target_unknown_abi) << Opts->ABI;
- return 0;
+ return nullptr;
}
// Set the fp math unit.
if (!Opts->FPMath.empty() && !Target->setFPMath(Opts->FPMath)) {
Diags.Report(diag::err_target_unknown_fpmath) << Opts->FPMath;
- return 0;
+ return nullptr;
}
// Compute the default target features, we need the target to handle this
@@ -6414,7 +6349,7 @@
ie = Features.end(); it != ie; ++it)
Opts->Features.push_back((it->second ? "+" : "-") + it->first().str());
if (!Target->handleTargetFeatures(Opts->Features, Diags))
- return 0;
+ return nullptr;
return Target.release();
}
diff --git a/lib/Basic/TokenKinds.cpp b/lib/Basic/TokenKinds.cpp
index 92fc2a2..3b1f8fe 100644
--- a/lib/Basic/TokenKinds.cpp
+++ b/lib/Basic/TokenKinds.cpp
@@ -19,14 +19,14 @@
#define TOK(X) #X,
#define KEYWORD(X,Y) #X,
#include "clang/Basic/TokenKinds.def"
- 0
+ nullptr
};
const char *tok::getTokenName(TokenKind Kind) {
if (Kind < tok::NUM_TOKENS)
return TokNames[Kind];
llvm_unreachable("unknown TokenKind");
- return 0;
+ return nullptr;
}
const char *tok::getPunctuatorSpelling(TokenKind Kind) {
@@ -35,7 +35,7 @@
#include "clang/Basic/TokenKinds.def"
default: break;
}
- return 0;
+ return nullptr;
}
const char *tok::getKeywordSpelling(TokenKind Kind) {
@@ -44,5 +44,5 @@
#include "clang/Basic/TokenKinds.def"
default: break;
}
- return 0;
+ return nullptr;
}
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index 9a88cfd..a469c9a 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/lib/Basic/VirtualFileSystem.cpp
@@ -11,6 +11,7 @@
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -30,13 +31,13 @@
Status::Status(const file_status &Status)
: UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
- Type(Status.type()), Perms(Status.permissions()) {}
+ Type(Status.type()), Perms(Status.permissions()), IsVFSMapped(false) {}
Status::Status(StringRef Name, StringRef ExternalName, UniqueID UID,
sys::TimeValue MTime, uint32_t User, uint32_t Group,
uint64_t Size, file_type Type, perms Perms)
: Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
- Type(Type), Perms(Perms) {}
+ Type(Type), Perms(Perms), IsVFSMapped(false) {}
bool Status::equivalent(const Status &Other) const {
return getUniqueID() == Other.getUniqueID();
@@ -67,12 +68,14 @@
error_code FileSystem::getBufferForFile(const llvm::Twine &Name,
std::unique_ptr<MemoryBuffer> &Result,
int64_t FileSize,
- bool RequiresNullTerminator) {
+ bool RequiresNullTerminator,
+ bool IsVolatile) {
std::unique_ptr<File> F;
if (error_code EC = openFileForRead(Name, F))
return EC;
- error_code EC = F->getBuffer(Name, Result, FileSize, RequiresNullTerminator);
+ error_code EC = F->getBuffer(Name, Result, FileSize, RequiresNullTerminator,
+ IsVolatile);
return EC;
}
@@ -95,7 +98,8 @@
ErrorOr<Status> status() override;
error_code getBuffer(const Twine &Name, std::unique_ptr<MemoryBuffer> &Result,
int64_t FileSize = -1,
- bool RequiresNullTerminator = true) override;
+ bool RequiresNullTerminator = true,
+ bool IsVolatile = false) override;
error_code close() override;
void setName(StringRef Name) override;
};
@@ -117,10 +121,11 @@
error_code RealFile::getBuffer(const Twine &Name,
std::unique_ptr<MemoryBuffer> &Result,
- int64_t FileSize, bool RequiresNullTerminator) {
+ int64_t FileSize, bool RequiresNullTerminator,
+ bool IsVolatile) {
assert(FD != -1 && "cannot get buffer for closed file");
return MemoryBuffer::getOpenFile(FD, Name.str().c_str(), Result, FileSize,
- RequiresNullTerminator);
+ RequiresNullTerminator, IsVolatile);
}
// FIXME: This is terrible, we need this for ::close.
@@ -469,7 +474,7 @@
yaml::MappingNode *M = dyn_cast<yaml::MappingNode>(N);
if (!M) {
error(N, "expected mapping node for file or directory entry");
- return NULL;
+ return nullptr;
}
KeyStatusPair Fields[] = {
@@ -497,32 +502,32 @@
// parsing value.
SmallString<256> Buffer;
if (!parseScalarString(I->getKey(), Key, Buffer))
- return NULL;
+ return nullptr;
if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys))
- return NULL;
+ return nullptr;
StringRef Value;
if (Key == "name") {
if (!parseScalarString(I->getValue(), Value, Buffer))
- return NULL;
+ return nullptr;
Name = Value;
} else if (Key == "type") {
if (!parseScalarString(I->getValue(), Value, Buffer))
- return NULL;
+ return nullptr;
if (Value == "file")
Kind = EK_File;
else if (Value == "directory")
Kind = EK_Directory;
else {
error(I->getValue(), "unknown value for 'type'");
- return NULL;
+ return nullptr;
}
} else if (Key == "contents") {
if (HasContents) {
error(I->getKey(),
"entry already has 'contents' or 'external-contents'");
- return NULL;
+ return nullptr;
}
HasContents = true;
yaml::SequenceNode *Contents =
@@ -530,7 +535,7 @@
if (!Contents) {
// FIXME: this is only for directories, what about files?
error(I->getValue(), "expected array");
- return NULL;
+ return nullptr;
}
for (yaml::SequenceNode::iterator I = Contents->begin(),
@@ -539,22 +544,22 @@
if (Entry *E = parseEntry(&*I))
EntryArrayContents.push_back(E);
else
- return NULL;
+ return nullptr;
}
} else if (Key == "external-contents") {
if (HasContents) {
error(I->getKey(),
"entry already has 'contents' or 'external-contents'");
- return NULL;
+ return nullptr;
}
HasContents = true;
if (!parseScalarString(I->getValue(), Value, Buffer))
- return NULL;
+ return nullptr;
ExternalContentsPath = Value;
} else if (Key == "use-external-name") {
bool Val;
if (!parseScalarBool(I->getValue(), Val))
- return NULL;
+ return nullptr;
UseExternalName = Val ? FileEntry::NK_External : FileEntry::NK_Virtual;
} else {
llvm_unreachable("key missing from Keys");
@@ -562,20 +567,20 @@
}
if (Stream.failed())
- return NULL;
+ return nullptr;
// check for missing keys
if (!HasContents) {
error(N, "missing key 'contents' or 'external-contents'");
- return NULL;
+ return nullptr;
}
if (!checkMissingKeys(N, Keys))
- return NULL;
+ return nullptr;
// check invalid configuration
if (Kind == EK_Directory && UseExternalName != FileEntry::NK_NotSet) {
error(N, "'use-external-name' is not supported for directories");
- return NULL;
+ return nullptr;
}
// Remove trailing slash(es), being careful not to remove the root path
@@ -587,7 +592,7 @@
// Get the last component
StringRef LastComponent = sys::path::filename(Trimmed);
- Entry *Result = 0;
+ Entry *Result = nullptr;
switch (Kind) {
case EK_File:
Result = new FileEntry(LastComponent, std::move(ExternalContentsPath),
@@ -718,14 +723,14 @@
yaml::Node *Root = DI->getRoot();
if (DI == Stream.end() || !Root) {
SM.PrintMessage(SMLoc(), SourceMgr::DK_Error, "expected root node");
- return NULL;
+ return nullptr;
}
VFSFromYAMLParser P(Stream);
std::unique_ptr<VFSFromYAML> FS(new VFSFromYAML(ExternalFS));
if (!P.parse(Root, FS.get()))
- return NULL;
+ return nullptr;
return FS.release();
}
@@ -796,6 +801,8 @@
assert(!S || S->getName() == F->getExternalContentsPath());
if (S && !F->useExternalName(UseExternalNames))
S->setName(PathStr);
+ if (S)
+ S->IsVFSMapped = true;
return S;
} else { // directory
DirectoryEntry *DE = cast<DirectoryEntry>(*Result);
@@ -839,3 +846,138 @@
// dev_t value from the OS.
return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
}
+
+#ifndef NDEBUG
+static bool pathHasTraversal(StringRef Path) {
+ using namespace llvm::sys;
+ for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
+ if (Comp == "." || Comp == "..")
+ return true;
+ return false;
+}
+#endif
+
+void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
+ assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
+ assert(sys::path::is_absolute(RealPath) && "real path not absolute");
+ assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
+ Mappings.emplace_back(VirtualPath, RealPath);
+}
+
+namespace {
+class JSONWriter {
+ llvm::raw_ostream &OS;
+ SmallVector<StringRef, 16> DirStack;
+ inline unsigned getDirIndent() { return 4 * DirStack.size(); }
+ inline unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
+ bool containedIn(StringRef Parent, StringRef Path);
+ StringRef containedPart(StringRef Parent, StringRef Path);
+ void startDirectory(StringRef Path);
+ void endDirectory();
+ void writeEntry(StringRef VPath, StringRef RPath);
+
+public:
+ JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
+ void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> IsCaseSensitive);
+};
+}
+
+bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
+ using namespace llvm::sys;
+ // Compare each path component.
+ auto IParent = path::begin(Parent), EParent = path::end(Parent);
+ for (auto IChild = path::begin(Path), EChild = path::end(Path);
+ IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
+ if (*IParent != *IChild)
+ return false;
+ }
+ // Have we exhausted the parent path?
+ return IParent == EParent;
+}
+
+StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
+ assert(!Parent.empty());
+ assert(containedIn(Parent, Path));
+ return Path.slice(Parent.size() + 1, StringRef::npos);
+}
+
+void JSONWriter::startDirectory(StringRef Path) {
+ StringRef Name =
+ DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
+ DirStack.push_back(Path);
+ unsigned Indent = getDirIndent();
+ OS.indent(Indent) << "{\n";
+ OS.indent(Indent + 2) << "'type': 'directory',\n";
+ OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(Name) << "\",\n";
+ OS.indent(Indent + 2) << "'contents': [\n";
+}
+
+void JSONWriter::endDirectory() {
+ unsigned Indent = getDirIndent();
+ OS.indent(Indent + 2) << "]\n";
+ OS.indent(Indent) << "}";
+
+ DirStack.pop_back();
+}
+
+void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
+ unsigned Indent = getFileIndent();
+ OS.indent(Indent) << "{\n";
+ OS.indent(Indent + 2) << "'type': 'file',\n";
+ OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(VPath) << "\",\n";
+ OS.indent(Indent + 2) << "'external-contents': \""
+ << llvm::yaml::escape(RPath) << "\"\n";
+ OS.indent(Indent) << "}";
+}
+
+void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
+ Optional<bool> IsCaseSensitive) {
+ using namespace llvm::sys;
+
+ OS << "{\n"
+ " 'version': 0,\n";
+ if (IsCaseSensitive.hasValue())
+ OS << " 'case-sensitive': '"
+ << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n";
+ OS << " 'roots': [\n";
+
+ if (Entries.empty())
+ return;
+
+ const YAMLVFSEntry &Entry = Entries.front();
+ startDirectory(path::parent_path(Entry.VPath));
+ writeEntry(path::filename(Entry.VPath), Entry.RPath);
+
+ for (const auto &Entry : Entries.slice(1)) {
+ StringRef Dir = path::parent_path(Entry.VPath);
+ if (Dir == DirStack.back())
+ OS << ",\n";
+ else {
+ while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
+ OS << "\n";
+ endDirectory();
+ }
+ OS << ",\n";
+ startDirectory(Dir);
+ }
+ writeEntry(path::filename(Entry.VPath), Entry.RPath);
+ }
+
+ while (!DirStack.empty()) {
+ OS << "\n";
+ endDirectory();
+ }
+
+ OS << "\n"
+ << " ]\n"
+ << "}\n";
+}
+
+void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
+ std::sort(Mappings.begin(), Mappings.end(),
+ [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
+ return LHS.VPath < RHS.VPath;
+ });
+
+ JSONWriter(OS).write(Mappings, IsCaseSensitive);
+}
diff --git a/lib/Frontend/Warnings.cpp b/lib/Basic/Warnings.cpp
similarity index 97%
rename from lib/Frontend/Warnings.cpp
rename to lib/Basic/Warnings.cpp
index 767096a..b09e69a 100644
--- a/lib/Frontend/Warnings.cpp
+++ b/lib/Basic/Warnings.cpp
@@ -20,12 +20,9 @@
// Given a warning option 'foo', the following are valid:
// -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo
//
-#include "clang/Frontend/Utils.h"
+#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Lex/LexDiagnostic.h"
-#include "clang/Sema/SemaDiagnostic.h"
#include <algorithm>
#include <cstring>
#include <utility>
diff --git a/lib/CodeGen/Android.mk b/lib/CodeGen/Android.mk
index 1c4a0b7..85805e4 100644
--- a/lib/CodeGen/Android.mk
+++ b/lib/CodeGen/Android.mk
@@ -40,9 +40,12 @@
CGObjCMac.cpp \
CGObjCRuntime.cpp \
CGOpenCLRuntime.cpp \
+ CGOpenMPRuntime.cpp \
+ CGLoopInfo.cpp \
CGRTTI.cpp \
CGRecordLayoutBuilder.cpp \
CGStmt.cpp \
+ CGStmtOpenMP.cpp \
CGVTT.cpp \
CGVTables.cpp \
CodeGenABITypes.cpp \
@@ -54,6 +57,7 @@
CodeGenTypes.cpp \
ItaniumCXXABI.cpp \
MicrosoftCXXABI.cpp \
+ MicrosoftRTTI.cpp \
ModuleBuilder.cpp \
TargetInfo.cpp
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 17f5f4d..fc6c594 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -14,6 +14,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
@@ -112,7 +113,8 @@
Module *M)
: Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts),
TheModule(M), CodeGenerationTime("Code Generation Time"),
- CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}
+ CodeGenPasses(nullptr), PerModulePasses(nullptr),
+ PerFunctionPasses(nullptr) {}
~EmitAssemblyHelper() {
delete CodeGenPasses;
@@ -247,6 +249,7 @@
PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP;
PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop;
+ PMBuilder.DisableTailCalls = CodeGenOpts.DisableTailCalls;
PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime;
PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;
PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;
@@ -334,6 +337,8 @@
// Set up the per-module pass manager.
PassManager *MPM = getPerModulePasses();
+ if (CodeGenOpts.VerifyModule)
+ MPM->add(createDebugInfoVerifierPass());
if (!CodeGenOpts.DisableGCov &&
(CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes)) {
@@ -363,32 +368,19 @@
if (!TheTarget) {
if (MustCreateTM)
Diags.Report(diag::err_fe_unable_to_create_target) << Error;
- return 0;
+ return nullptr;
}
- // FIXME: Expose these capabilities via actual APIs!!!! Aside from just
- // being gross, this is also totally broken if we ever care about
- // concurrency.
-
- TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose);
-
- TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections);
- TargetMachine::setDataSections (CodeGenOpts.DataSections);
-
- // FIXME: Parse this earlier.
- llvm::CodeModel::Model CM;
- if (CodeGenOpts.CodeModel == "small") {
- CM = llvm::CodeModel::Small;
- } else if (CodeGenOpts.CodeModel == "kernel") {
- CM = llvm::CodeModel::Kernel;
- } else if (CodeGenOpts.CodeModel == "medium") {
- CM = llvm::CodeModel::Medium;
- } else if (CodeGenOpts.CodeModel == "large") {
- CM = llvm::CodeModel::Large;
- } else {
- assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!");
- CM = llvm::CodeModel::Default;
- }
+ unsigned CodeModel =
+ llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel)
+ .Case("small", llvm::CodeModel::Small)
+ .Case("kernel", llvm::CodeModel::Kernel)
+ .Case("medium", llvm::CodeModel::Medium)
+ .Case("large", llvm::CodeModel::Large)
+ .Case("default", llvm::CodeModel::Default)
+ .Default(~0u);
+ assert(CodeModel != ~0u && "invalid code model!");
+ llvm::CodeModel::Model CM = static_cast<llvm::CodeModel::Model>(CodeModel);
SmallVector<const char *, 16> BackendArgs;
BackendArgs.push_back("clang"); // Fake program name.
@@ -406,7 +398,7 @@
BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str());
if (CodeGenOpts.NoGlobalMerge)
BackendArgs.push_back("-global-merge=false");
- BackendArgs.push_back(0);
+ BackendArgs.push_back(nullptr);
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
BackendArgs.data());
@@ -491,23 +483,19 @@
Options.DisableTailCalls = CodeGenOpts.DisableTailCalls;
Options.TrapFuncName = CodeGenOpts.TrapFuncName;
Options.PositionIndependentExecutable = LangOpts.PIELevel != 0;
- Options.EnableSegmentedStacks = CodeGenOpts.EnableSegmentedStacks;
+ Options.FunctionSections = CodeGenOpts.FunctionSections;
+ Options.DataSections = CodeGenOpts.DataSections;
+
+ Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;
+ Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;
+ Options.MCOptions.MCUseDwarfDirectory = !CodeGenOpts.NoDwarfDirectoryAsm;
+ Options.MCOptions.MCNoExecStack = CodeGenOpts.NoExecStack;
+ Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose;
TargetMachine *TM = TheTarget->createTargetMachine(Triple, TargetOpts.CPU,
FeaturesStr, Options,
RM, CM, OptLevel);
- if (CodeGenOpts.RelaxAll)
- TM->setMCRelaxAll(true);
- if (CodeGenOpts.SaveTempLabels)
- TM->setMCSaveTempLabels(true);
- if (CodeGenOpts.NoDwarf2CFIAsm)
- TM->setMCUseCFI(false);
- if (!CodeGenOpts.NoDwarfDirectoryAsm)
- TM->setMCUseDwarfDirectory(true);
- if (CodeGenOpts.NoExecStack)
- TM->setMCNoExecStack(true);
-
return TM;
}
@@ -554,7 +542,7 @@
}
void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
- TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0);
+ TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
llvm::formatted_raw_ostream FormattedOS;
bool UsesCodeGen = (Action != Backend_EmitNothing &&
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index 7c7c80c..18eb065 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -255,7 +255,8 @@
}
// Create all the relevant BB's
- llvm::BasicBlock *MonotonicBB = 0, *AcquireBB = 0, *SeqCstBB = 0;
+ llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr,
+ *SeqCstBB = nullptr;
MonotonicBB = CGF.createBasicBlock("monotonic_fail", CGF.CurFn);
if (SuccessOrder != llvm::Monotonic && SuccessOrder != llvm::Release)
AcquireBB = CGF.createBasicBlock("acquire_fail", CGF.CurFn);
@@ -452,17 +453,17 @@
bool UseLibcall = (Size != Align ||
getContext().toBits(sizeChars) > MaxInlineWidthInBits);
- llvm::Value *Ptr, *Order, *OrderFail = 0, *Val1 = 0, *Val2 = 0;
- Ptr = EmitScalarExpr(E->getPtr());
+ llvm::Value *OrderFail = nullptr, *Val1 = nullptr, *Val2 = nullptr;
+ llvm::Value *Ptr = EmitScalarExpr(E->getPtr());
if (E->getOp() == AtomicExpr::AO__c11_atomic_init) {
assert(!Dest && "Init does not return a value");
LValue lvalue = LValue::MakeAddr(Ptr, AtomicTy, alignChars, getContext());
EmitAtomicInit(E->getVal1(), lvalue);
- return RValue::get(0);
+ return RValue::get(nullptr);
}
- Order = EmitScalarExpr(E->getOrder());
+ llvm::Value *Order = EmitScalarExpr(E->getOrder());
switch (E->getOp()) {
case AtomicExpr::AO__c11_atomic_init:
@@ -696,7 +697,7 @@
if (!RetTy->isVoidType())
return Res;
if (E->getType()->isVoidType())
- return RValue::get(0);
+ return RValue::get(nullptr);
return convertTempToRValue(Dest, E->getType(), E->getExprLoc());
}
@@ -751,15 +752,16 @@
break;
}
if (E->getType()->isVoidType())
- return RValue::get(0);
+ return RValue::get(nullptr);
return convertTempToRValue(OrigDest, E->getType(), E->getExprLoc());
}
// Long case, when Order isn't obviously constant.
// Create all the relevant BB's
- llvm::BasicBlock *MonotonicBB = 0, *AcquireBB = 0, *ReleaseBB = 0,
- *AcqRelBB = 0, *SeqCstBB = 0;
+ llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr,
+ *ReleaseBB = nullptr, *AcqRelBB = nullptr,
+ *SeqCstBB = nullptr;
MonotonicBB = createBasicBlock("monotonic", CurFn);
if (!IsStore)
AcquireBB = createBasicBlock("acquire", CurFn);
@@ -818,7 +820,7 @@
// Cleanup and return
Builder.SetInsertPoint(ContBB);
if (E->getType()->isVoidType())
- return RValue::get(0);
+ return RValue::get(nullptr);
return convertTempToRValue(OrigDest, E->getType(), E->getExprLoc());
}
@@ -896,7 +898,7 @@
// If we're ignoring an aggregate return, don't do anything.
if (atomics.getEvaluationKind() == TEK_Aggregate && resultSlot.isIgnored())
- return RValue::getAggregate(0, false);
+ return RValue::getAggregate(nullptr, false);
// The easiest way to do this this is to go through memory, but we
// try not to in some easy cases.
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 15b08d4..21896da 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -30,9 +30,9 @@
CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
: Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false),
- StructureType(0), Block(block),
- DominatingIP(0) {
-
+ StructureType(nullptr), Block(block),
+ DominatingIP(nullptr) {
+
// Skip asm prefix, if any. 'name' is usually taken directly from
// the mangled name of the enclosing function.
if (!name.empty() && name[0] == '\01')
@@ -246,7 +246,7 @@
// Only records can be unsafe.
if (!recordType) return true;
- const CXXRecordDecl *record = cast<CXXRecordDecl>(recordType->getDecl());
+ const auto *record = cast<CXXRecordDecl>(recordType->getDecl());
// Maintain semantics for classes with non-trivial dtors or copy ctors.
if (!record->hasTrivialDestructor()) return false;
@@ -269,7 +269,7 @@
QualType type = var->getType();
// We can only do this if the variable is const.
- if (!type.isConstQualified()) return 0;
+ if (!type.isConstQualified()) return nullptr;
// Furthermore, in C++ we have to worry about mutable fields:
// C++ [dcl.type.cv]p4:
@@ -277,13 +277,13 @@
// modified, any attempt to modify a const object during its
// lifetime results in undefined behavior.
if (CGM.getLangOpts().CPlusPlus && !isSafeForCXXConstantCapture(type))
- return 0;
+ return nullptr;
// If the variable doesn't have any initializer (shouldn't this be
// invalid?), it's not clear what we should do. Maybe capture as
// zero?
const Expr *init = var->getInit();
- if (!init) return 0;
+ if (!init) return nullptr;
return CGM.EmitConstantInit(*var, CGF);
}
@@ -366,7 +366,7 @@
layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first,
Qualifiers::OCL_None,
- 0, llvmType));
+ nullptr, llvmType));
}
// Next, all the block captures.
@@ -661,7 +661,7 @@
CGBlockInfo *cur = head;
head = cur->NextBlockInfo;
delete cur;
- } while (head != 0);
+ } while (head != nullptr);
}
/// Emit a block literal expression in the current function.
@@ -769,7 +769,7 @@
} else if (blockDecl->isConversionFromLambda()) {
// The lambda capture in a lambda's conversion-to-block-pointer is
// special; we'll simply emit it directly.
- src = 0;
+ src = nullptr;
} else {
// Just look it up in the locals map, which will give us back a
// [[type]]*. If that doesn't work, do the more elaborate DRE
@@ -841,8 +841,9 @@
} else {
// Fake up a new variable so that EmitScalarInit doesn't think
// we're referring to the variable in its own initializer.
- ImplicitParamDecl blockFieldPseudoVar(/*DC*/ 0, SourceLocation(),
- /*name*/ 0, type);
+ ImplicitParamDecl blockFieldPseudoVar(getContext(), /*DC*/ nullptr,
+ SourceLocation(), /*name*/ nullptr,
+ type);
// We use one of these or the other depending on whether the
// reference is nested.
@@ -1019,7 +1020,7 @@
blockInfo.BlockExpression = blockExpr;
// Compute information about the layout, etc., of this block.
- computeBlockInfo(*this, 0, blockInfo);
+ computeBlockInfo(*this, nullptr, blockInfo);
// Using that metadata, generate the actual block function.
llvm::Constant *blockFn;
@@ -1093,7 +1094,7 @@
// to be local to this function as well, in case they're directly
// referenced in a block.
for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) {
- const VarDecl *var = dyn_cast<VarDecl>(i->first);
+ const auto *var = dyn_cast<VarDecl>(i->first);
if (var && !var->hasLocalStorage())
LocalDeclMap[var] = i->second;
}
@@ -1108,7 +1109,7 @@
QualType selfTy = getContext().VoidPtrTy;
IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
- ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl),
+ ImplicitParamDecl selfDecl(getContext(), const_cast<BlockDecl*>(blockDecl),
SourceLocation(), II, selfTy);
args.push_back(&selfDecl);
@@ -1135,6 +1136,7 @@
// Begin generating the function.
StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args,
+ blockDecl->getLocation(),
blockInfo.getBlockExpr()->getBody()->getLocStart());
// Okay. Undo some of what StartFunction did.
@@ -1236,7 +1238,7 @@
}
// And resume where we left off.
- if (resume == 0)
+ if (resume == nullptr)
Builder.ClearInsertionPoint();
else
Builder.SetInsertPoint(resume);
@@ -1278,9 +1280,11 @@
ASTContext &C = getContext();
FunctionArgList args;
- ImplicitParamDecl dstDecl(0, SourceLocation(), 0, C.VoidPtrTy);
+ ImplicitParamDecl dstDecl(getContext(), nullptr, SourceLocation(), nullptr,
+ C.VoidPtrTy);
args.push_back(&dstDecl);
- ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy);
+ ImplicitParamDecl srcDecl(getContext(), nullptr, SourceLocation(), nullptr,
+ C.VoidPtrTy);
args.push_back(&srcDecl);
const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
@@ -1300,13 +1304,13 @@
FunctionDecl *FD = FunctionDecl::Create(C,
C.getTranslationUnitDecl(),
SourceLocation(),
- SourceLocation(), II, C.VoidTy, 0,
- SC_Static,
+ SourceLocation(), II, C.VoidTy,
+ nullptr, SC_Static,
false,
false);
// Create a scope with an artificial location for the body of this function.
ArtificialLocation AL(*this, Builder);
- StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
+ StartFunction(FD, C.VoidTy, Fn, FI, args);
AL.Emit();
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
@@ -1395,7 +1399,7 @@
// storeStrong doesn't over-release) and then call storeStrong.
// This is a workaround to not having an initStrong call.
if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
- llvm::PointerType *ty = cast<llvm::PointerType>(srcValue->getType());
+ auto *ty = cast<llvm::PointerType>(srcValue->getType());
llvm::Value *null = llvm::ConstantPointerNull::get(ty);
Builder.CreateStore(null, dstField);
EmitARCStoreStrongCall(dstField, srcValue, true);
@@ -1452,7 +1456,8 @@
ASTContext &C = getContext();
FunctionArgList args;
- ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy);
+ ImplicitParamDecl srcDecl(getContext(), nullptr, SourceLocation(), nullptr,
+ C.VoidPtrTy);
args.push_back(&srcDecl);
const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
@@ -1471,12 +1476,12 @@
FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(),
SourceLocation(),
- SourceLocation(), II, C.VoidTy, 0,
- SC_Static,
+ SourceLocation(), II, C.VoidTy,
+ nullptr, SC_Static,
false, false);
// Create a scope with an artificial location for the body of this function.
ArtificialLocation AL(*this, Builder);
- StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
+ StartFunction(FD, C.VoidTy, Fn, FI, args);
AL.Emit();
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
@@ -1497,7 +1502,7 @@
if (capture.isConstant()) continue;
BlockFieldFlags flags;
- const CXXDestructorDecl *dtor = 0;
+ const CXXDestructorDecl *dtor = nullptr;
bool useARCWeakDestroy = false;
bool useARCStrongDestroy = false;
@@ -1708,7 +1713,7 @@
const Expr *copyExpr)
: ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {}
- bool needsCopy() const override { return CopyExpr != 0; }
+ bool needsCopy() const override { return CopyExpr != nullptr; }
void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
llvm::Value *srcField) override {
if (!CopyExpr) return;
@@ -1737,10 +1742,12 @@
QualType R = Context.VoidTy;
FunctionArgList args;
- ImplicitParamDecl dst(0, SourceLocation(), 0, Context.VoidPtrTy);
+ ImplicitParamDecl dst(CGF.getContext(), nullptr, SourceLocation(), nullptr,
+ Context.VoidPtrTy);
args.push_back(&dst);
- ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy);
+ ImplicitParamDecl src(CGF.getContext(), nullptr, SourceLocation(), nullptr,
+ Context.VoidPtrTy);
args.push_back(&src);
const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration(
@@ -1761,11 +1768,11 @@
FunctionDecl *FD = FunctionDecl::Create(Context,
Context.getTranslationUnitDecl(),
SourceLocation(),
- SourceLocation(), II, R, 0,
+ SourceLocation(), II, R, nullptr,
SC_Static,
false, false);
- CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation());
+ CGF.StartFunction(FD, R, Fn, FI, args);
if (byrefInfo.needsCopy()) {
llvm::Type *byrefPtrType = byrefType.getPointerTo(0);
@@ -1809,7 +1816,8 @@
QualType R = Context.VoidTy;
FunctionArgList args;
- ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy);
+ ImplicitParamDecl src(CGF.getContext(), nullptr, SourceLocation(), nullptr,
+ Context.VoidPtrTy);
args.push_back(&src);
const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration(
@@ -1831,10 +1839,10 @@
FunctionDecl *FD = FunctionDecl::Create(Context,
Context.getTranslationUnitDecl(),
SourceLocation(),
- SourceLocation(), II, R, 0,
+ SourceLocation(), II, R, nullptr,
SC_Static,
false, false);
- CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation());
+ CGF.StartFunction(FD, R, Fn, FI, args);
if (byrefInfo.needsDispose()) {
llvm::Value *V = CGF.GetAddrOfLocalVar(&src);
@@ -1901,7 +1909,7 @@
if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var);
- if (!copyExpr && record->hasTrivialDestructor()) return 0;
+ if (!copyExpr && record->hasTrivialDestructor()) return nullptr;
CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr);
return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
@@ -1909,7 +1917,7 @@
// Otherwise, if we don't have a retainable type, there's nothing to do.
// that the runtime does extra copies.
- if (!type->isObjCRetainableType()) return 0;
+ if (!type->isObjCRetainableType()) return nullptr;
Qualifiers qs = type.getQualifiers();
@@ -1923,7 +1931,7 @@
// These are just bits as far as the runtime is concerned.
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
- return 0;
+ return nullptr;
// Tell the runtime that this is ARC __weak, called by the
// byref routines.
@@ -1957,7 +1965,7 @@
type->isObjCObjectPointerType()) {
flags |= BLOCK_FIELD_IS_OBJECT;
} else {
- return 0;
+ return nullptr;
}
if (type.isObjCGCWeak())
@@ -2230,9 +2238,8 @@
llvm::Constant *C) {
if (!CGM.getLangOpts().BlocksRuntimeOptional) return;
- llvm::GlobalValue *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());
- if (GV->isDeclaration() &&
- GV->getLinkage() == llvm::GlobalValue::ExternalLinkage)
+ auto *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());
+ if (GV->isDeclaration() && GV->hasExternalLinkage())
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
}
@@ -2265,7 +2272,8 @@
return NSConcreteGlobalBlock;
NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock",
- Int8PtrTy->getPointerTo(), 0);
+ Int8PtrTy->getPointerTo(),
+ nullptr);
configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock);
return NSConcreteGlobalBlock;
}
@@ -2275,7 +2283,8 @@
return NSConcreteStackBlock;
NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock",
- Int8PtrTy->getPointerTo(), 0);
+ Int8PtrTy->getPointerTo(),
+ nullptr);
configureBlocksRuntimeObject(*this, NSConcreteStackBlock);
return NSConcreteStackBlock;
}
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 020638a..0031e32 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -28,15 +28,15 @@
#include "llvm/IR/Module.h"
namespace llvm {
- class Module;
- class Constant;
- class Function;
- class GlobalValue;
- class DataLayout;
- class FunctionType;
- class PointerType;
- class Value;
- class LLVMContext;
+class Module;
+class Constant;
+class Function;
+class GlobalValue;
+class DataLayout;
+class FunctionType;
+class PointerType;
+class Value;
+class LLVMContext;
}
namespace clang {
diff --git a/lib/CodeGen/CGBuilder.h b/lib/CodeGen/CGBuilder.h
index fd21e7e..f113b97 100644
--- a/lib/CodeGen/CGBuilder.h
+++ b/lib/CodeGen/CGBuilder.h
@@ -15,12 +15,39 @@
namespace clang {
namespace CodeGen {
+class CodeGenFunction;
+
+/// \brief This is an IRBuilder insertion helper that forwards to
+/// CodeGenFunction::InsertHelper, which adds nesessary metadata to
+/// instructions.
+template <bool PreserveNames>
+class CGBuilderInserter
+ : protected llvm::IRBuilderDefaultInserter<PreserveNames> {
+public:
+ CGBuilderInserter() : CGF(nullptr) {}
+ explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
+
+protected:
+ /// \brief This forwards to CodeGenFunction::InsertHelper.
+ void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
+ llvm::BasicBlock *BB,
+ llvm::BasicBlock::iterator InsertPt) const;
+private:
+ void operator=(const CGBuilderInserter &) LLVM_DELETED_FUNCTION;
+
+ CodeGenFunction *CGF;
+};
+
// Don't preserve names on values in an optimized build.
#ifdef NDEBUG
-typedef llvm::IRBuilder<false> CGBuilderTy;
+#define PreserveNames false
#else
-typedef llvm::IRBuilder<> CGBuilderTy;
+#define PreserveNames true
#endif
+typedef CGBuilderInserter<PreserveNames> CGBuilderInserterTy;
+typedef llvm::IRBuilder<PreserveNames, llvm::ConstantFolder,
+ CGBuilderInserterTy> CGBuilderTy;
+#undef PreserveNames
} // end namespace CodeGen
} // end namespace clang
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 5a86bdd..c6ac3cc 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -212,7 +212,7 @@
default: break; // Handle intrinsics and libm functions below.
case Builtin::BI__builtin___CFStringMakeConstantString:
case Builtin::BI__builtin___NSStringMakeConstantString:
- return RValue::get(CGM.EmitConstantExpr(E, E->getType(), 0));
+ return RValue::get(CGM.EmitConstantExpr(E, E->getType(), nullptr));
case Builtin::BI__builtin_stdarg_start:
case Builtin::BI__builtin_va_start:
case Builtin::BI__va_start:
@@ -457,7 +457,7 @@
// We do need to preserve an insertion point.
EmitBlock(createBasicBlock("unreachable.cont"));
- return RValue::get(0);
+ return RValue::get(nullptr);
}
case Builtin::BI__builtin_powi:
@@ -790,7 +790,7 @@
// We do need to preserve an insertion point.
EmitBlock(createBasicBlock("builtin_eh_return.cont"));
- return RValue::get(0);
+ return RValue::get(nullptr);
}
case Builtin::BI__builtin_unwind_init: {
Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init);
@@ -856,7 +856,7 @@
// We do need to preserve an insertion point.
EmitBlock(createBasicBlock("longjmp.cont"));
- return RValue::get(0);
+ return RValue::get(nullptr);
}
case Builtin::BI__sync_fetch_and_add:
case Builtin::BI__sync_fetch_and_sub:
@@ -1037,7 +1037,7 @@
Builder.CreateStore(llvm::Constant::getNullValue(ITy), Ptr);
Store->setAlignment(StoreSize.getQuantity());
Store->setAtomic(llvm::Release);
- return RValue::get(0);
+ return RValue::get(nullptr);
}
case Builtin::BI__sync_synchronize: {
@@ -1049,7 +1049,7 @@
// to use it with non-atomic loads and stores to get acquire/release
// semantics.
Builder.CreateFence(llvm::SequentiallyConsistent);
- return RValue::get(0);
+ return RValue::get(nullptr);
}
case Builtin::BI__c11_atomic_is_lock_free:
@@ -1090,7 +1090,7 @@
Value *Order = EmitScalarExpr(E->getArg(1));
if (isa<llvm::ConstantInt>(Order)) {
int ord = cast<llvm::ConstantInt>(Order)->getZExtValue();
- AtomicRMWInst *Result = 0;
+ AtomicRMWInst *Result = nullptr;
switch (ord) {
case 0: // memory_order_relaxed
default: // invalid order
@@ -1190,7 +1190,7 @@
Store->setOrdering(llvm::SequentiallyConsistent);
break;
}
- return RValue::get(0);
+ return RValue::get(nullptr);
}
llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn);
@@ -1220,7 +1220,7 @@
SI->addCase(Builder.getInt32(5), BBs[2]);
Builder.SetInsertPoint(ContBB);
- return RValue::get(0);
+ return RValue::get(nullptr);
}
case Builtin::BI__atomic_thread_fence:
@@ -1254,7 +1254,7 @@
Builder.CreateFence(llvm::SequentiallyConsistent, Scope);
break;
}
- return RValue::get(0);
+ return RValue::get(nullptr);
}
llvm::BasicBlock *AcquireBB, *ReleaseBB, *AcqRelBB, *SeqCstBB;
@@ -1289,7 +1289,7 @@
SI->addCase(Builder.getInt32(5), SeqCstBB);
Builder.SetInsertPoint(ContBB);
- return RValue::get(0);
+ return RValue::get(nullptr);
}
// Library functions with special handling.
@@ -1509,7 +1509,7 @@
case Builtin::BI__builtin_addressof:
return RValue::get(EmitLValue(E->getArg(0)).getAddress());
case Builtin::BI__noop:
- return RValue::get(0);
+ return RValue::get(nullptr);
case Builtin::BI_InterlockedCompareExchange: {
AtomicCmpXchgInst *CXI = Builder.CreateAtomicCmpXchg(
EmitScalarExpr(E->getArg(0)),
@@ -1637,16 +1637,16 @@
Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
switch (getTarget().getTriple().getArch()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- return EmitAArch64BuiltinExpr(BuiltinID, E);
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
return EmitARMBuiltinExpr(BuiltinID, E);
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
case llvm::Triple::arm64:
- return EmitARM64BuiltinExpr(BuiltinID, E);
+ case llvm::Triple::arm64_be:
+ return EmitAArch64BuiltinExpr(BuiltinID, E);
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return EmitX86BuiltinExpr(BuiltinID, E);
@@ -1655,7 +1655,7 @@
case llvm::Triple::ppc64le:
return EmitPPCBuiltinExpr(BuiltinID, E);
default:
- return 0;
+ return nullptr;
}
}
@@ -1882,354 +1882,6 @@
Intrinsic::LLVMIntrinsic, Intrinsic::AltLLVMIntrinsic, \
#NameBase, TypeModifier }
-static const NeonIntrinsicInfo AArch64SISDIntrinsicInfo[] = {
- NEONMAP1(vabdd_f64, aarch64_neon_vabd, AddRetType),
- NEONMAP1(vabds_f32, aarch64_neon_vabd, AddRetType),
- NEONMAP1(vabsd_s64, aarch64_neon_vabs, 0),
- NEONMAP1(vaddd_s64, aarch64_neon_vaddds, 0),
- NEONMAP1(vaddd_u64, aarch64_neon_vadddu, 0),
- NEONMAP1(vaddlv_s16, aarch64_neon_saddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlv_s32, aarch64_neon_saddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlv_s8, aarch64_neon_saddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlv_u16, aarch64_neon_uaddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlv_u32, aarch64_neon_uaddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlv_u8, aarch64_neon_uaddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlvq_s16, aarch64_neon_saddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlvq_s32, aarch64_neon_saddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlvq_s8, aarch64_neon_saddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlvq_u16, aarch64_neon_uaddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlvq_u32, aarch64_neon_uaddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddlvq_u8, aarch64_neon_uaddlv, VectorRet | Add1ArgType),
- NEONMAP1(vaddv_f32, aarch64_neon_vpfadd, AddRetType | Add1ArgType),
- NEONMAP1(vaddv_s16, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddv_s32, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddv_s8, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddv_u16, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddv_u32, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddv_u8, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddvq_f32, aarch64_neon_vpfadd, AddRetType | Add1ArgType),
- NEONMAP1(vaddvq_f64, aarch64_neon_vpfadd, AddRetType | Add1ArgType),
- NEONMAP1(vaddvq_s16, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddvq_s32, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddvq_s64, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddvq_s8, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddvq_u16, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddvq_u32, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddvq_u64, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vaddvq_u8, aarch64_neon_vaddv, VectorRet | Add1ArgType),
- NEONMAP1(vcaged_f64, aarch64_neon_fcage, VectorRet | Add2ArgTypes),
- NEONMAP1(vcages_f32, aarch64_neon_fcage, VectorRet | Add2ArgTypes),
- NEONMAP1(vcagtd_f64, aarch64_neon_fcagt, VectorRet | Add2ArgTypes),
- NEONMAP1(vcagts_f32, aarch64_neon_fcagt, VectorRet | Add2ArgTypes),
- NEONMAP1(vcaled_f64, aarch64_neon_fcage, VectorRet | Add2ArgTypes),
- NEONMAP1(vcales_f32, aarch64_neon_fcage, VectorRet | Add2ArgTypes),
- NEONMAP1(vcaltd_f64, aarch64_neon_fcagt, VectorRet | Add2ArgTypes),
- NEONMAP1(vcalts_f32, aarch64_neon_fcagt, VectorRet | Add2ArgTypes),
- NEONMAP1(vceqd_f64, aarch64_neon_fceq, VectorRet | Add2ArgTypes),
- NEONMAP1(vceqd_s64, aarch64_neon_vceq, VectorRetGetArgs01),
- NEONMAP1(vceqd_u64, aarch64_neon_vceq, VectorRetGetArgs01),
- NEONMAP1(vceqs_f32, aarch64_neon_fceq, VectorRet | Add2ArgTypes),
- NEONMAP1(vceqzd_f64, aarch64_neon_fceq, FpCmpzModifiers),
- NEONMAP1(vceqzd_s64, aarch64_neon_vceq, VectorRetGetArgs01),
- NEONMAP1(vceqzd_u64, aarch64_neon_vceq, VectorRetGetArgs01),
- NEONMAP1(vceqzs_f32, aarch64_neon_fceq, FpCmpzModifiers),
- NEONMAP1(vcged_f64, aarch64_neon_fcge, VectorRet | Add2ArgTypes),
- NEONMAP1(vcged_s64, aarch64_neon_vcge, VectorRetGetArgs01),
- NEONMAP1(vcged_u64, aarch64_neon_vchs, VectorRetGetArgs01),
- NEONMAP1(vcges_f32, aarch64_neon_fcge, VectorRet | Add2ArgTypes),
- NEONMAP1(vcgezd_f64, aarch64_neon_fcge, FpCmpzModifiers),
- NEONMAP1(vcgezd_s64, aarch64_neon_vcge, VectorRetGetArgs01),
- NEONMAP1(vcgezs_f32, aarch64_neon_fcge, FpCmpzModifiers),
- NEONMAP1(vcgtd_f64, aarch64_neon_fcgt, VectorRet | Add2ArgTypes),
- NEONMAP1(vcgtd_s64, aarch64_neon_vcgt, VectorRetGetArgs01),
- NEONMAP1(vcgtd_u64, aarch64_neon_vchi, VectorRetGetArgs01),
- NEONMAP1(vcgts_f32, aarch64_neon_fcgt, VectorRet | Add2ArgTypes),
- NEONMAP1(vcgtzd_f64, aarch64_neon_fcgt, FpCmpzModifiers),
- NEONMAP1(vcgtzd_s64, aarch64_neon_vcgt, VectorRetGetArgs01),
- NEONMAP1(vcgtzs_f32, aarch64_neon_fcgt, FpCmpzModifiers),
- NEONMAP1(vcled_f64, aarch64_neon_fcge, VectorRet | Add2ArgTypes),
- NEONMAP1(vcled_s64, aarch64_neon_vcge, VectorRetGetArgs01),
- NEONMAP1(vcled_u64, aarch64_neon_vchs, VectorRetGetArgs01),
- NEONMAP1(vcles_f32, aarch64_neon_fcge, VectorRet | Add2ArgTypes),
- NEONMAP1(vclezd_f64, aarch64_neon_fclez, FpCmpzModifiers),
- NEONMAP1(vclezd_s64, aarch64_neon_vclez, VectorRetGetArgs01),
- NEONMAP1(vclezs_f32, aarch64_neon_fclez, FpCmpzModifiers),
- NEONMAP1(vcltd_f64, aarch64_neon_fcgt, VectorRet | Add2ArgTypes),
- NEONMAP1(vcltd_s64, aarch64_neon_vcgt, VectorRetGetArgs01),
- NEONMAP1(vcltd_u64, aarch64_neon_vchi, VectorRetGetArgs01),
- NEONMAP1(vclts_f32, aarch64_neon_fcgt, VectorRet | Add2ArgTypes),
- NEONMAP1(vcltzd_f64, aarch64_neon_fcltz, FpCmpzModifiers),
- NEONMAP1(vcltzd_s64, aarch64_neon_vcltz, VectorRetGetArgs01),
- NEONMAP1(vcltzs_f32, aarch64_neon_fcltz, FpCmpzModifiers),
- NEONMAP1(vcvtad_s64_f64, aarch64_neon_fcvtas, VectorRet | Add1ArgType),
- NEONMAP1(vcvtad_u64_f64, aarch64_neon_fcvtau, VectorRet | Add1ArgType),
- NEONMAP1(vcvtas_s32_f32, aarch64_neon_fcvtas, VectorRet | Add1ArgType),
- NEONMAP1(vcvtas_u32_f32, aarch64_neon_fcvtau, VectorRet | Add1ArgType),
- NEONMAP1(vcvtd_f64_s64, aarch64_neon_vcvtint2fps, AddRetType | Vectorize1ArgType),
- NEONMAP1(vcvtd_f64_u64, aarch64_neon_vcvtint2fpu, AddRetType | Vectorize1ArgType),
- NEONMAP1(vcvtd_n_f64_s64, aarch64_neon_vcvtfxs2fp_n, AddRetType | Vectorize1ArgType),
- NEONMAP1(vcvtd_n_f64_u64, aarch64_neon_vcvtfxu2fp_n, AddRetType | Vectorize1ArgType),
- NEONMAP1(vcvtd_n_s64_f64, aarch64_neon_vcvtfp2fxs_n, VectorRet | Add1ArgType),
- NEONMAP1(vcvtd_n_u64_f64, aarch64_neon_vcvtfp2fxu_n, VectorRet | Add1ArgType),
- NEONMAP1(vcvtd_s64_f64, aarch64_neon_fcvtzs, VectorRet | Add1ArgType),
- NEONMAP1(vcvtd_u64_f64, aarch64_neon_fcvtzu, VectorRet | Add1ArgType),
- NEONMAP1(vcvtmd_s64_f64, aarch64_neon_fcvtms, VectorRet | Add1ArgType),
- NEONMAP1(vcvtmd_u64_f64, aarch64_neon_fcvtmu, VectorRet | Add1ArgType),
- NEONMAP1(vcvtms_s32_f32, aarch64_neon_fcvtms, VectorRet | Add1ArgType),
- NEONMAP1(vcvtms_u32_f32, aarch64_neon_fcvtmu, VectorRet | Add1ArgType),
- NEONMAP1(vcvtnd_s64_f64, aarch64_neon_fcvtns, VectorRet | Add1ArgType),
- NEONMAP1(vcvtnd_u64_f64, aarch64_neon_fcvtnu, VectorRet | Add1ArgType),
- NEONMAP1(vcvtns_s32_f32, aarch64_neon_fcvtns, VectorRet | Add1ArgType),
- NEONMAP1(vcvtns_u32_f32, aarch64_neon_fcvtnu, VectorRet | Add1ArgType),
- NEONMAP1(vcvtpd_s64_f64, aarch64_neon_fcvtps, VectorRet | Add1ArgType),
- NEONMAP1(vcvtpd_u64_f64, aarch64_neon_fcvtpu, VectorRet | Add1ArgType),
- NEONMAP1(vcvtps_s32_f32, aarch64_neon_fcvtps, VectorRet | Add1ArgType),
- NEONMAP1(vcvtps_u32_f32, aarch64_neon_fcvtpu, VectorRet | Add1ArgType),
- NEONMAP1(vcvts_f32_s32, aarch64_neon_vcvtint2fps, AddRetType | Vectorize1ArgType),
- NEONMAP1(vcvts_f32_u32, aarch64_neon_vcvtint2fpu, AddRetType | Vectorize1ArgType),
- NEONMAP1(vcvts_n_f32_s32, aarch64_neon_vcvtfxs2fp_n, AddRetType | Vectorize1ArgType),
- NEONMAP1(vcvts_n_f32_u32, aarch64_neon_vcvtfxu2fp_n, AddRetType | Vectorize1ArgType),
- NEONMAP1(vcvts_n_s32_f32, aarch64_neon_vcvtfp2fxs_n, VectorRet | Add1ArgType),
- NEONMAP1(vcvts_n_u32_f32, aarch64_neon_vcvtfp2fxu_n, VectorRet | Add1ArgType),
- NEONMAP1(vcvts_s32_f32, aarch64_neon_fcvtzs, VectorRet | Add1ArgType),
- NEONMAP1(vcvts_u32_f32, aarch64_neon_fcvtzu, VectorRet | Add1ArgType),
- NEONMAP1(vcvtxd_f32_f64, aarch64_neon_fcvtxn, 0),
- NEONMAP0(vdupb_lane_i8),
- NEONMAP0(vdupb_laneq_i8),
- NEONMAP0(vdupd_lane_f64),
- NEONMAP0(vdupd_lane_i64),
- NEONMAP0(vdupd_laneq_f64),
- NEONMAP0(vdupd_laneq_i64),
- NEONMAP0(vduph_lane_i16),
- NEONMAP0(vduph_laneq_i16),
- NEONMAP0(vdups_lane_f32),
- NEONMAP0(vdups_lane_i32),
- NEONMAP0(vdups_laneq_f32),
- NEONMAP0(vdups_laneq_i32),
- NEONMAP0(vfmad_lane_f64),
- NEONMAP0(vfmad_laneq_f64),
- NEONMAP0(vfmas_lane_f32),
- NEONMAP0(vfmas_laneq_f32),
- NEONMAP0(vget_lane_f32),
- NEONMAP0(vget_lane_f64),
- NEONMAP0(vget_lane_i16),
- NEONMAP0(vget_lane_i32),
- NEONMAP0(vget_lane_i64),
- NEONMAP0(vget_lane_i8),
- NEONMAP0(vgetq_lane_f32),
- NEONMAP0(vgetq_lane_f64),
- NEONMAP0(vgetq_lane_i16),
- NEONMAP0(vgetq_lane_i32),
- NEONMAP0(vgetq_lane_i64),
- NEONMAP0(vgetq_lane_i8),
- NEONMAP1(vmaxnmv_f32, aarch64_neon_vpfmaxnm, AddRetType | Add1ArgType),
- NEONMAP1(vmaxnmvq_f32, aarch64_neon_vmaxnmv, 0),
- NEONMAP1(vmaxnmvq_f64, aarch64_neon_vpfmaxnm, AddRetType | Add1ArgType),
- NEONMAP1(vmaxv_f32, aarch64_neon_vpmax, AddRetType | Add1ArgType),
- NEONMAP1(vmaxv_s16, aarch64_neon_smaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxv_s32, aarch64_neon_smaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxv_s8, aarch64_neon_smaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxv_u16, aarch64_neon_umaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxv_u32, aarch64_neon_umaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxv_u8, aarch64_neon_umaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxvq_f32, aarch64_neon_vmaxv, 0),
- NEONMAP1(vmaxvq_f64, aarch64_neon_vpmax, AddRetType | Add1ArgType),
- NEONMAP1(vmaxvq_s16, aarch64_neon_smaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxvq_s32, aarch64_neon_smaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxvq_s8, aarch64_neon_smaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxvq_u16, aarch64_neon_umaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxvq_u32, aarch64_neon_umaxv, VectorRet | Add1ArgType),
- NEONMAP1(vmaxvq_u8, aarch64_neon_umaxv, VectorRet | Add1ArgType),
- NEONMAP1(vminnmv_f32, aarch64_neon_vpfminnm, AddRetType | Add1ArgType),
- NEONMAP1(vminnmvq_f32, aarch64_neon_vminnmv, 0),
- NEONMAP1(vminnmvq_f64, aarch64_neon_vpfminnm, AddRetType | Add1ArgType),
- NEONMAP1(vminv_f32, aarch64_neon_vpmin, AddRetType | Add1ArgType),
- NEONMAP1(vminv_s16, aarch64_neon_sminv, VectorRet | Add1ArgType),
- NEONMAP1(vminv_s32, aarch64_neon_sminv, VectorRet | Add1ArgType),
- NEONMAP1(vminv_s8, aarch64_neon_sminv, VectorRet | Add1ArgType),
- NEONMAP1(vminv_u16, aarch64_neon_uminv, VectorRet | Add1ArgType),
- NEONMAP1(vminv_u32, aarch64_neon_uminv, VectorRet | Add1ArgType),
- NEONMAP1(vminv_u8, aarch64_neon_uminv, VectorRet | Add1ArgType),
- NEONMAP1(vminvq_f32, aarch64_neon_vminv, 0),
- NEONMAP1(vminvq_f64, aarch64_neon_vpmin, AddRetType | Add1ArgType),
- NEONMAP1(vminvq_s16, aarch64_neon_sminv, VectorRet | Add1ArgType),
- NEONMAP1(vminvq_s32, aarch64_neon_sminv, VectorRet | Add1ArgType),
- NEONMAP1(vminvq_s8, aarch64_neon_sminv, VectorRet | Add1ArgType),
- NEONMAP1(vminvq_u16, aarch64_neon_uminv, VectorRet | Add1ArgType),
- NEONMAP1(vminvq_u32, aarch64_neon_uminv, VectorRet | Add1ArgType),
- NEONMAP1(vminvq_u8, aarch64_neon_uminv, VectorRet | Add1ArgType),
- NEONMAP0(vmul_n_f64),
- NEONMAP1(vmull_p64, aarch64_neon_vmull_p64, 0),
- NEONMAP0(vmulxd_f64),
- NEONMAP0(vmulxs_f32),
- NEONMAP1(vnegd_s64, aarch64_neon_vneg, 0),
- NEONMAP1(vpaddd_f64, aarch64_neon_vpfadd, AddRetType | Add1ArgType),
- NEONMAP1(vpaddd_s64, aarch64_neon_vpadd, 0),
- NEONMAP1(vpaddd_u64, aarch64_neon_vpadd, 0),
- NEONMAP1(vpadds_f32, aarch64_neon_vpfadd, AddRetType | Add1ArgType),
- NEONMAP1(vpmaxnmqd_f64, aarch64_neon_vpfmaxnm, AddRetType | Add1ArgType),
- NEONMAP1(vpmaxnms_f32, aarch64_neon_vpfmaxnm, AddRetType | Add1ArgType),
- NEONMAP1(vpmaxqd_f64, aarch64_neon_vpmax, AddRetType | Add1ArgType),
- NEONMAP1(vpmaxs_f32, aarch64_neon_vpmax, AddRetType | Add1ArgType),
- NEONMAP1(vpminnmqd_f64, aarch64_neon_vpfminnm, AddRetType | Add1ArgType),
- NEONMAP1(vpminnms_f32, aarch64_neon_vpfminnm, AddRetType | Add1ArgType),
- NEONMAP1(vpminqd_f64, aarch64_neon_vpmin, AddRetType | Add1ArgType),
- NEONMAP1(vpmins_f32, aarch64_neon_vpmin, AddRetType | Add1ArgType),
- NEONMAP1(vqabsb_s8, arm_neon_vqabs, VectorRet),
- NEONMAP1(vqabsd_s64, arm_neon_vqabs, VectorRet),
- NEONMAP1(vqabsh_s16, arm_neon_vqabs, VectorRet),
- NEONMAP1(vqabss_s32, arm_neon_vqabs, VectorRet),
- NEONMAP1(vqaddb_s8, arm_neon_vqadds, VectorRet),
- NEONMAP1(vqaddb_u8, arm_neon_vqaddu, VectorRet),
- NEONMAP1(vqaddd_s64, arm_neon_vqadds, VectorRet),
- NEONMAP1(vqaddd_u64, arm_neon_vqaddu, VectorRet),
- NEONMAP1(vqaddh_s16, arm_neon_vqadds, VectorRet),
- NEONMAP1(vqaddh_u16, arm_neon_vqaddu, VectorRet),
- NEONMAP1(vqadds_s32, arm_neon_vqadds, VectorRet),
- NEONMAP1(vqadds_u32, arm_neon_vqaddu, VectorRet),
- NEONMAP0(vqdmlalh_lane_s16),
- NEONMAP0(vqdmlalh_laneq_s16),
- NEONMAP1(vqdmlalh_s16, aarch64_neon_vqdmlal, VectorRet),
- NEONMAP0(vqdmlals_lane_s32),
- NEONMAP0(vqdmlals_laneq_s32),
- NEONMAP1(vqdmlals_s32, aarch64_neon_vqdmlal, VectorRet),
- NEONMAP0(vqdmlslh_lane_s16),
- NEONMAP0(vqdmlslh_laneq_s16),
- NEONMAP1(vqdmlslh_s16, aarch64_neon_vqdmlsl, VectorRet),
- NEONMAP0(vqdmlsls_lane_s32),
- NEONMAP0(vqdmlsls_laneq_s32),
- NEONMAP1(vqdmlsls_s32, aarch64_neon_vqdmlsl, VectorRet),
- NEONMAP1(vqdmulhh_s16, arm_neon_vqdmulh, VectorRet),
- NEONMAP1(vqdmulhs_s32, arm_neon_vqdmulh, VectorRet),
- NEONMAP1(vqdmullh_s16, arm_neon_vqdmull, VectorRet),
- NEONMAP1(vqdmulls_s32, arm_neon_vqdmull, VectorRet),
- NEONMAP1(vqmovnd_s64, arm_neon_vqmovns, VectorRet),
- NEONMAP1(vqmovnd_u64, arm_neon_vqmovnu, VectorRet),
- NEONMAP1(vqmovnh_s16, arm_neon_vqmovns, VectorRet),
- NEONMAP1(vqmovnh_u16, arm_neon_vqmovnu, VectorRet),
- NEONMAP1(vqmovns_s32, arm_neon_vqmovns, VectorRet),
- NEONMAP1(vqmovns_u32, arm_neon_vqmovnu, VectorRet),
- NEONMAP1(vqmovund_s64, arm_neon_vqmovnsu, VectorRet),
- NEONMAP1(vqmovunh_s16, arm_neon_vqmovnsu, VectorRet),
- NEONMAP1(vqmovuns_s32, arm_neon_vqmovnsu, VectorRet),
- NEONMAP1(vqnegb_s8, arm_neon_vqneg, VectorRet),
- NEONMAP1(vqnegd_s64, arm_neon_vqneg, VectorRet),
- NEONMAP1(vqnegh_s16, arm_neon_vqneg, VectorRet),
- NEONMAP1(vqnegs_s32, arm_neon_vqneg, VectorRet),
- NEONMAP1(vqrdmulhh_s16, arm_neon_vqrdmulh, VectorRet),
- NEONMAP1(vqrdmulhs_s32, arm_neon_vqrdmulh, VectorRet),
- NEONMAP1(vqrshlb_s8, aarch64_neon_vqrshls, VectorRet),
- NEONMAP1(vqrshlb_u8, aarch64_neon_vqrshlu, VectorRet),
- NEONMAP1(vqrshld_s64, aarch64_neon_vqrshls, VectorRet),
- NEONMAP1(vqrshld_u64, aarch64_neon_vqrshlu, VectorRet),
- NEONMAP1(vqrshlh_s16, aarch64_neon_vqrshls, VectorRet),
- NEONMAP1(vqrshlh_u16, aarch64_neon_vqrshlu, VectorRet),
- NEONMAP1(vqrshls_s32, aarch64_neon_vqrshls, VectorRet),
- NEONMAP1(vqrshls_u32, aarch64_neon_vqrshlu, VectorRet),
- NEONMAP1(vqrshrnd_n_s64, aarch64_neon_vsqrshrn, VectorRet),
- NEONMAP1(vqrshrnd_n_u64, aarch64_neon_vuqrshrn, VectorRet),
- NEONMAP1(vqrshrnh_n_s16, aarch64_neon_vsqrshrn, VectorRet),
- NEONMAP1(vqrshrnh_n_u16, aarch64_neon_vuqrshrn, VectorRet),
- NEONMAP1(vqrshrns_n_s32, aarch64_neon_vsqrshrn, VectorRet),
- NEONMAP1(vqrshrns_n_u32, aarch64_neon_vuqrshrn, VectorRet),
- NEONMAP1(vqrshrund_n_s64, aarch64_neon_vsqrshrun, VectorRet),
- NEONMAP1(vqrshrunh_n_s16, aarch64_neon_vsqrshrun, VectorRet),
- NEONMAP1(vqrshruns_n_s32, aarch64_neon_vsqrshrun, VectorRet),
- NEONMAP1(vqshlb_n_s8, aarch64_neon_vqshls_n, VectorRet),
- NEONMAP1(vqshlb_n_u8, aarch64_neon_vqshlu_n, VectorRet),
- NEONMAP1(vqshlb_s8, aarch64_neon_vqshls, VectorRet),
- NEONMAP1(vqshlb_u8, aarch64_neon_vqshlu, VectorRet),
- NEONMAP1(vqshld_n_s64, aarch64_neon_vqshls_n, VectorRet),
- NEONMAP1(vqshld_n_u64, aarch64_neon_vqshlu_n, VectorRet),
- NEONMAP1(vqshld_s64, aarch64_neon_vqshls, VectorRet),
- NEONMAP1(vqshld_u64, aarch64_neon_vqshlu, VectorRet),
- NEONMAP1(vqshlh_n_s16, aarch64_neon_vqshls_n, VectorRet),
- NEONMAP1(vqshlh_n_u16, aarch64_neon_vqshlu_n, VectorRet),
- NEONMAP1(vqshlh_s16, aarch64_neon_vqshls, VectorRet),
- NEONMAP1(vqshlh_u16, aarch64_neon_vqshlu, VectorRet),
- NEONMAP1(vqshls_n_s32, aarch64_neon_vqshls_n, VectorRet),
- NEONMAP1(vqshls_n_u32, aarch64_neon_vqshlu_n, VectorRet),
- NEONMAP1(vqshls_s32, aarch64_neon_vqshls, VectorRet),
- NEONMAP1(vqshls_u32, aarch64_neon_vqshlu, VectorRet),
- NEONMAP1(vqshlub_n_s8, aarch64_neon_vsqshlu, VectorRet),
- NEONMAP1(vqshlud_n_s64, aarch64_neon_vsqshlu, VectorRet),
- NEONMAP1(vqshluh_n_s16, aarch64_neon_vsqshlu, VectorRet),
- NEONMAP1(vqshlus_n_s32, aarch64_neon_vsqshlu, VectorRet),
- NEONMAP1(vqshrnd_n_s64, aarch64_neon_vsqshrn, VectorRet),
- NEONMAP1(vqshrnd_n_u64, aarch64_neon_vuqshrn, VectorRet),
- NEONMAP1(vqshrnh_n_s16, aarch64_neon_vsqshrn, VectorRet),
- NEONMAP1(vqshrnh_n_u16, aarch64_neon_vuqshrn, VectorRet),
- NEONMAP1(vqshrns_n_s32, aarch64_neon_vsqshrn, VectorRet),
- NEONMAP1(vqshrns_n_u32, aarch64_neon_vuqshrn, VectorRet),
- NEONMAP1(vqshrund_n_s64, aarch64_neon_vsqshrun, VectorRet),
- NEONMAP1(vqshrunh_n_s16, aarch64_neon_vsqshrun, VectorRet),
- NEONMAP1(vqshruns_n_s32, aarch64_neon_vsqshrun, VectorRet),
- NEONMAP1(vqsubb_s8, arm_neon_vqsubs, VectorRet),
- NEONMAP1(vqsubb_u8, arm_neon_vqsubu, VectorRet),
- NEONMAP1(vqsubd_s64, arm_neon_vqsubs, VectorRet),
- NEONMAP1(vqsubd_u64, arm_neon_vqsubu, VectorRet),
- NEONMAP1(vqsubh_s16, arm_neon_vqsubs, VectorRet),
- NEONMAP1(vqsubh_u16, arm_neon_vqsubu, VectorRet),
- NEONMAP1(vqsubs_s32, arm_neon_vqsubs, VectorRet),
- NEONMAP1(vqsubs_u32, arm_neon_vqsubu, VectorRet),
- NEONMAP1(vrecped_f64, aarch64_neon_vrecpe, AddRetType),
- NEONMAP1(vrecpes_f32, aarch64_neon_vrecpe, AddRetType),
- NEONMAP1(vrecpsd_f64, aarch64_neon_vrecps, AddRetType),
- NEONMAP1(vrecpss_f32, aarch64_neon_vrecps, AddRetType),
- NEONMAP1(vrecpxd_f64, aarch64_neon_vrecpx, AddRetType),
- NEONMAP1(vrecpxs_f32, aarch64_neon_vrecpx, AddRetType),
- NEONMAP1(vrshld_s64, aarch64_neon_vrshlds, 0),
- NEONMAP1(vrshld_u64, aarch64_neon_vrshldu, 0),
- NEONMAP1(vrshrd_n_s64, aarch64_neon_vsrshr, VectorRet),
- NEONMAP1(vrshrd_n_u64, aarch64_neon_vurshr, VectorRet),
- NEONMAP1(vrsqrted_f64, aarch64_neon_vrsqrte, AddRetType),
- NEONMAP1(vrsqrtes_f32, aarch64_neon_vrsqrte, AddRetType),
- NEONMAP1(vrsqrtsd_f64, aarch64_neon_vrsqrts, AddRetType),
- NEONMAP1(vrsqrtss_f32, aarch64_neon_vrsqrts, AddRetType),
- NEONMAP1(vrsrad_n_s64, aarch64_neon_vrsrads_n, 0),
- NEONMAP1(vrsrad_n_u64, aarch64_neon_vrsradu_n, 0),
- NEONMAP0(vset_lane_f32),
- NEONMAP0(vset_lane_f64),
- NEONMAP0(vset_lane_i16),
- NEONMAP0(vset_lane_i32),
- NEONMAP0(vset_lane_i64),
- NEONMAP0(vset_lane_i8),
- NEONMAP0(vsetq_lane_f32),
- NEONMAP0(vsetq_lane_f64),
- NEONMAP0(vsetq_lane_i16),
- NEONMAP0(vsetq_lane_i32),
- NEONMAP0(vsetq_lane_i64),
- NEONMAP0(vsetq_lane_i8),
- NEONMAP1(vsha1cq_u32, arm_neon_sha1c, 0),
- NEONMAP1(vsha1h_u32, arm_neon_sha1h, 0),
- NEONMAP1(vsha1mq_u32, arm_neon_sha1m, 0),
- NEONMAP1(vsha1pq_u32, arm_neon_sha1p, 0),
- NEONMAP1(vshld_n_s64, aarch64_neon_vshld_n, 0),
- NEONMAP1(vshld_n_u64, aarch64_neon_vshld_n, 0),
- NEONMAP1(vshld_s64, aarch64_neon_vshlds, 0),
- NEONMAP1(vshld_u64, aarch64_neon_vshldu, 0),
- NEONMAP1(vshrd_n_s64, aarch64_neon_vshrds_n, 0),
- NEONMAP1(vshrd_n_u64, aarch64_neon_vshrdu_n, 0),
- NEONMAP1(vslid_n_s64, aarch64_neon_vsli, VectorRet),
- NEONMAP1(vslid_n_u64, aarch64_neon_vsli, VectorRet),
- NEONMAP1(vsqaddb_u8, aarch64_neon_vsqadd, VectorRet),
- NEONMAP1(vsqaddd_u64, aarch64_neon_vsqadd, VectorRet),
- NEONMAP1(vsqaddh_u16, aarch64_neon_vsqadd, VectorRet),
- NEONMAP1(vsqadds_u32, aarch64_neon_vsqadd, VectorRet),
- NEONMAP1(vsrad_n_s64, aarch64_neon_vsrads_n, 0),
- NEONMAP1(vsrad_n_u64, aarch64_neon_vsradu_n, 0),
- NEONMAP1(vsrid_n_s64, aarch64_neon_vsri, VectorRet),
- NEONMAP1(vsrid_n_u64, aarch64_neon_vsri, VectorRet),
- NEONMAP1(vsubd_s64, aarch64_neon_vsubds, 0),
- NEONMAP1(vsubd_u64, aarch64_neon_vsubdu, 0),
- NEONMAP1(vtstd_s64, aarch64_neon_vtstd, VectorRetGetArgs01),
- NEONMAP1(vtstd_u64, aarch64_neon_vtstd, VectorRetGetArgs01),
- NEONMAP1(vuqaddb_s8, aarch64_neon_vuqadd, VectorRet),
- NEONMAP1(vuqaddd_s64, aarch64_neon_vuqadd, VectorRet),
- NEONMAP1(vuqaddh_s16, aarch64_neon_vuqadd, VectorRet),
- NEONMAP1(vuqadds_s32, aarch64_neon_vuqadd, VectorRet)
-};
-
static NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP2(vabd_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts),
NEONMAP2(vabdq_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts),
@@ -2427,109 +2079,109 @@
NEONMAP0(vzipq_v)
};
-static NeonIntrinsicInfo ARM64SIMDIntrinsicMap[] = {
- NEONMAP1(vabs_v, arm64_neon_abs, 0),
- NEONMAP1(vabsq_v, arm64_neon_abs, 0),
+static NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
+ NEONMAP1(vabs_v, aarch64_neon_abs, 0),
+ NEONMAP1(vabsq_v, aarch64_neon_abs, 0),
NEONMAP0(vaddhn_v),
- NEONMAP1(vaesdq_v, arm64_crypto_aesd, 0),
- NEONMAP1(vaeseq_v, arm64_crypto_aese, 0),
- NEONMAP1(vaesimcq_v, arm64_crypto_aesimc, 0),
- NEONMAP1(vaesmcq_v, arm64_crypto_aesmc, 0),
- NEONMAP1(vcage_v, arm64_neon_facge, 0),
- NEONMAP1(vcageq_v, arm64_neon_facge, 0),
- NEONMAP1(vcagt_v, arm64_neon_facgt, 0),
- NEONMAP1(vcagtq_v, arm64_neon_facgt, 0),
- NEONMAP1(vcale_v, arm64_neon_facge, 0),
- NEONMAP1(vcaleq_v, arm64_neon_facge, 0),
- NEONMAP1(vcalt_v, arm64_neon_facgt, 0),
- NEONMAP1(vcaltq_v, arm64_neon_facgt, 0),
- NEONMAP1(vcls_v, arm64_neon_cls, Add1ArgType),
- NEONMAP1(vclsq_v, arm64_neon_cls, Add1ArgType),
+ NEONMAP1(vaesdq_v, aarch64_crypto_aesd, 0),
+ NEONMAP1(vaeseq_v, aarch64_crypto_aese, 0),
+ NEONMAP1(vaesimcq_v, aarch64_crypto_aesimc, 0),
+ NEONMAP1(vaesmcq_v, aarch64_crypto_aesmc, 0),
+ NEONMAP1(vcage_v, aarch64_neon_facge, 0),
+ NEONMAP1(vcageq_v, aarch64_neon_facge, 0),
+ NEONMAP1(vcagt_v, aarch64_neon_facgt, 0),
+ NEONMAP1(vcagtq_v, aarch64_neon_facgt, 0),
+ NEONMAP1(vcale_v, aarch64_neon_facge, 0),
+ NEONMAP1(vcaleq_v, aarch64_neon_facge, 0),
+ NEONMAP1(vcalt_v, aarch64_neon_facgt, 0),
+ NEONMAP1(vcaltq_v, aarch64_neon_facgt, 0),
+ NEONMAP1(vcls_v, aarch64_neon_cls, Add1ArgType),
+ NEONMAP1(vclsq_v, aarch64_neon_cls, Add1ArgType),
NEONMAP1(vclz_v, ctlz, Add1ArgType),
NEONMAP1(vclzq_v, ctlz, Add1ArgType),
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
NEONMAP1(vcntq_v, ctpop, Add1ArgType),
- NEONMAP1(vcvt_f16_v, arm64_neon_vcvtfp2hf, 0),
- NEONMAP1(vcvt_f32_f16, arm64_neon_vcvthf2fp, 0),
+ NEONMAP1(vcvt_f16_v, aarch64_neon_vcvtfp2hf, 0),
+ NEONMAP1(vcvt_f32_f16, aarch64_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
- NEONMAP2(vcvt_n_f32_v, arm64_neon_vcvtfxu2fp, arm64_neon_vcvtfxs2fp, 0),
- NEONMAP2(vcvt_n_f64_v, arm64_neon_vcvtfxu2fp, arm64_neon_vcvtfxs2fp, 0),
- NEONMAP1(vcvt_n_s32_v, arm64_neon_vcvtfp2fxs, 0),
- NEONMAP1(vcvt_n_s64_v, arm64_neon_vcvtfp2fxs, 0),
- NEONMAP1(vcvt_n_u32_v, arm64_neon_vcvtfp2fxu, 0),
- NEONMAP1(vcvt_n_u64_v, arm64_neon_vcvtfp2fxu, 0),
+ NEONMAP2(vcvt_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
+ NEONMAP2(vcvt_n_f64_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
+ NEONMAP1(vcvt_n_s32_v, aarch64_neon_vcvtfp2fxs, 0),
+ NEONMAP1(vcvt_n_s64_v, aarch64_neon_vcvtfp2fxs, 0),
+ NEONMAP1(vcvt_n_u32_v, aarch64_neon_vcvtfp2fxu, 0),
+ NEONMAP1(vcvt_n_u64_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP0(vcvtq_f32_v),
- NEONMAP2(vcvtq_n_f32_v, arm64_neon_vcvtfxu2fp, arm64_neon_vcvtfxs2fp, 0),
- NEONMAP2(vcvtq_n_f64_v, arm64_neon_vcvtfxu2fp, arm64_neon_vcvtfxs2fp, 0),
- NEONMAP1(vcvtq_n_s32_v, arm64_neon_vcvtfp2fxs, 0),
- NEONMAP1(vcvtq_n_s64_v, arm64_neon_vcvtfp2fxs, 0),
- NEONMAP1(vcvtq_n_u32_v, arm64_neon_vcvtfp2fxu, 0),
- NEONMAP1(vcvtq_n_u64_v, arm64_neon_vcvtfp2fxu, 0),
- NEONMAP1(vcvtx_f32_v, arm64_neon_fcvtxn, AddRetType | Add1ArgType),
+ NEONMAP2(vcvtq_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
+ NEONMAP2(vcvtq_n_f64_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
+ NEONMAP1(vcvtq_n_s32_v, aarch64_neon_vcvtfp2fxs, 0),
+ NEONMAP1(vcvtq_n_s64_v, aarch64_neon_vcvtfp2fxs, 0),
+ NEONMAP1(vcvtq_n_u32_v, aarch64_neon_vcvtfp2fxu, 0),
+ NEONMAP1(vcvtq_n_u64_v, aarch64_neon_vcvtfp2fxu, 0),
+ NEONMAP1(vcvtx_f32_v, aarch64_neon_fcvtxn, AddRetType | Add1ArgType),
NEONMAP0(vext_v),
NEONMAP0(vextq_v),
NEONMAP0(vfma_v),
NEONMAP0(vfmaq_v),
- NEONMAP2(vhadd_v, arm64_neon_uhadd, arm64_neon_shadd, Add1ArgType | UnsignedAlts),
- NEONMAP2(vhaddq_v, arm64_neon_uhadd, arm64_neon_shadd, Add1ArgType | UnsignedAlts),
- NEONMAP2(vhsub_v, arm64_neon_uhsub, arm64_neon_shsub, Add1ArgType | UnsignedAlts),
- NEONMAP2(vhsubq_v, arm64_neon_uhsub, arm64_neon_shsub, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vhadd_v, aarch64_neon_uhadd, aarch64_neon_shadd, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vhaddq_v, aarch64_neon_uhadd, aarch64_neon_shadd, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vhsub_v, aarch64_neon_uhsub, aarch64_neon_shsub, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vhsubq_v, aarch64_neon_uhsub, aarch64_neon_shsub, Add1ArgType | UnsignedAlts),
NEONMAP0(vmovl_v),
NEONMAP0(vmovn_v),
- NEONMAP1(vmul_v, arm64_neon_pmul, Add1ArgType),
- NEONMAP1(vmulq_v, arm64_neon_pmul, Add1ArgType),
- NEONMAP1(vpadd_v, arm64_neon_addp, Add1ArgType),
- NEONMAP2(vpaddl_v, arm64_neon_uaddlp, arm64_neon_saddlp, UnsignedAlts),
- NEONMAP2(vpaddlq_v, arm64_neon_uaddlp, arm64_neon_saddlp, UnsignedAlts),
- NEONMAP1(vpaddq_v, arm64_neon_addp, Add1ArgType),
- NEONMAP1(vqabs_v, arm64_neon_sqabs, Add1ArgType),
- NEONMAP1(vqabsq_v, arm64_neon_sqabs, Add1ArgType),
- NEONMAP2(vqadd_v, arm64_neon_uqadd, arm64_neon_sqadd, Add1ArgType | UnsignedAlts),
- NEONMAP2(vqaddq_v, arm64_neon_uqadd, arm64_neon_sqadd, Add1ArgType | UnsignedAlts),
- NEONMAP2(vqdmlal_v, arm64_neon_sqdmull, arm64_neon_sqadd, 0),
- NEONMAP2(vqdmlsl_v, arm64_neon_sqdmull, arm64_neon_sqsub, 0),
- NEONMAP1(vqdmulh_v, arm64_neon_sqdmulh, Add1ArgType),
- NEONMAP1(vqdmulhq_v, arm64_neon_sqdmulh, Add1ArgType),
- NEONMAP1(vqdmull_v, arm64_neon_sqdmull, Add1ArgType),
- NEONMAP2(vqmovn_v, arm64_neon_uqxtn, arm64_neon_sqxtn, Add1ArgType | UnsignedAlts),
- NEONMAP1(vqmovun_v, arm64_neon_sqxtun, Add1ArgType),
- NEONMAP1(vqneg_v, arm64_neon_sqneg, Add1ArgType),
- NEONMAP1(vqnegq_v, arm64_neon_sqneg, Add1ArgType),
- NEONMAP1(vqrdmulh_v, arm64_neon_sqrdmulh, Add1ArgType),
- NEONMAP1(vqrdmulhq_v, arm64_neon_sqrdmulh, Add1ArgType),
- NEONMAP2(vqrshl_v, arm64_neon_uqrshl, arm64_neon_sqrshl, Add1ArgType | UnsignedAlts),
- NEONMAP2(vqrshlq_v, arm64_neon_uqrshl, arm64_neon_sqrshl, Add1ArgType | UnsignedAlts),
- NEONMAP2(vqshl_n_v, arm64_neon_uqshl, arm64_neon_sqshl, UnsignedAlts),
- NEONMAP2(vqshl_v, arm64_neon_uqshl, arm64_neon_sqshl, Add1ArgType | UnsignedAlts),
- NEONMAP2(vqshlq_n_v, arm64_neon_uqshl, arm64_neon_sqshl,UnsignedAlts),
- NEONMAP2(vqshlq_v, arm64_neon_uqshl, arm64_neon_sqshl, Add1ArgType | UnsignedAlts),
- NEONMAP2(vqsub_v, arm64_neon_uqsub, arm64_neon_sqsub, Add1ArgType | UnsignedAlts),
- NEONMAP2(vqsubq_v, arm64_neon_uqsub, arm64_neon_sqsub, Add1ArgType | UnsignedAlts),
- NEONMAP1(vraddhn_v, arm64_neon_raddhn, Add1ArgType),
- NEONMAP2(vrecpe_v, arm64_neon_frecpe, arm64_neon_urecpe, 0),
- NEONMAP2(vrecpeq_v, arm64_neon_frecpe, arm64_neon_urecpe, 0),
- NEONMAP1(vrecps_v, arm64_neon_frecps, Add1ArgType),
- NEONMAP1(vrecpsq_v, arm64_neon_frecps, Add1ArgType),
- NEONMAP2(vrhadd_v, arm64_neon_urhadd, arm64_neon_srhadd, Add1ArgType | UnsignedAlts),
- NEONMAP2(vrhaddq_v, arm64_neon_urhadd, arm64_neon_srhadd, Add1ArgType | UnsignedAlts),
- NEONMAP2(vrshl_v, arm64_neon_urshl, arm64_neon_srshl, Add1ArgType | UnsignedAlts),
- NEONMAP2(vrshlq_v, arm64_neon_urshl, arm64_neon_srshl, Add1ArgType | UnsignedAlts),
- NEONMAP2(vrsqrte_v, arm64_neon_frsqrte, arm64_neon_ursqrte, 0),
- NEONMAP2(vrsqrteq_v, arm64_neon_frsqrte, arm64_neon_ursqrte, 0),
- NEONMAP1(vrsqrts_v, arm64_neon_frsqrts, Add1ArgType),
- NEONMAP1(vrsqrtsq_v, arm64_neon_frsqrts, Add1ArgType),
- NEONMAP1(vrsubhn_v, arm64_neon_rsubhn, Add1ArgType),
- NEONMAP1(vsha1su0q_v, arm64_crypto_sha1su0, 0),
- NEONMAP1(vsha1su1q_v, arm64_crypto_sha1su1, 0),
- NEONMAP1(vsha256h2q_v, arm64_crypto_sha256h2, 0),
- NEONMAP1(vsha256hq_v, arm64_crypto_sha256h, 0),
- NEONMAP1(vsha256su0q_v, arm64_crypto_sha256su0, 0),
- NEONMAP1(vsha256su1q_v, arm64_crypto_sha256su1, 0),
+ NEONMAP1(vmul_v, aarch64_neon_pmul, Add1ArgType),
+ NEONMAP1(vmulq_v, aarch64_neon_pmul, Add1ArgType),
+ NEONMAP1(vpadd_v, aarch64_neon_addp, Add1ArgType),
+ NEONMAP2(vpaddl_v, aarch64_neon_uaddlp, aarch64_neon_saddlp, UnsignedAlts),
+ NEONMAP2(vpaddlq_v, aarch64_neon_uaddlp, aarch64_neon_saddlp, UnsignedAlts),
+ NEONMAP1(vpaddq_v, aarch64_neon_addp, Add1ArgType),
+ NEONMAP1(vqabs_v, aarch64_neon_sqabs, Add1ArgType),
+ NEONMAP1(vqabsq_v, aarch64_neon_sqabs, Add1ArgType),
+ NEONMAP2(vqadd_v, aarch64_neon_uqadd, aarch64_neon_sqadd, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vqaddq_v, aarch64_neon_uqadd, aarch64_neon_sqadd, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vqdmlal_v, aarch64_neon_sqdmull, aarch64_neon_sqadd, 0),
+ NEONMAP2(vqdmlsl_v, aarch64_neon_sqdmull, aarch64_neon_sqsub, 0),
+ NEONMAP1(vqdmulh_v, aarch64_neon_sqdmulh, Add1ArgType),
+ NEONMAP1(vqdmulhq_v, aarch64_neon_sqdmulh, Add1ArgType),
+ NEONMAP1(vqdmull_v, aarch64_neon_sqdmull, Add1ArgType),
+ NEONMAP2(vqmovn_v, aarch64_neon_uqxtn, aarch64_neon_sqxtn, Add1ArgType | UnsignedAlts),
+ NEONMAP1(vqmovun_v, aarch64_neon_sqxtun, Add1ArgType),
+ NEONMAP1(vqneg_v, aarch64_neon_sqneg, Add1ArgType),
+ NEONMAP1(vqnegq_v, aarch64_neon_sqneg, Add1ArgType),
+ NEONMAP1(vqrdmulh_v, aarch64_neon_sqrdmulh, Add1ArgType),
+ NEONMAP1(vqrdmulhq_v, aarch64_neon_sqrdmulh, Add1ArgType),
+ NEONMAP2(vqrshl_v, aarch64_neon_uqrshl, aarch64_neon_sqrshl, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vqrshlq_v, aarch64_neon_uqrshl, aarch64_neon_sqrshl, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vqshl_n_v, aarch64_neon_uqshl, aarch64_neon_sqshl, UnsignedAlts),
+ NEONMAP2(vqshl_v, aarch64_neon_uqshl, aarch64_neon_sqshl, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vqshlq_n_v, aarch64_neon_uqshl, aarch64_neon_sqshl,UnsignedAlts),
+ NEONMAP2(vqshlq_v, aarch64_neon_uqshl, aarch64_neon_sqshl, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vqsub_v, aarch64_neon_uqsub, aarch64_neon_sqsub, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vqsubq_v, aarch64_neon_uqsub, aarch64_neon_sqsub, Add1ArgType | UnsignedAlts),
+ NEONMAP1(vraddhn_v, aarch64_neon_raddhn, Add1ArgType),
+ NEONMAP2(vrecpe_v, aarch64_neon_frecpe, aarch64_neon_urecpe, 0),
+ NEONMAP2(vrecpeq_v, aarch64_neon_frecpe, aarch64_neon_urecpe, 0),
+ NEONMAP1(vrecps_v, aarch64_neon_frecps, Add1ArgType),
+ NEONMAP1(vrecpsq_v, aarch64_neon_frecps, Add1ArgType),
+ NEONMAP2(vrhadd_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vrhaddq_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vrshl_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vrshlq_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vrsqrte_v, aarch64_neon_frsqrte, aarch64_neon_ursqrte, 0),
+ NEONMAP2(vrsqrteq_v, aarch64_neon_frsqrte, aarch64_neon_ursqrte, 0),
+ NEONMAP1(vrsqrts_v, aarch64_neon_frsqrts, Add1ArgType),
+ NEONMAP1(vrsqrtsq_v, aarch64_neon_frsqrts, Add1ArgType),
+ NEONMAP1(vrsubhn_v, aarch64_neon_rsubhn, Add1ArgType),
+ NEONMAP1(vsha1su0q_v, aarch64_crypto_sha1su0, 0),
+ NEONMAP1(vsha1su1q_v, aarch64_crypto_sha1su1, 0),
+ NEONMAP1(vsha256h2q_v, aarch64_crypto_sha256h2, 0),
+ NEONMAP1(vsha256hq_v, aarch64_crypto_sha256h, 0),
+ NEONMAP1(vsha256su0q_v, aarch64_crypto_sha256su0, 0),
+ NEONMAP1(vsha256su1q_v, aarch64_crypto_sha256su1, 0),
NEONMAP0(vshl_n_v),
- NEONMAP2(vshl_v, arm64_neon_ushl, arm64_neon_sshl, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vshl_v, aarch64_neon_ushl, aarch64_neon_sshl, Add1ArgType | UnsignedAlts),
NEONMAP0(vshll_n_v),
NEONMAP0(vshlq_n_v),
- NEONMAP2(vshlq_v, arm64_neon_ushl, arm64_neon_sshl, Add1ArgType | UnsignedAlts),
+ NEONMAP2(vshlq_v, aarch64_neon_ushl, aarch64_neon_sshl, Add1ArgType | UnsignedAlts),
NEONMAP0(vshr_n_v),
NEONMAP0(vshrn_n_v),
NEONMAP0(vshrq_n_v),
@@ -2538,199 +2190,199 @@
NEONMAP0(vtstq_v),
};
-static NeonIntrinsicInfo ARM64SISDIntrinsicMap[] = {
- NEONMAP1(vabdd_f64, arm64_sisd_fabd, Add1ArgType),
- NEONMAP1(vabds_f32, arm64_sisd_fabd, Add1ArgType),
- NEONMAP1(vabsd_s64, arm64_neon_abs, Add1ArgType),
- NEONMAP1(vaddlv_s32, arm64_neon_saddlv, AddRetType | Add1ArgType),
- NEONMAP1(vaddlv_u32, arm64_neon_uaddlv, AddRetType | Add1ArgType),
- NEONMAP1(vaddlvq_s32, arm64_neon_saddlv, AddRetType | Add1ArgType),
- NEONMAP1(vaddlvq_u32, arm64_neon_uaddlv, AddRetType | Add1ArgType),
- NEONMAP1(vaddv_f32, arm64_neon_faddv, AddRetType | Add1ArgType),
- NEONMAP1(vaddv_s32, arm64_neon_saddv, AddRetType | Add1ArgType),
- NEONMAP1(vaddv_u32, arm64_neon_uaddv, AddRetType | Add1ArgType),
- NEONMAP1(vaddvq_f32, arm64_neon_faddv, AddRetType | Add1ArgType),
- NEONMAP1(vaddvq_f64, arm64_neon_faddv, AddRetType | Add1ArgType),
- NEONMAP1(vaddvq_s32, arm64_neon_saddv, AddRetType | Add1ArgType),
- NEONMAP1(vaddvq_s64, arm64_neon_saddv, AddRetType | Add1ArgType),
- NEONMAP1(vaddvq_u32, arm64_neon_uaddv, AddRetType | Add1ArgType),
- NEONMAP1(vaddvq_u64, arm64_neon_uaddv, AddRetType | Add1ArgType),
- NEONMAP1(vcaged_f64, arm64_neon_facge, AddRetType | Add1ArgType),
- NEONMAP1(vcages_f32, arm64_neon_facge, AddRetType | Add1ArgType),
- NEONMAP1(vcagtd_f64, arm64_neon_facgt, AddRetType | Add1ArgType),
- NEONMAP1(vcagts_f32, arm64_neon_facgt, AddRetType | Add1ArgType),
- NEONMAP1(vcaled_f64, arm64_neon_facge, AddRetType | Add1ArgType),
- NEONMAP1(vcales_f32, arm64_neon_facge, AddRetType | Add1ArgType),
- NEONMAP1(vcaltd_f64, arm64_neon_facgt, AddRetType | Add1ArgType),
- NEONMAP1(vcalts_f32, arm64_neon_facgt, AddRetType | Add1ArgType),
- NEONMAP1(vcvtad_s64_f64, arm64_neon_fcvtas, AddRetType | Add1ArgType),
- NEONMAP1(vcvtad_u64_f64, arm64_neon_fcvtau, AddRetType | Add1ArgType),
- NEONMAP1(vcvtas_s32_f32, arm64_neon_fcvtas, AddRetType | Add1ArgType),
- NEONMAP1(vcvtas_u32_f32, arm64_neon_fcvtau, AddRetType | Add1ArgType),
- NEONMAP1(vcvtd_n_f64_s64, arm64_neon_vcvtfxs2fp, AddRetType | Add1ArgType),
- NEONMAP1(vcvtd_n_f64_u64, arm64_neon_vcvtfxu2fp, AddRetType | Add1ArgType),
- NEONMAP1(vcvtd_n_s64_f64, arm64_neon_vcvtfp2fxs, AddRetType | Add1ArgType),
- NEONMAP1(vcvtd_n_u64_f64, arm64_neon_vcvtfp2fxu, AddRetType | Add1ArgType),
- NEONMAP1(vcvtmd_s64_f64, arm64_neon_fcvtms, AddRetType | Add1ArgType),
- NEONMAP1(vcvtmd_u64_f64, arm64_neon_fcvtmu, AddRetType | Add1ArgType),
- NEONMAP1(vcvtms_s32_f32, arm64_neon_fcvtms, AddRetType | Add1ArgType),
- NEONMAP1(vcvtms_u32_f32, arm64_neon_fcvtmu, AddRetType | Add1ArgType),
- NEONMAP1(vcvtnd_s64_f64, arm64_neon_fcvtns, AddRetType | Add1ArgType),
- NEONMAP1(vcvtnd_u64_f64, arm64_neon_fcvtnu, AddRetType | Add1ArgType),
- NEONMAP1(vcvtns_s32_f32, arm64_neon_fcvtns, AddRetType | Add1ArgType),
- NEONMAP1(vcvtns_u32_f32, arm64_neon_fcvtnu, AddRetType | Add1ArgType),
- NEONMAP1(vcvtpd_s64_f64, arm64_neon_fcvtps, AddRetType | Add1ArgType),
- NEONMAP1(vcvtpd_u64_f64, arm64_neon_fcvtpu, AddRetType | Add1ArgType),
- NEONMAP1(vcvtps_s32_f32, arm64_neon_fcvtps, AddRetType | Add1ArgType),
- NEONMAP1(vcvtps_u32_f32, arm64_neon_fcvtpu, AddRetType | Add1ArgType),
- NEONMAP1(vcvts_n_f32_s32, arm64_neon_vcvtfxs2fp, AddRetType | Add1ArgType),
- NEONMAP1(vcvts_n_f32_u32, arm64_neon_vcvtfxu2fp, AddRetType | Add1ArgType),
- NEONMAP1(vcvts_n_s32_f32, arm64_neon_vcvtfp2fxs, AddRetType | Add1ArgType),
- NEONMAP1(vcvts_n_u32_f32, arm64_neon_vcvtfp2fxu, AddRetType | Add1ArgType),
- NEONMAP1(vcvtxd_f32_f64, arm64_sisd_fcvtxn, 0),
- NEONMAP1(vmaxnmv_f32, arm64_neon_fmaxnmv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxnmvq_f32, arm64_neon_fmaxnmv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxnmvq_f64, arm64_neon_fmaxnmv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxv_f32, arm64_neon_fmaxv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxv_s32, arm64_neon_smaxv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxv_u32, arm64_neon_umaxv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxvq_f32, arm64_neon_fmaxv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxvq_f64, arm64_neon_fmaxv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxvq_s32, arm64_neon_smaxv, AddRetType | Add1ArgType),
- NEONMAP1(vmaxvq_u32, arm64_neon_umaxv, AddRetType | Add1ArgType),
- NEONMAP1(vminnmv_f32, arm64_neon_fminnmv, AddRetType | Add1ArgType),
- NEONMAP1(vminnmvq_f32, arm64_neon_fminnmv, AddRetType | Add1ArgType),
- NEONMAP1(vminnmvq_f64, arm64_neon_fminnmv, AddRetType | Add1ArgType),
- NEONMAP1(vminv_f32, arm64_neon_fminv, AddRetType | Add1ArgType),
- NEONMAP1(vminv_s32, arm64_neon_sminv, AddRetType | Add1ArgType),
- NEONMAP1(vminv_u32, arm64_neon_uminv, AddRetType | Add1ArgType),
- NEONMAP1(vminvq_f32, arm64_neon_fminv, AddRetType | Add1ArgType),
- NEONMAP1(vminvq_f64, arm64_neon_fminv, AddRetType | Add1ArgType),
- NEONMAP1(vminvq_s32, arm64_neon_sminv, AddRetType | Add1ArgType),
- NEONMAP1(vminvq_u32, arm64_neon_uminv, AddRetType | Add1ArgType),
- NEONMAP1(vmull_p64, arm64_neon_pmull64, 0),
- NEONMAP1(vmulxd_f64, arm64_neon_fmulx, Add1ArgType),
- NEONMAP1(vmulxs_f32, arm64_neon_fmulx, Add1ArgType),
- NEONMAP1(vpaddd_s64, arm64_neon_uaddv, AddRetType | Add1ArgType),
- NEONMAP1(vpaddd_u64, arm64_neon_uaddv, AddRetType | Add1ArgType),
- NEONMAP1(vpmaxnmqd_f64, arm64_neon_fmaxnmv, AddRetType | Add1ArgType),
- NEONMAP1(vpmaxnms_f32, arm64_neon_fmaxnmv, AddRetType | Add1ArgType),
- NEONMAP1(vpmaxqd_f64, arm64_neon_fmaxv, AddRetType | Add1ArgType),
- NEONMAP1(vpmaxs_f32, arm64_neon_fmaxv, AddRetType | Add1ArgType),
- NEONMAP1(vpminnmqd_f64, arm64_neon_fminnmv, AddRetType | Add1ArgType),
- NEONMAP1(vpminnms_f32, arm64_neon_fminnmv, AddRetType | Add1ArgType),
- NEONMAP1(vpminqd_f64, arm64_neon_fminv, AddRetType | Add1ArgType),
- NEONMAP1(vpmins_f32, arm64_neon_fminv, AddRetType | Add1ArgType),
- NEONMAP1(vqabsb_s8, arm64_neon_sqabs, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqabsd_s64, arm64_neon_sqabs, Add1ArgType),
- NEONMAP1(vqabsh_s16, arm64_neon_sqabs, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqabss_s32, arm64_neon_sqabs, Add1ArgType),
- NEONMAP1(vqaddb_s8, arm64_neon_sqadd, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqaddb_u8, arm64_neon_uqadd, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqaddd_s64, arm64_neon_sqadd, Add1ArgType),
- NEONMAP1(vqaddd_u64, arm64_neon_uqadd, Add1ArgType),
- NEONMAP1(vqaddh_s16, arm64_neon_sqadd, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqaddh_u16, arm64_neon_uqadd, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqadds_s32, arm64_neon_sqadd, Add1ArgType),
- NEONMAP1(vqadds_u32, arm64_neon_uqadd, Add1ArgType),
- NEONMAP1(vqdmulhh_s16, arm64_neon_sqdmulh, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqdmulhs_s32, arm64_neon_sqdmulh, Add1ArgType),
- NEONMAP1(vqdmullh_s16, arm64_neon_sqdmull, VectorRet | Use128BitVectors),
- NEONMAP1(vqdmulls_s32, arm64_neon_sqdmulls_scalar, 0),
- NEONMAP1(vqmovnd_s64, arm64_neon_scalar_sqxtn, AddRetType | Add1ArgType),
- NEONMAP1(vqmovnd_u64, arm64_neon_scalar_uqxtn, AddRetType | Add1ArgType),
- NEONMAP1(vqmovnh_s16, arm64_neon_sqxtn, VectorRet | Use64BitVectors),
- NEONMAP1(vqmovnh_u16, arm64_neon_uqxtn, VectorRet | Use64BitVectors),
- NEONMAP1(vqmovns_s32, arm64_neon_sqxtn, VectorRet | Use64BitVectors),
- NEONMAP1(vqmovns_u32, arm64_neon_uqxtn, VectorRet | Use64BitVectors),
- NEONMAP1(vqmovund_s64, arm64_neon_scalar_sqxtun, AddRetType | Add1ArgType),
- NEONMAP1(vqmovunh_s16, arm64_neon_sqxtun, VectorRet | Use64BitVectors),
- NEONMAP1(vqmovuns_s32, arm64_neon_sqxtun, VectorRet | Use64BitVectors),
- NEONMAP1(vqnegb_s8, arm64_neon_sqneg, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqnegd_s64, arm64_neon_sqneg, Add1ArgType),
- NEONMAP1(vqnegh_s16, arm64_neon_sqneg, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqnegs_s32, arm64_neon_sqneg, Add1ArgType),
- NEONMAP1(vqrdmulhh_s16, arm64_neon_sqrdmulh, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqrdmulhs_s32, arm64_neon_sqrdmulh, Add1ArgType),
- NEONMAP1(vqrshlb_s8, arm64_neon_sqrshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqrshlb_u8, arm64_neon_uqrshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqrshld_s64, arm64_neon_sqrshl, Add1ArgType),
- NEONMAP1(vqrshld_u64, arm64_neon_uqrshl, Add1ArgType),
- NEONMAP1(vqrshlh_s16, arm64_neon_sqrshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqrshlh_u16, arm64_neon_uqrshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqrshls_s32, arm64_neon_sqrshl, Add1ArgType),
- NEONMAP1(vqrshls_u32, arm64_neon_uqrshl, Add1ArgType),
- NEONMAP1(vqrshrnd_n_s64, arm64_neon_sqrshrn, AddRetType),
- NEONMAP1(vqrshrnd_n_u64, arm64_neon_uqrshrn, AddRetType),
- NEONMAP1(vqrshrnh_n_s16, arm64_neon_sqrshrn, VectorRet | Use64BitVectors),
- NEONMAP1(vqrshrnh_n_u16, arm64_neon_uqrshrn, VectorRet | Use64BitVectors),
- NEONMAP1(vqrshrns_n_s32, arm64_neon_sqrshrn, VectorRet | Use64BitVectors),
- NEONMAP1(vqrshrns_n_u32, arm64_neon_uqrshrn, VectorRet | Use64BitVectors),
- NEONMAP1(vqrshrund_n_s64, arm64_neon_sqrshrun, AddRetType),
- NEONMAP1(vqrshrunh_n_s16, arm64_neon_sqrshrun, VectorRet | Use64BitVectors),
- NEONMAP1(vqrshruns_n_s32, arm64_neon_sqrshrun, VectorRet | Use64BitVectors),
- NEONMAP1(vqshlb_n_s8, arm64_neon_sqshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshlb_n_u8, arm64_neon_uqshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshlb_s8, arm64_neon_sqshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshlb_u8, arm64_neon_uqshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshld_s64, arm64_neon_sqshl, Add1ArgType),
- NEONMAP1(vqshld_u64, arm64_neon_uqshl, Add1ArgType),
- NEONMAP1(vqshlh_n_s16, arm64_neon_sqshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshlh_n_u16, arm64_neon_uqshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshlh_s16, arm64_neon_sqshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshlh_u16, arm64_neon_uqshl, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshls_n_s32, arm64_neon_sqshl, Add1ArgType),
- NEONMAP1(vqshls_n_u32, arm64_neon_uqshl, Add1ArgType),
- NEONMAP1(vqshls_s32, arm64_neon_sqshl, Add1ArgType),
- NEONMAP1(vqshls_u32, arm64_neon_uqshl, Add1ArgType),
- NEONMAP1(vqshlub_n_s8, arm64_neon_sqshlu, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshluh_n_s16, arm64_neon_sqshlu, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqshlus_n_s32, arm64_neon_sqshlu, Add1ArgType),
- NEONMAP1(vqshrnd_n_s64, arm64_neon_sqshrn, AddRetType),
- NEONMAP1(vqshrnd_n_u64, arm64_neon_uqshrn, AddRetType),
- NEONMAP1(vqshrnh_n_s16, arm64_neon_sqshrn, VectorRet | Use64BitVectors),
- NEONMAP1(vqshrnh_n_u16, arm64_neon_uqshrn, VectorRet | Use64BitVectors),
- NEONMAP1(vqshrns_n_s32, arm64_neon_sqshrn, VectorRet | Use64BitVectors),
- NEONMAP1(vqshrns_n_u32, arm64_neon_uqshrn, VectorRet | Use64BitVectors),
- NEONMAP1(vqshrund_n_s64, arm64_neon_sqshrun, AddRetType),
- NEONMAP1(vqshrunh_n_s16, arm64_neon_sqshrun, VectorRet | Use64BitVectors),
- NEONMAP1(vqshruns_n_s32, arm64_neon_sqshrun, VectorRet | Use64BitVectors),
- NEONMAP1(vqsubb_s8, arm64_neon_sqsub, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqsubb_u8, arm64_neon_uqsub, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqsubd_s64, arm64_neon_sqsub, Add1ArgType),
- NEONMAP1(vqsubd_u64, arm64_neon_uqsub, Add1ArgType),
- NEONMAP1(vqsubh_s16, arm64_neon_sqsub, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqsubh_u16, arm64_neon_uqsub, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vqsubs_s32, arm64_neon_sqsub, Add1ArgType),
- NEONMAP1(vqsubs_u32, arm64_neon_uqsub, Add1ArgType),
- NEONMAP1(vrecped_f64, arm64_neon_frecpe, Add1ArgType),
- NEONMAP1(vrecpes_f32, arm64_neon_frecpe, Add1ArgType),
- NEONMAP1(vrecpxd_f64, arm64_neon_frecpx, Add1ArgType),
- NEONMAP1(vrecpxs_f32, arm64_neon_frecpx, Add1ArgType),
- NEONMAP1(vrshld_s64, arm64_neon_srshl, Add1ArgType),
- NEONMAP1(vrshld_u64, arm64_neon_urshl, Add1ArgType),
- NEONMAP1(vrsqrted_f64, arm64_neon_frsqrte, Add1ArgType),
- NEONMAP1(vrsqrtes_f32, arm64_neon_frsqrte, Add1ArgType),
- NEONMAP1(vrsqrtsd_f64, arm64_neon_frsqrts, Add1ArgType),
- NEONMAP1(vrsqrtss_f32, arm64_neon_frsqrts, Add1ArgType),
- NEONMAP1(vsha1cq_u32, arm64_crypto_sha1c, 0),
- NEONMAP1(vsha1h_u32, arm64_crypto_sha1h, 0),
- NEONMAP1(vsha1mq_u32, arm64_crypto_sha1m, 0),
- NEONMAP1(vsha1pq_u32, arm64_crypto_sha1p, 0),
- NEONMAP1(vshld_s64, arm64_neon_sshl, Add1ArgType),
- NEONMAP1(vshld_u64, arm64_neon_ushl, Add1ArgType),
- NEONMAP1(vslid_n_s64, arm64_neon_vsli, Vectorize1ArgType),
- NEONMAP1(vslid_n_u64, arm64_neon_vsli, Vectorize1ArgType),
- NEONMAP1(vsqaddb_u8, arm64_neon_usqadd, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vsqaddd_u64, arm64_neon_usqadd, Add1ArgType),
- NEONMAP1(vsqaddh_u16, arm64_neon_usqadd, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vsqadds_u32, arm64_neon_usqadd, Add1ArgType),
- NEONMAP1(vsrid_n_s64, arm64_neon_vsri, Vectorize1ArgType),
- NEONMAP1(vsrid_n_u64, arm64_neon_vsri, Vectorize1ArgType),
- NEONMAP1(vuqaddb_s8, arm64_neon_suqadd, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vuqaddd_s64, arm64_neon_suqadd, Add1ArgType),
- NEONMAP1(vuqaddh_s16, arm64_neon_suqadd, Vectorize1ArgType | Use64BitVectors),
- NEONMAP1(vuqadds_s32, arm64_neon_suqadd, Add1ArgType),
+static NeonIntrinsicInfo AArch64SISDIntrinsicMap[] = {
+ NEONMAP1(vabdd_f64, aarch64_sisd_fabd, Add1ArgType),
+ NEONMAP1(vabds_f32, aarch64_sisd_fabd, Add1ArgType),
+ NEONMAP1(vabsd_s64, aarch64_neon_abs, Add1ArgType),
+ NEONMAP1(vaddlv_s32, aarch64_neon_saddlv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddlv_u32, aarch64_neon_uaddlv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddlvq_s32, aarch64_neon_saddlv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddlvq_u32, aarch64_neon_uaddlv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddv_f32, aarch64_neon_faddv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddv_s32, aarch64_neon_saddv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddv_u32, aarch64_neon_uaddv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddvq_f32, aarch64_neon_faddv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddvq_f64, aarch64_neon_faddv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddvq_s32, aarch64_neon_saddv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddvq_s64, aarch64_neon_saddv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddvq_u32, aarch64_neon_uaddv, AddRetType | Add1ArgType),
+ NEONMAP1(vaddvq_u64, aarch64_neon_uaddv, AddRetType | Add1ArgType),
+ NEONMAP1(vcaged_f64, aarch64_neon_facge, AddRetType | Add1ArgType),
+ NEONMAP1(vcages_f32, aarch64_neon_facge, AddRetType | Add1ArgType),
+ NEONMAP1(vcagtd_f64, aarch64_neon_facgt, AddRetType | Add1ArgType),
+ NEONMAP1(vcagts_f32, aarch64_neon_facgt, AddRetType | Add1ArgType),
+ NEONMAP1(vcaled_f64, aarch64_neon_facge, AddRetType | Add1ArgType),
+ NEONMAP1(vcales_f32, aarch64_neon_facge, AddRetType | Add1ArgType),
+ NEONMAP1(vcaltd_f64, aarch64_neon_facgt, AddRetType | Add1ArgType),
+ NEONMAP1(vcalts_f32, aarch64_neon_facgt, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtad_s64_f64, aarch64_neon_fcvtas, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtad_u64_f64, aarch64_neon_fcvtau, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtas_s32_f32, aarch64_neon_fcvtas, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtas_u32_f32, aarch64_neon_fcvtau, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtd_n_f64_s64, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtd_n_f64_u64, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtd_n_s64_f64, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtd_n_u64_f64, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtmd_s64_f64, aarch64_neon_fcvtms, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtmd_u64_f64, aarch64_neon_fcvtmu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtms_s32_f32, aarch64_neon_fcvtms, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtms_u32_f32, aarch64_neon_fcvtmu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtnd_s64_f64, aarch64_neon_fcvtns, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtnd_u64_f64, aarch64_neon_fcvtnu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtns_s32_f32, aarch64_neon_fcvtns, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtns_u32_f32, aarch64_neon_fcvtnu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtpd_s64_f64, aarch64_neon_fcvtps, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtpd_u64_f64, aarch64_neon_fcvtpu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtps_s32_f32, aarch64_neon_fcvtps, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtps_u32_f32, aarch64_neon_fcvtpu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvts_n_f32_s32, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType),
+ NEONMAP1(vcvts_n_f32_u32, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType),
+ NEONMAP1(vcvts_n_s32_f32, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType),
+ NEONMAP1(vcvts_n_u32_f32, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtxd_f32_f64, aarch64_sisd_fcvtxn, 0),
+ NEONMAP1(vmaxnmv_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxnmvq_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxnmvq_f64, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxv_f32, aarch64_neon_fmaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxv_s32, aarch64_neon_smaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxv_u32, aarch64_neon_umaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxvq_f32, aarch64_neon_fmaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxvq_f64, aarch64_neon_fmaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxvq_s32, aarch64_neon_smaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vmaxvq_u32, aarch64_neon_umaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vminnmv_f32, aarch64_neon_fminnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vminnmvq_f32, aarch64_neon_fminnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vminnmvq_f64, aarch64_neon_fminnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vminv_f32, aarch64_neon_fminv, AddRetType | Add1ArgType),
+ NEONMAP1(vminv_s32, aarch64_neon_sminv, AddRetType | Add1ArgType),
+ NEONMAP1(vminv_u32, aarch64_neon_uminv, AddRetType | Add1ArgType),
+ NEONMAP1(vminvq_f32, aarch64_neon_fminv, AddRetType | Add1ArgType),
+ NEONMAP1(vminvq_f64, aarch64_neon_fminv, AddRetType | Add1ArgType),
+ NEONMAP1(vminvq_s32, aarch64_neon_sminv, AddRetType | Add1ArgType),
+ NEONMAP1(vminvq_u32, aarch64_neon_uminv, AddRetType | Add1ArgType),
+ NEONMAP1(vmull_p64, aarch64_neon_pmull64, 0),
+ NEONMAP1(vmulxd_f64, aarch64_neon_fmulx, Add1ArgType),
+ NEONMAP1(vmulxs_f32, aarch64_neon_fmulx, Add1ArgType),
+ NEONMAP1(vpaddd_s64, aarch64_neon_uaddv, AddRetType | Add1ArgType),
+ NEONMAP1(vpaddd_u64, aarch64_neon_uaddv, AddRetType | Add1ArgType),
+ NEONMAP1(vpmaxnmqd_f64, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vpmaxnms_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vpmaxqd_f64, aarch64_neon_fmaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vpmaxs_f32, aarch64_neon_fmaxv, AddRetType | Add1ArgType),
+ NEONMAP1(vpminnmqd_f64, aarch64_neon_fminnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vpminnms_f32, aarch64_neon_fminnmv, AddRetType | Add1ArgType),
+ NEONMAP1(vpminqd_f64, aarch64_neon_fminv, AddRetType | Add1ArgType),
+ NEONMAP1(vpmins_f32, aarch64_neon_fminv, AddRetType | Add1ArgType),
+ NEONMAP1(vqabsb_s8, aarch64_neon_sqabs, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqabsd_s64, aarch64_neon_sqabs, Add1ArgType),
+ NEONMAP1(vqabsh_s16, aarch64_neon_sqabs, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqabss_s32, aarch64_neon_sqabs, Add1ArgType),
+ NEONMAP1(vqaddb_s8, aarch64_neon_sqadd, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqaddb_u8, aarch64_neon_uqadd, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqaddd_s64, aarch64_neon_sqadd, Add1ArgType),
+ NEONMAP1(vqaddd_u64, aarch64_neon_uqadd, Add1ArgType),
+ NEONMAP1(vqaddh_s16, aarch64_neon_sqadd, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqaddh_u16, aarch64_neon_uqadd, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqadds_s32, aarch64_neon_sqadd, Add1ArgType),
+ NEONMAP1(vqadds_u32, aarch64_neon_uqadd, Add1ArgType),
+ NEONMAP1(vqdmulhh_s16, aarch64_neon_sqdmulh, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqdmulhs_s32, aarch64_neon_sqdmulh, Add1ArgType),
+ NEONMAP1(vqdmullh_s16, aarch64_neon_sqdmull, VectorRet | Use128BitVectors),
+ NEONMAP1(vqdmulls_s32, aarch64_neon_sqdmulls_scalar, 0),
+ NEONMAP1(vqmovnd_s64, aarch64_neon_scalar_sqxtn, AddRetType | Add1ArgType),
+ NEONMAP1(vqmovnd_u64, aarch64_neon_scalar_uqxtn, AddRetType | Add1ArgType),
+ NEONMAP1(vqmovnh_s16, aarch64_neon_sqxtn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqmovnh_u16, aarch64_neon_uqxtn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqmovns_s32, aarch64_neon_sqxtn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqmovns_u32, aarch64_neon_uqxtn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqmovund_s64, aarch64_neon_scalar_sqxtun, AddRetType | Add1ArgType),
+ NEONMAP1(vqmovunh_s16, aarch64_neon_sqxtun, VectorRet | Use64BitVectors),
+ NEONMAP1(vqmovuns_s32, aarch64_neon_sqxtun, VectorRet | Use64BitVectors),
+ NEONMAP1(vqnegb_s8, aarch64_neon_sqneg, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqnegd_s64, aarch64_neon_sqneg, Add1ArgType),
+ NEONMAP1(vqnegh_s16, aarch64_neon_sqneg, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqnegs_s32, aarch64_neon_sqneg, Add1ArgType),
+ NEONMAP1(vqrdmulhh_s16, aarch64_neon_sqrdmulh, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqrdmulhs_s32, aarch64_neon_sqrdmulh, Add1ArgType),
+ NEONMAP1(vqrshlb_s8, aarch64_neon_sqrshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqrshlb_u8, aarch64_neon_uqrshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqrshld_s64, aarch64_neon_sqrshl, Add1ArgType),
+ NEONMAP1(vqrshld_u64, aarch64_neon_uqrshl, Add1ArgType),
+ NEONMAP1(vqrshlh_s16, aarch64_neon_sqrshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqrshlh_u16, aarch64_neon_uqrshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqrshls_s32, aarch64_neon_sqrshl, Add1ArgType),
+ NEONMAP1(vqrshls_u32, aarch64_neon_uqrshl, Add1ArgType),
+ NEONMAP1(vqrshrnd_n_s64, aarch64_neon_sqrshrn, AddRetType),
+ NEONMAP1(vqrshrnd_n_u64, aarch64_neon_uqrshrn, AddRetType),
+ NEONMAP1(vqrshrnh_n_s16, aarch64_neon_sqrshrn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqrshrnh_n_u16, aarch64_neon_uqrshrn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqrshrns_n_s32, aarch64_neon_sqrshrn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqrshrns_n_u32, aarch64_neon_uqrshrn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqrshrund_n_s64, aarch64_neon_sqrshrun, AddRetType),
+ NEONMAP1(vqrshrunh_n_s16, aarch64_neon_sqrshrun, VectorRet | Use64BitVectors),
+ NEONMAP1(vqrshruns_n_s32, aarch64_neon_sqrshrun, VectorRet | Use64BitVectors),
+ NEONMAP1(vqshlb_n_s8, aarch64_neon_sqshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshlb_n_u8, aarch64_neon_uqshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshlb_s8, aarch64_neon_sqshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshlb_u8, aarch64_neon_uqshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshld_s64, aarch64_neon_sqshl, Add1ArgType),
+ NEONMAP1(vqshld_u64, aarch64_neon_uqshl, Add1ArgType),
+ NEONMAP1(vqshlh_n_s16, aarch64_neon_sqshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshlh_n_u16, aarch64_neon_uqshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshlh_s16, aarch64_neon_sqshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshlh_u16, aarch64_neon_uqshl, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshls_n_s32, aarch64_neon_sqshl, Add1ArgType),
+ NEONMAP1(vqshls_n_u32, aarch64_neon_uqshl, Add1ArgType),
+ NEONMAP1(vqshls_s32, aarch64_neon_sqshl, Add1ArgType),
+ NEONMAP1(vqshls_u32, aarch64_neon_uqshl, Add1ArgType),
+ NEONMAP1(vqshlub_n_s8, aarch64_neon_sqshlu, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshluh_n_s16, aarch64_neon_sqshlu, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqshlus_n_s32, aarch64_neon_sqshlu, Add1ArgType),
+ NEONMAP1(vqshrnd_n_s64, aarch64_neon_sqshrn, AddRetType),
+ NEONMAP1(vqshrnd_n_u64, aarch64_neon_uqshrn, AddRetType),
+ NEONMAP1(vqshrnh_n_s16, aarch64_neon_sqshrn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqshrnh_n_u16, aarch64_neon_uqshrn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqshrns_n_s32, aarch64_neon_sqshrn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqshrns_n_u32, aarch64_neon_uqshrn, VectorRet | Use64BitVectors),
+ NEONMAP1(vqshrund_n_s64, aarch64_neon_sqshrun, AddRetType),
+ NEONMAP1(vqshrunh_n_s16, aarch64_neon_sqshrun, VectorRet | Use64BitVectors),
+ NEONMAP1(vqshruns_n_s32, aarch64_neon_sqshrun, VectorRet | Use64BitVectors),
+ NEONMAP1(vqsubb_s8, aarch64_neon_sqsub, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqsubb_u8, aarch64_neon_uqsub, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqsubd_s64, aarch64_neon_sqsub, Add1ArgType),
+ NEONMAP1(vqsubd_u64, aarch64_neon_uqsub, Add1ArgType),
+ NEONMAP1(vqsubh_s16, aarch64_neon_sqsub, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqsubh_u16, aarch64_neon_uqsub, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vqsubs_s32, aarch64_neon_sqsub, Add1ArgType),
+ NEONMAP1(vqsubs_u32, aarch64_neon_uqsub, Add1ArgType),
+ NEONMAP1(vrecped_f64, aarch64_neon_frecpe, Add1ArgType),
+ NEONMAP1(vrecpes_f32, aarch64_neon_frecpe, Add1ArgType),
+ NEONMAP1(vrecpxd_f64, aarch64_neon_frecpx, Add1ArgType),
+ NEONMAP1(vrecpxs_f32, aarch64_neon_frecpx, Add1ArgType),
+ NEONMAP1(vrshld_s64, aarch64_neon_srshl, Add1ArgType),
+ NEONMAP1(vrshld_u64, aarch64_neon_urshl, Add1ArgType),
+ NEONMAP1(vrsqrted_f64, aarch64_neon_frsqrte, Add1ArgType),
+ NEONMAP1(vrsqrtes_f32, aarch64_neon_frsqrte, Add1ArgType),
+ NEONMAP1(vrsqrtsd_f64, aarch64_neon_frsqrts, Add1ArgType),
+ NEONMAP1(vrsqrtss_f32, aarch64_neon_frsqrts, Add1ArgType),
+ NEONMAP1(vsha1cq_u32, aarch64_crypto_sha1c, 0),
+ NEONMAP1(vsha1h_u32, aarch64_crypto_sha1h, 0),
+ NEONMAP1(vsha1mq_u32, aarch64_crypto_sha1m, 0),
+ NEONMAP1(vsha1pq_u32, aarch64_crypto_sha1p, 0),
+ NEONMAP1(vshld_s64, aarch64_neon_sshl, Add1ArgType),
+ NEONMAP1(vshld_u64, aarch64_neon_ushl, Add1ArgType),
+ NEONMAP1(vslid_n_s64, aarch64_neon_vsli, Vectorize1ArgType),
+ NEONMAP1(vslid_n_u64, aarch64_neon_vsli, Vectorize1ArgType),
+ NEONMAP1(vsqaddb_u8, aarch64_neon_usqadd, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vsqaddd_u64, aarch64_neon_usqadd, Add1ArgType),
+ NEONMAP1(vsqaddh_u16, aarch64_neon_usqadd, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vsqadds_u32, aarch64_neon_usqadd, Add1ArgType),
+ NEONMAP1(vsrid_n_s64, aarch64_neon_vsri, Vectorize1ArgType),
+ NEONMAP1(vsrid_n_u64, aarch64_neon_vsri, Vectorize1ArgType),
+ NEONMAP1(vuqaddb_s8, aarch64_neon_suqadd, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vuqaddd_s64, aarch64_neon_suqadd, Add1ArgType),
+ NEONMAP1(vuqaddh_s16, aarch64_neon_suqadd, Vectorize1ArgType | Use64BitVectors),
+ NEONMAP1(vuqadds_s32, aarch64_neon_suqadd, Add1ArgType),
};
#undef NEONMAP0
@@ -2738,10 +2390,9 @@
#undef NEONMAP2
static bool NEONSIMDIntrinsicsProvenSorted = false;
-static bool AArch64SISDIntrinsicInfoProvenSorted = false;
-static bool ARM64SIMDIntrinsicsProvenSorted = false;
-static bool ARM64SISDIntrinsicsProvenSorted = false;
+static bool AArch64SIMDIntrinsicsProvenSorted = false;
+static bool AArch64SISDIntrinsicsProvenSorted = false;
static const NeonIntrinsicInfo *
@@ -2763,7 +2414,7 @@
if (Builtin != IntrinsicMap.end() && Builtin->BuiltinID == BuiltinID)
return Builtin;
- return 0;
+ return nullptr;
}
Function *CodeGenFunction::LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
@@ -2868,169 +2519,6 @@
return CGF.Builder.CreateBitCast(Result, ResultType, s);
}
-static Value *EmitAArch64ScalarBuiltinExpr(CodeGenFunction &CGF,
- const NeonIntrinsicInfo &SISDInfo,
- const CallExpr *E) {
- unsigned BuiltinID = SISDInfo.BuiltinID;
- unsigned int Int = SISDInfo.LLVMIntrinsic;
- const char *s = SISDInfo.NameHint;
-
- SmallVector<Value *, 4> Ops;
- for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) {
- Ops.push_back(CGF.EmitScalarExpr(E->getArg(i)));
- }
-
- // AArch64 scalar builtins are not overloaded, they do not have an extra
- // argument that specifies the vector type, need to handle each case.
- switch (BuiltinID) {
- default: break;
- case NEON::BI__builtin_neon_vdups_lane_f32:
- case NEON::BI__builtin_neon_vdupd_lane_f64:
- case NEON::BI__builtin_neon_vdups_laneq_f32:
- case NEON::BI__builtin_neon_vdupd_laneq_f64: {
- return CGF.Builder.CreateExtractElement(Ops[0], Ops[1], "vdup_lane");
- }
- case NEON::BI__builtin_neon_vdupb_lane_i8:
- case NEON::BI__builtin_neon_vduph_lane_i16:
- case NEON::BI__builtin_neon_vdups_lane_i32:
- case NEON::BI__builtin_neon_vdupd_lane_i64:
- case NEON::BI__builtin_neon_vdupb_laneq_i8:
- case NEON::BI__builtin_neon_vduph_laneq_i16:
- case NEON::BI__builtin_neon_vdups_laneq_i32:
- case NEON::BI__builtin_neon_vdupd_laneq_i64: {
- // The backend treats Neon scalar types as v1ix types
- // So we want to dup lane from any vector to v1ix vector
- // with shufflevector
- s = "vdup_lane";
- Value* SV = llvm::ConstantVector::getSplat(1, cast<ConstantInt>(Ops[1]));
- Value *Result = CGF.Builder.CreateShuffleVector(Ops[0], Ops[0], SV, s);
- llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
- // AArch64 intrinsic one-element vector type cast to
- // scalar type expected by the builtin
- return CGF.Builder.CreateBitCast(Result, Ty, s);
- }
- case NEON::BI__builtin_neon_vqdmlalh_lane_s16 :
- case NEON::BI__builtin_neon_vqdmlalh_laneq_s16 :
- case NEON::BI__builtin_neon_vqdmlals_lane_s32 :
- case NEON::BI__builtin_neon_vqdmlals_laneq_s32 :
- case NEON::BI__builtin_neon_vqdmlslh_lane_s16 :
- case NEON::BI__builtin_neon_vqdmlslh_laneq_s16 :
- case NEON::BI__builtin_neon_vqdmlsls_lane_s32 :
- case NEON::BI__builtin_neon_vqdmlsls_laneq_s32 : {
- Int = Intrinsic::arm_neon_vqadds;
- if (BuiltinID == NEON::BI__builtin_neon_vqdmlslh_lane_s16 ||
- BuiltinID == NEON::BI__builtin_neon_vqdmlslh_laneq_s16 ||
- BuiltinID == NEON::BI__builtin_neon_vqdmlsls_lane_s32 ||
- BuiltinID == NEON::BI__builtin_neon_vqdmlsls_laneq_s32) {
- Int = Intrinsic::arm_neon_vqsubs;
- }
- // create vqdmull call with b * c[i]
- llvm::Type *Ty = CGF.ConvertType(E->getArg(1)->getType());
- llvm::VectorType *OpVTy = llvm::VectorType::get(Ty, 1);
- Ty = CGF.ConvertType(E->getArg(0)->getType());
- llvm::VectorType *ResVTy = llvm::VectorType::get(Ty, 1);
- Value *F = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, ResVTy);
- Value *V = UndefValue::get(OpVTy);
- llvm::Constant *CI = ConstantInt::get(CGF.Int32Ty, 0);
- SmallVector<Value *, 2> MulOps;
- MulOps.push_back(Ops[1]);
- MulOps.push_back(Ops[2]);
- MulOps[0] = CGF.Builder.CreateInsertElement(V, MulOps[0], CI);
- MulOps[1] = CGF.Builder.CreateExtractElement(MulOps[1], Ops[3], "extract");
- MulOps[1] = CGF.Builder.CreateInsertElement(V, MulOps[1], CI);
- Value *MulRes = CGF.Builder.CreateCall2(F, MulOps[0], MulOps[1]);
- // create vqadds call with a +/- vqdmull result
- F = CGF.CGM.getIntrinsic(Int, ResVTy);
- SmallVector<Value *, 2> AddOps;
- AddOps.push_back(Ops[0]);
- AddOps.push_back(MulRes);
- V = UndefValue::get(ResVTy);
- AddOps[0] = CGF.Builder.CreateInsertElement(V, AddOps[0], CI);
- Value *AddRes = CGF.Builder.CreateCall2(F, AddOps[0], AddOps[1]);
- return CGF.Builder.CreateBitCast(AddRes, Ty);
- }
- case NEON::BI__builtin_neon_vfmas_lane_f32:
- case NEON::BI__builtin_neon_vfmas_laneq_f32:
- case NEON::BI__builtin_neon_vfmad_lane_f64:
- case NEON::BI__builtin_neon_vfmad_laneq_f64: {
- llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
- Value *F = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty);
- Ops[2] = CGF.Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
- return CGF.Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
- }
- // Scalar Floating-point Multiply Extended
- case NEON::BI__builtin_neon_vmulxs_f32:
- case NEON::BI__builtin_neon_vmulxd_f64: {
- Int = Intrinsic::aarch64_neon_vmulx;
- llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
- return CGF.EmitNeonCall(CGF.CGM.getIntrinsic(Int, Ty), Ops, "vmulx");
- }
- case NEON::BI__builtin_neon_vmul_n_f64: {
- // v1f64 vmul_n_f64 should be mapped to Neon scalar mul lane
- llvm::Type *VTy = GetNeonType(&CGF,
- NeonTypeFlags(NeonTypeFlags::Float64, false, false));
- Ops[0] = CGF.Builder.CreateBitCast(Ops[0], VTy);
- llvm::Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, 0);
- Ops[0] = CGF.Builder.CreateExtractElement(Ops[0], Idx, "extract");
- Value *Result = CGF.Builder.CreateFMul(Ops[0], Ops[1]);
- return CGF.Builder.CreateBitCast(Result, VTy);
- }
- case NEON::BI__builtin_neon_vget_lane_i8:
- case NEON::BI__builtin_neon_vget_lane_i16:
- case NEON::BI__builtin_neon_vget_lane_i32:
- case NEON::BI__builtin_neon_vget_lane_i64:
- case NEON::BI__builtin_neon_vget_lane_f32:
- case NEON::BI__builtin_neon_vget_lane_f64:
- case NEON::BI__builtin_neon_vgetq_lane_i8:
- case NEON::BI__builtin_neon_vgetq_lane_i16:
- case NEON::BI__builtin_neon_vgetq_lane_i32:
- case NEON::BI__builtin_neon_vgetq_lane_i64:
- case NEON::BI__builtin_neon_vgetq_lane_f32:
- case NEON::BI__builtin_neon_vgetq_lane_f64:
- return CGF.EmitARMBuiltinExpr(NEON::BI__builtin_neon_vget_lane_i8, E);
- case NEON::BI__builtin_neon_vset_lane_i8:
- case NEON::BI__builtin_neon_vset_lane_i16:
- case NEON::BI__builtin_neon_vset_lane_i32:
- case NEON::BI__builtin_neon_vset_lane_i64:
- case NEON::BI__builtin_neon_vset_lane_f32:
- case NEON::BI__builtin_neon_vset_lane_f64:
- case NEON::BI__builtin_neon_vsetq_lane_i8:
- case NEON::BI__builtin_neon_vsetq_lane_i16:
- case NEON::BI__builtin_neon_vsetq_lane_i32:
- case NEON::BI__builtin_neon_vsetq_lane_i64:
- case NEON::BI__builtin_neon_vsetq_lane_f32:
- case NEON::BI__builtin_neon_vsetq_lane_f64:
- return CGF.EmitARMBuiltinExpr(NEON::BI__builtin_neon_vset_lane_i8, E);
-
- case NEON::BI__builtin_neon_vceqzd_s64:
- case NEON::BI__builtin_neon_vceqzd_u64:
- case NEON::BI__builtin_neon_vcgezd_s64:
- case NEON::BI__builtin_neon_vcgtzd_s64:
- case NEON::BI__builtin_neon_vclezd_s64:
- case NEON::BI__builtin_neon_vcltzd_s64:
- // Add implicit zero operand.
- Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType()));
- break;
- case NEON::BI__builtin_neon_vceqzs_f32:
- case NEON::BI__builtin_neon_vceqzd_f64:
- case NEON::BI__builtin_neon_vcgezs_f32:
- case NEON::BI__builtin_neon_vcgezd_f64:
- case NEON::BI__builtin_neon_vcgtzs_f32:
- case NEON::BI__builtin_neon_vcgtzd_f64:
- case NEON::BI__builtin_neon_vclezs_f32:
- case NEON::BI__builtin_neon_vclezd_f64:
- case NEON::BI__builtin_neon_vcltzs_f32:
- case NEON::BI__builtin_neon_vcltzd_f64:
- // Add implicit zero operand.
- Ops.push_back(llvm::Constant::getNullValue(CGF.FloatTy));
- break;
- }
-
- // It didn't need any handling specific to the AArch64 backend, so defer to
- // common code.
- return EmitCommonNeonSISDBuiltinExpr(CGF, SISDInfo, Ops, E);
-}
-
Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
unsigned BuiltinID, unsigned LLVMIntrinsic, unsigned AltLLVMIntrinsic,
const char *NameHint, unsigned Modifier, const CallExpr *E,
@@ -3039,7 +2527,7 @@
llvm::APSInt NeonTypeConst;
const Expr *Arg = E->getArg(E->getNumArgs() - 1);
if (!Arg->isIntegerConstantExpr(NeonTypeConst, getContext()))
- return 0;
+ return nullptr;
// Determine the type of this overloaded NEON intrinsic.
NeonTypeFlags Type(NeonTypeConst.getZExtValue());
@@ -3049,7 +2537,7 @@
llvm::VectorType *VTy = GetNeonType(this, Type);
llvm::Type *Ty = VTy;
if (!Ty)
- return 0;
+ return nullptr;
unsigned Int = LLVMIntrinsic;
if ((Modifier & UnsignedAlts) && !Usgn)
@@ -3396,7 +2884,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Value *SV = 0;
+ Value *SV = nullptr;
for (unsigned vi = 0; vi != 2; ++vi) {
SmallVector<Constant*, 16> Indices;
@@ -3425,7 +2913,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Value *SV = 0;
+ Value *SV = nullptr;
for (unsigned vi = 0; vi != 2; ++vi) {
SmallVector<Constant*, 16> Indices;
@@ -3444,7 +2932,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Value *SV = 0;
+ Value *SV = nullptr;
for (unsigned vi = 0; vi != 2; ++vi) {
SmallVector<Constant*, 16> Indices;
@@ -3533,799 +3021,33 @@
return CGF.EmitNeonCall(TblF, TblOps, Name);
}
-static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF,
- unsigned BuiltinID,
- const CallExpr *E) {
- unsigned int Int = 0;
- const char *s = NULL;
-
+Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ unsigned HintID = static_cast<unsigned>(-1);
switch (BuiltinID) {
- default:
- return 0;
- case NEON::BI__builtin_neon_vtbl1_v:
- case NEON::BI__builtin_neon_vqtbl1_v:
- case NEON::BI__builtin_neon_vqtbl1q_v:
- case NEON::BI__builtin_neon_vtbl2_v:
- case NEON::BI__builtin_neon_vqtbl2_v:
- case NEON::BI__builtin_neon_vqtbl2q_v:
- case NEON::BI__builtin_neon_vtbl3_v:
- case NEON::BI__builtin_neon_vqtbl3_v:
- case NEON::BI__builtin_neon_vqtbl3q_v:
- case NEON::BI__builtin_neon_vtbl4_v:
- case NEON::BI__builtin_neon_vqtbl4_v:
- case NEON::BI__builtin_neon_vqtbl4q_v:
- case NEON::BI__builtin_neon_vtbx1_v:
- case NEON::BI__builtin_neon_vqtbx1_v:
- case NEON::BI__builtin_neon_vqtbx1q_v:
- case NEON::BI__builtin_neon_vtbx2_v:
- case NEON::BI__builtin_neon_vqtbx2_v:
- case NEON::BI__builtin_neon_vqtbx2q_v:
- case NEON::BI__builtin_neon_vtbx3_v:
- case NEON::BI__builtin_neon_vqtbx3_v:
- case NEON::BI__builtin_neon_vqtbx3q_v:
- case NEON::BI__builtin_neon_vtbx4_v:
- case NEON::BI__builtin_neon_vqtbx4_v:
- case NEON::BI__builtin_neon_vqtbx4q_v:
+ default: break;
+ case ARM::BI__yield:
+ HintID = 1;
+ break;
+ case ARM::BI__wfe:
+ HintID = 2;
+ break;
+ case ARM::BI__wfi:
+ HintID = 3;
+ break;
+ case ARM::BI__sev:
+ HintID = 4;
+ break;
+ case ARM::BI__sevl:
+ HintID = 5;
break;
}
- assert(E->getNumArgs() >= 3);
-
- // Get the last argument, which specifies the vector type.
- llvm::APSInt Result;
- const Expr *Arg = E->getArg(E->getNumArgs() - 1);
- if (!Arg->isIntegerConstantExpr(Result, CGF.getContext()))
- return 0;
-
- // Determine the type of this overloaded NEON intrinsic.
- NeonTypeFlags Type(Result.getZExtValue());
- llvm::VectorType *VTy = GetNeonType(&CGF, Type);
- llvm::Type *Ty = VTy;
- if (!Ty)
- return 0;
-
- SmallVector<Value *, 4> Ops;
- for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
- Ops.push_back(CGF.EmitScalarExpr(E->getArg(i)));
+ if (HintID != static_cast<unsigned>(-1)) {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_hint);
+ return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID));
}
- unsigned nElts = VTy->getNumElements();
-
- // AArch64 scalar builtins are not overloaded, they do not have an extra
- // argument that specifies the vector type, need to handle each case.
- SmallVector<Value *, 2> TblOps;
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vtbl1_v: {
- TblOps.push_back(Ops[0]);
- return packTBLDVectorList(CGF, TblOps, 0, Ops[1], Ty,
- Intrinsic::aarch64_neon_vtbl1, "vtbl1");
- }
- case NEON::BI__builtin_neon_vtbl2_v: {
- TblOps.push_back(Ops[0]);
- TblOps.push_back(Ops[1]);
- return packTBLDVectorList(CGF, TblOps, 0, Ops[2], Ty,
- Intrinsic::aarch64_neon_vtbl1, "vtbl1");
- }
- case NEON::BI__builtin_neon_vtbl3_v: {
- TblOps.push_back(Ops[0]);
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- return packTBLDVectorList(CGF, TblOps, 0, Ops[3], Ty,
- Intrinsic::aarch64_neon_vtbl2, "vtbl2");
- }
- case NEON::BI__builtin_neon_vtbl4_v: {
- TblOps.push_back(Ops[0]);
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- TblOps.push_back(Ops[3]);
- return packTBLDVectorList(CGF, TblOps, 0, Ops[4], Ty,
- Intrinsic::aarch64_neon_vtbl2, "vtbl2");
- }
- case NEON::BI__builtin_neon_vtbx1_v: {
- TblOps.push_back(Ops[1]);
- Value *TblRes = packTBLDVectorList(CGF, TblOps, 0, Ops[2], Ty,
- Intrinsic::aarch64_neon_vtbl1, "vtbl1");
-
- llvm::Constant *Eight = ConstantInt::get(VTy->getElementType(), 8);
- Value* EightV = llvm::ConstantVector::getSplat(nElts, Eight);
- Value *CmpRes = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[2], EightV);
- CmpRes = CGF.Builder.CreateSExt(CmpRes, Ty);
-
- SmallVector<Value *, 4> BslOps;
- BslOps.push_back(CmpRes);
- BslOps.push_back(Ops[0]);
- BslOps.push_back(TblRes);
- Function *BslF = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vbsl, Ty);
- return CGF.EmitNeonCall(BslF, BslOps, "vbsl");
- }
- case NEON::BI__builtin_neon_vtbx2_v: {
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[3], Ty,
- Intrinsic::aarch64_neon_vtbx1, "vtbx1");
- }
- case NEON::BI__builtin_neon_vtbx3_v: {
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- TblOps.push_back(Ops[3]);
- Value *TblRes = packTBLDVectorList(CGF, TblOps, 0, Ops[4], Ty,
- Intrinsic::aarch64_neon_vtbl2, "vtbl2");
-
- llvm::Constant *TwentyFour = ConstantInt::get(VTy->getElementType(), 24);
- Value* TwentyFourV = llvm::ConstantVector::getSplat(nElts, TwentyFour);
- Value *CmpRes = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[4],
- TwentyFourV);
- CmpRes = CGF.Builder.CreateSExt(CmpRes, Ty);
-
- SmallVector<Value *, 4> BslOps;
- BslOps.push_back(CmpRes);
- BslOps.push_back(Ops[0]);
- BslOps.push_back(TblRes);
- Function *BslF = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vbsl, Ty);
- return CGF.EmitNeonCall(BslF, BslOps, "vbsl");
- }
- case NEON::BI__builtin_neon_vtbx4_v: {
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- TblOps.push_back(Ops[3]);
- TblOps.push_back(Ops[4]);
- return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[5], Ty,
- Intrinsic::aarch64_neon_vtbx2, "vtbx2");
- }
- case NEON::BI__builtin_neon_vqtbl1_v:
- case NEON::BI__builtin_neon_vqtbl1q_v:
- Int = Intrinsic::aarch64_neon_vtbl1; s = "vtbl1"; break;
- case NEON::BI__builtin_neon_vqtbl2_v:
- case NEON::BI__builtin_neon_vqtbl2q_v: {
- Int = Intrinsic::aarch64_neon_vtbl2; s = "vtbl2"; break;
- case NEON::BI__builtin_neon_vqtbl3_v:
- case NEON::BI__builtin_neon_vqtbl3q_v:
- Int = Intrinsic::aarch64_neon_vtbl3; s = "vtbl3"; break;
- case NEON::BI__builtin_neon_vqtbl4_v:
- case NEON::BI__builtin_neon_vqtbl4q_v:
- Int = Intrinsic::aarch64_neon_vtbl4; s = "vtbl4"; break;
- case NEON::BI__builtin_neon_vqtbx1_v:
- case NEON::BI__builtin_neon_vqtbx1q_v:
- Int = Intrinsic::aarch64_neon_vtbx1; s = "vtbx1"; break;
- case NEON::BI__builtin_neon_vqtbx2_v:
- case NEON::BI__builtin_neon_vqtbx2q_v:
- Int = Intrinsic::aarch64_neon_vtbx2; s = "vtbx2"; break;
- case NEON::BI__builtin_neon_vqtbx3_v:
- case NEON::BI__builtin_neon_vqtbx3q_v:
- Int = Intrinsic::aarch64_neon_vtbx3; s = "vtbx3"; break;
- case NEON::BI__builtin_neon_vqtbx4_v:
- case NEON::BI__builtin_neon_vqtbx4q_v:
- Int = Intrinsic::aarch64_neon_vtbx4; s = "vtbx4"; break;
- }
- }
-
- if (!Int)
- return 0;
-
- Function *F = CGF.CGM.getIntrinsic(Int, Ty);
- return CGF.EmitNeonCall(F, Ops, s);
-}
-
-Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
- const CallExpr *E) {
-
- // Process AArch64 scalar builtins
- llvm::ArrayRef<NeonIntrinsicInfo> SISDInfo(AArch64SISDIntrinsicInfo);
- const NeonIntrinsicInfo *Builtin = findNeonIntrinsicInMap(
- SISDInfo, BuiltinID, AArch64SISDIntrinsicInfoProvenSorted);
-
- if (Builtin) {
- Value *Result = EmitAArch64ScalarBuiltinExpr(*this, *Builtin, E);
- assert(Result && "SISD intrinsic should have been handled");
- return Result;
- }
-
- // Process AArch64 table lookup builtins
- if (Value *Result = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E))
- return Result;
-
- if (BuiltinID == AArch64::BI__clear_cache) {
- assert(E->getNumArgs() == 2 &&
- "Variadic __clear_cache slipped through on AArch64");
-
- const FunctionDecl *FD = E->getDirectCallee();
- SmallVector<Value *, 2> Ops;
- for (unsigned i = 0; i < E->getNumArgs(); i++)
- Ops.push_back(EmitScalarExpr(E->getArg(i)));
- llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType());
- llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
- StringRef Name = FD->getName();
- return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops);
- }
-
- SmallVector<Value *, 4> Ops;
- llvm::Value *Align = 0; // Alignment for load/store
-
- if (BuiltinID == NEON::BI__builtin_neon_vldrq_p128) {
- Value *Op = EmitScalarExpr(E->getArg(0));
- unsigned addressSpace =
- cast<llvm::PointerType>(Op->getType())->getAddressSpace();
- llvm::Type *Ty = llvm::Type::getFP128PtrTy(getLLVMContext(), addressSpace);
- Op = Builder.CreateBitCast(Op, Ty);
- Op = Builder.CreateLoad(Op);
- Ty = llvm::Type::getIntNTy(getLLVMContext(), 128);
- return Builder.CreateBitCast(Op, Ty);
- }
- if (BuiltinID == NEON::BI__builtin_neon_vstrq_p128) {
- Value *Op0 = EmitScalarExpr(E->getArg(0));
- unsigned addressSpace =
- cast<llvm::PointerType>(Op0->getType())->getAddressSpace();
- llvm::Type *PTy = llvm::Type::getFP128PtrTy(getLLVMContext(), addressSpace);
- Op0 = Builder.CreateBitCast(Op0, PTy);
- Value *Op1 = EmitScalarExpr(E->getArg(1));
- llvm::Type *Ty = llvm::Type::getFP128Ty(getLLVMContext());
- Op1 = Builder.CreateBitCast(Op1, Ty);
- return Builder.CreateStore(Op1, Op0);
- }
- for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
- if (i == 0) {
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vld1_v:
- case NEON::BI__builtin_neon_vld1q_v:
- case NEON::BI__builtin_neon_vst1_v:
- case NEON::BI__builtin_neon_vst1q_v:
- case NEON::BI__builtin_neon_vst2_v:
- case NEON::BI__builtin_neon_vst2q_v:
- case NEON::BI__builtin_neon_vst3_v:
- case NEON::BI__builtin_neon_vst3q_v:
- case NEON::BI__builtin_neon_vst4_v:
- case NEON::BI__builtin_neon_vst4q_v:
- case NEON::BI__builtin_neon_vst1_x2_v:
- case NEON::BI__builtin_neon_vst1q_x2_v:
- case NEON::BI__builtin_neon_vst1_x3_v:
- case NEON::BI__builtin_neon_vst1q_x3_v:
- case NEON::BI__builtin_neon_vst1_x4_v:
- case NEON::BI__builtin_neon_vst1q_x4_v:
- // Handle ld1/st1 lane in this function a little different from ARM.
- case NEON::BI__builtin_neon_vld1_lane_v:
- case NEON::BI__builtin_neon_vld1q_lane_v:
- case NEON::BI__builtin_neon_vst1_lane_v:
- case NEON::BI__builtin_neon_vst1q_lane_v:
- case NEON::BI__builtin_neon_vst2_lane_v:
- case NEON::BI__builtin_neon_vst2q_lane_v:
- case NEON::BI__builtin_neon_vst3_lane_v:
- case NEON::BI__builtin_neon_vst3q_lane_v:
- case NEON::BI__builtin_neon_vst4_lane_v:
- case NEON::BI__builtin_neon_vst4q_lane_v:
- case NEON::BI__builtin_neon_vld1_dup_v:
- case NEON::BI__builtin_neon_vld1q_dup_v:
- // Get the alignment for the argument in addition to the value;
- // we'll use it later.
- std::pair<llvm::Value *, unsigned> Src =
- EmitPointerWithAlignment(E->getArg(0));
- Ops.push_back(Src.first);
- Align = Builder.getInt32(Src.second);
- continue;
- }
- }
- if (i == 1) {
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vld2_v:
- case NEON::BI__builtin_neon_vld2q_v:
- case NEON::BI__builtin_neon_vld3_v:
- case NEON::BI__builtin_neon_vld3q_v:
- case NEON::BI__builtin_neon_vld4_v:
- case NEON::BI__builtin_neon_vld4q_v:
- case NEON::BI__builtin_neon_vld1_x2_v:
- case NEON::BI__builtin_neon_vld1q_x2_v:
- case NEON::BI__builtin_neon_vld1_x3_v:
- case NEON::BI__builtin_neon_vld1q_x3_v:
- case NEON::BI__builtin_neon_vld1_x4_v:
- case NEON::BI__builtin_neon_vld1q_x4_v:
- // Handle ld1/st1 dup lane in this function a little different from ARM.
- case NEON::BI__builtin_neon_vld2_dup_v:
- case NEON::BI__builtin_neon_vld2q_dup_v:
- case NEON::BI__builtin_neon_vld3_dup_v:
- case NEON::BI__builtin_neon_vld3q_dup_v:
- case NEON::BI__builtin_neon_vld4_dup_v:
- case NEON::BI__builtin_neon_vld4q_dup_v:
- case NEON::BI__builtin_neon_vld2_lane_v:
- case NEON::BI__builtin_neon_vld2q_lane_v:
- case NEON::BI__builtin_neon_vld3_lane_v:
- case NEON::BI__builtin_neon_vld3q_lane_v:
- case NEON::BI__builtin_neon_vld4_lane_v:
- case NEON::BI__builtin_neon_vld4q_lane_v:
- // Get the alignment for the argument in addition to the value;
- // we'll use it later.
- std::pair<llvm::Value *, unsigned> Src =
- EmitPointerWithAlignment(E->getArg(1));
- Ops.push_back(Src.first);
- Align = Builder.getInt32(Src.second);
- continue;
- }
- }
- Ops.push_back(EmitScalarExpr(E->getArg(i)));
- }
-
- // Get the last argument, which specifies the vector type.
- llvm::APSInt Result;
- const Expr *Arg = E->getArg(E->getNumArgs() - 1);
- if (!Arg->isIntegerConstantExpr(Result, getContext()))
- return 0;
-
- // Determine the type of this overloaded NEON intrinsic.
- NeonTypeFlags Type(Result.getZExtValue());
- bool usgn = Type.isUnsigned();
- bool quad = Type.isQuad();
-
- llvm::VectorType *VTy = GetNeonType(this, Type);
- llvm::Type *Ty = VTy;
- if (!Ty)
- return 0;
-
-
- // Many NEON builtins have identical semantics and uses in ARM and
- // AArch64. Emit these in a single function.
- llvm::ArrayRef<NeonIntrinsicInfo> IntrinsicMap(ARMSIMDIntrinsicMap);
- Builtin = findNeonIntrinsicInMap(IntrinsicMap, BuiltinID,
- NEONSIMDIntrinsicsProvenSorted);
- if (Builtin)
- return EmitCommonNeonBuiltinExpr(
- Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic,
- Builtin->NameHint, Builtin->TypeModifier, E, Ops, Align);
-
- unsigned Int;
- switch (BuiltinID) {
- default:
- return 0;
-
- // AArch64 builtins mapping to legacy ARM v7 builtins.
- // FIXME: the mapped builtins listed correspond to what has been tested
- // in aarch64-neon-intrinsics.c so far.
-
- // Shift by immediate
- case NEON::BI__builtin_neon_vrshr_n_v:
- case NEON::BI__builtin_neon_vrshrq_n_v:
- Int = usgn ? Intrinsic::aarch64_neon_vurshr
- : Intrinsic::aarch64_neon_vsrshr;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n");
- case NEON::BI__builtin_neon_vsra_n_v:
- if (VTy->getElementType()->isIntegerTy(64)) {
- Int = usgn ? Intrinsic::aarch64_neon_vsradu_n
- : Intrinsic::aarch64_neon_vsrads_n;
- return EmitNeonCall(CGM.getIntrinsic(Int), Ops, "vsra_n");
- }
- return EmitARMBuiltinExpr(NEON::BI__builtin_neon_vsra_n_v, E);
- case NEON::BI__builtin_neon_vsraq_n_v:
- return EmitARMBuiltinExpr(NEON::BI__builtin_neon_vsraq_n_v, E);
- case NEON::BI__builtin_neon_vrsra_n_v:
- if (VTy->getElementType()->isIntegerTy(64)) {
- Int = usgn ? Intrinsic::aarch64_neon_vrsradu_n
- : Intrinsic::aarch64_neon_vrsrads_n;
- return EmitNeonCall(CGM.getIntrinsic(Int), Ops, "vrsra_n");
- }
- // fall through
- case NEON::BI__builtin_neon_vrsraq_n_v: {
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
- Int = usgn ? Intrinsic::aarch64_neon_vurshr
- : Intrinsic::aarch64_neon_vsrshr;
- Ops[1] = Builder.CreateCall2(CGM.getIntrinsic(Int, Ty), Ops[1], Ops[2]);
- return Builder.CreateAdd(Ops[0], Ops[1], "vrsra_n");
- }
- case NEON::BI__builtin_neon_vqshlu_n_v:
- case NEON::BI__builtin_neon_vqshluq_n_v:
- Int = Intrinsic::aarch64_neon_vsqshlu;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshlu_n");
- case NEON::BI__builtin_neon_vsri_n_v:
- case NEON::BI__builtin_neon_vsriq_n_v:
- Int = Intrinsic::aarch64_neon_vsri;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsri_n");
- case NEON::BI__builtin_neon_vsli_n_v:
- case NEON::BI__builtin_neon_vsliq_n_v:
- Int = Intrinsic::aarch64_neon_vsli;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsli_n");
- case NEON::BI__builtin_neon_vqshrun_n_v:
- Int = Intrinsic::aarch64_neon_vsqshrun;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrun_n");
- case NEON::BI__builtin_neon_vrshrn_n_v:
- Int = Intrinsic::aarch64_neon_vrshrn;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshrn_n");
- case NEON::BI__builtin_neon_vqrshrun_n_v:
- Int = Intrinsic::aarch64_neon_vsqrshrun;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrun_n");
- case NEON::BI__builtin_neon_vqshrn_n_v:
- Int = usgn ? Intrinsic::aarch64_neon_vuqshrn
- : Intrinsic::aarch64_neon_vsqshrn;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n");
- case NEON::BI__builtin_neon_vqrshrn_n_v:
- Int = usgn ? Intrinsic::aarch64_neon_vuqrshrn
- : Intrinsic::aarch64_neon_vsqrshrn;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n");
-
- // Convert
- case NEON::BI__builtin_neon_vcvt_n_f64_v:
- case NEON::BI__builtin_neon_vcvtq_n_f64_v: {
- llvm::Type *FloatTy =
- GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
- llvm::Type *Tys[2] = { FloatTy, Ty };
- Int = usgn ? Intrinsic::arm_neon_vcvtfxu2fp
- : Intrinsic::arm_neon_vcvtfxs2fp;
- Function *F = CGM.getIntrinsic(Int, Tys);
- return EmitNeonCall(F, Ops, "vcvt_n");
- }
-
- // Load/Store
- case NEON::BI__builtin_neon_vld1_x2_v:
- case NEON::BI__builtin_neon_vld1q_x2_v:
- case NEON::BI__builtin_neon_vld1_x3_v:
- case NEON::BI__builtin_neon_vld1q_x3_v:
- case NEON::BI__builtin_neon_vld1_x4_v:
- case NEON::BI__builtin_neon_vld1q_x4_v: {
- unsigned Int;
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vld1_x2_v:
- case NEON::BI__builtin_neon_vld1q_x2_v:
- Int = Intrinsic::aarch64_neon_vld1x2;
- break;
- case NEON::BI__builtin_neon_vld1_x3_v:
- case NEON::BI__builtin_neon_vld1q_x3_v:
- Int = Intrinsic::aarch64_neon_vld1x3;
- break;
- case NEON::BI__builtin_neon_vld1_x4_v:
- case NEON::BI__builtin_neon_vld1q_x4_v:
- Int = Intrinsic::aarch64_neon_vld1x4;
- break;
- }
- Function *F = CGM.getIntrinsic(Int, Ty);
- Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld1xN");
- Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
- }
- case NEON::BI__builtin_neon_vst1_x2_v:
- case NEON::BI__builtin_neon_vst1q_x2_v:
- case NEON::BI__builtin_neon_vst1_x3_v:
- case NEON::BI__builtin_neon_vst1q_x3_v:
- case NEON::BI__builtin_neon_vst1_x4_v:
- case NEON::BI__builtin_neon_vst1q_x4_v: {
- Ops.push_back(Align);
- unsigned Int;
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vst1_x2_v:
- case NEON::BI__builtin_neon_vst1q_x2_v:
- Int = Intrinsic::aarch64_neon_vst1x2;
- break;
- case NEON::BI__builtin_neon_vst1_x3_v:
- case NEON::BI__builtin_neon_vst1q_x3_v:
- Int = Intrinsic::aarch64_neon_vst1x3;
- break;
- case NEON::BI__builtin_neon_vst1_x4_v:
- case NEON::BI__builtin_neon_vst1q_x4_v:
- Int = Intrinsic::aarch64_neon_vst1x4;
- break;
- }
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "");
- }
- case NEON::BI__builtin_neon_vld1_lane_v:
- case NEON::BI__builtin_neon_vld1q_lane_v: {
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
- Ty = llvm::PointerType::getUnqual(VTy->getElementType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- LoadInst *Ld = Builder.CreateLoad(Ops[0]);
- Ld->setAlignment(cast<ConstantInt>(Align)->getZExtValue());
- return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane");
- }
- case NEON::BI__builtin_neon_vst1_lane_v:
- case NEON::BI__builtin_neon_vst1q_lane_v: {
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
- Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
- Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- StoreInst *St =
- Builder.CreateStore(Ops[1], Builder.CreateBitCast(Ops[0], Ty));
- St->setAlignment(cast<ConstantInt>(Align)->getZExtValue());
- return St;
- }
- case NEON::BI__builtin_neon_vld2_dup_v:
- case NEON::BI__builtin_neon_vld2q_dup_v:
- case NEON::BI__builtin_neon_vld3_dup_v:
- case NEON::BI__builtin_neon_vld3q_dup_v:
- case NEON::BI__builtin_neon_vld4_dup_v:
- case NEON::BI__builtin_neon_vld4q_dup_v: {
- // Handle 64-bit x 1 elements as a special-case. There is no "dup" needed.
- if (VTy->getElementType()->getPrimitiveSizeInBits() == 64 &&
- VTy->getNumElements() == 1) {
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vld2_dup_v:
- Int = Intrinsic::arm_neon_vld2;
- break;
- case NEON::BI__builtin_neon_vld3_dup_v:
- Int = Intrinsic::arm_neon_vld3;
- break;
- case NEON::BI__builtin_neon_vld4_dup_v:
- Int = Intrinsic::arm_neon_vld4;
- break;
- default:
- llvm_unreachable("unknown vld_dup intrinsic?");
- }
- Function *F = CGM.getIntrinsic(Int, Ty);
- Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld_dup");
- Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
- }
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vld2_dup_v:
- case NEON::BI__builtin_neon_vld2q_dup_v:
- Int = Intrinsic::arm_neon_vld2lane;
- break;
- case NEON::BI__builtin_neon_vld3_dup_v:
- case NEON::BI__builtin_neon_vld3q_dup_v:
- Int = Intrinsic::arm_neon_vld3lane;
- break;
- case NEON::BI__builtin_neon_vld4_dup_v:
- case NEON::BI__builtin_neon_vld4q_dup_v:
- Int = Intrinsic::arm_neon_vld4lane;
- break;
- }
- Function *F = CGM.getIntrinsic(Int, Ty);
- llvm::StructType *STy = cast<llvm::StructType>(F->getReturnType());
-
- SmallVector<Value *, 6> Args;
- Args.push_back(Ops[1]);
- Args.append(STy->getNumElements(), UndefValue::get(Ty));
-
- llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
- Args.push_back(CI);
- Args.push_back(Align);
-
- Ops[1] = Builder.CreateCall(F, Args, "vld_dup");
- // splat lane 0 to all elts in each vector of the result.
- for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- Value *Val = Builder.CreateExtractValue(Ops[1], i);
- Value *Elt = Builder.CreateBitCast(Val, Ty);
- Elt = EmitNeonSplat(Elt, CI);
- Elt = Builder.CreateBitCast(Elt, Val->getType());
- Ops[1] = Builder.CreateInsertValue(Ops[1], Elt, i);
- }
- Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
- }
-
- case NEON::BI__builtin_neon_vmul_lane_v:
- case NEON::BI__builtin_neon_vmul_laneq_v: {
- // v1f64 vmul_lane should be mapped to Neon scalar mul lane
- bool Quad = false;
- if (BuiltinID == NEON::BI__builtin_neon_vmul_laneq_v)
- Quad = true;
- Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
- llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, Quad));
- Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
- Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
- Value *Result = Builder.CreateFMul(Ops[0], Ops[1]);
- return Builder.CreateBitCast(Result, Ty);
- }
-
- // AArch64-only builtins
- case NEON::BI__builtin_neon_vfmaq_laneq_v: {
- Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
-
- Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]));
- return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
- }
- case NEON::BI__builtin_neon_vfmaq_lane_v: {
- Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
-
- llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
- llvm::Type *STy = llvm::VectorType::get(VTy->getElementType(),
- VTy->getNumElements() / 2);
- Ops[2] = Builder.CreateBitCast(Ops[2], STy);
- Value* SV = llvm::ConstantVector::getSplat(VTy->getNumElements(),
- cast<ConstantInt>(Ops[3]));
- Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane");
-
- return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
- }
- case NEON::BI__builtin_neon_vfma_lane_v: {
- llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
- // v1f64 fma should be mapped to Neon scalar f64 fma
- if (VTy && VTy->getElementType() == DoubleTy) {
- Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
- Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
- llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, false));
- Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
- Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
- Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy);
- Value *Result = Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
- return Builder.CreateBitCast(Result, Ty);
- }
- Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
-
- Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]));
- return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
- }
- case NEON::BI__builtin_neon_vfma_laneq_v: {
- llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
- // v1f64 fma should be mapped to Neon scalar f64 fma
- if (VTy && VTy->getElementType() == DoubleTy) {
- Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
- Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
- llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, true));
- Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
- Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
- Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy);
- Value *Result = Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
- return Builder.CreateBitCast(Result, Ty);
- }
- Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
-
- llvm::Type *STy = llvm::VectorType::get(VTy->getElementType(),
- VTy->getNumElements() * 2);
- Ops[2] = Builder.CreateBitCast(Ops[2], STy);
- Value* SV = llvm::ConstantVector::getSplat(VTy->getNumElements(),
- cast<ConstantInt>(Ops[3]));
- Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane");
-
- return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
- }
- case NEON::BI__builtin_neon_vfms_v:
- case NEON::BI__builtin_neon_vfmsq_v: {
- Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
- Ops[1] = Builder.CreateFNeg(Ops[1]);
- Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
-
- // LLVM's fma intrinsic puts the accumulator in the last position, but the
- // AArch64 intrinsic has it first.
- return Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
- }
- case NEON::BI__builtin_neon_vmaxnm_v:
- case NEON::BI__builtin_neon_vmaxnmq_v: {
- Int = Intrinsic::aarch64_neon_vmaxnm;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmaxnm");
- }
- case NEON::BI__builtin_neon_vminnm_v:
- case NEON::BI__builtin_neon_vminnmq_v: {
- Int = Intrinsic::aarch64_neon_vminnm;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vminnm");
- }
- case NEON::BI__builtin_neon_vpmaxnm_v:
- case NEON::BI__builtin_neon_vpmaxnmq_v: {
- Int = Intrinsic::aarch64_neon_vpmaxnm;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmaxnm");
- }
- case NEON::BI__builtin_neon_vpminnm_v:
- case NEON::BI__builtin_neon_vpminnmq_v: {
- Int = Intrinsic::aarch64_neon_vpminnm;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpminnm");
- }
- case NEON::BI__builtin_neon_vpmaxq_v: {
- Int = usgn ? Intrinsic::arm_neon_vpmaxu : Intrinsic::arm_neon_vpmaxs;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmax");
- }
- case NEON::BI__builtin_neon_vpminq_v: {
- Int = usgn ? Intrinsic::arm_neon_vpminu : Intrinsic::arm_neon_vpmins;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmin");
- }
- case NEON::BI__builtin_neon_vmulx_v:
- case NEON::BI__builtin_neon_vmulxq_v: {
- Int = Intrinsic::aarch64_neon_vmulx;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmulx");
- }
- case NEON::BI__builtin_neon_vsqadd_v:
- case NEON::BI__builtin_neon_vsqaddq_v: {
- Int = Intrinsic::aarch64_neon_usqadd;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqadd");
- }
- case NEON::BI__builtin_neon_vuqadd_v:
- case NEON::BI__builtin_neon_vuqaddq_v: {
- Int = Intrinsic::aarch64_neon_suqadd;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vuqadd");
- }
- case NEON::BI__builtin_neon_vrbit_v:
- case NEON::BI__builtin_neon_vrbitq_v:
- Int = Intrinsic::aarch64_neon_rbit;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrbit");
- case NEON::BI__builtin_neon_vcvt_f32_f64: {
- NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float64, false, true);
- Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag));
- return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt");
- }
- case NEON::BI__builtin_neon_vcvtx_f32_v: {
- llvm::Type *EltTy = FloatTy;
- llvm::Type *ResTy = llvm::VectorType::get(EltTy, 2);
- llvm::Type *Tys[2] = { ResTy, Ty };
- Int = Intrinsic::aarch64_neon_vcvtxn;
- return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtx_f32_f64");
- }
- case NEON::BI__builtin_neon_vcvt_f64_f32: {
- llvm::Type *OpTy =
- GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, false));
- Ops[0] = Builder.CreateBitCast(Ops[0], OpTy);
- return Builder.CreateFPExt(Ops[0], Ty, "vcvt");
- }
- case NEON::BI__builtin_neon_vcvt_f64_v:
- case NEON::BI__builtin_neon_vcvtq_f64_v: {
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
- return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
- : Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
- }
- case NEON::BI__builtin_neon_vrndn_v:
- case NEON::BI__builtin_neon_vrndnq_v: {
- Int = Intrinsic::aarch64_neon_frintn;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn");
- }
- case NEON::BI__builtin_neon_vrnda_v:
- case NEON::BI__builtin_neon_vrndaq_v: {
- Int = Intrinsic::round;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnda");
- }
- case NEON::BI__builtin_neon_vrndp_v:
- case NEON::BI__builtin_neon_vrndpq_v: {
- Int = Intrinsic::ceil;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndp");
- }
- case NEON::BI__builtin_neon_vrndm_v:
- case NEON::BI__builtin_neon_vrndmq_v: {
- Int = Intrinsic::floor;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndm");
- }
- case NEON::BI__builtin_neon_vrndx_v:
- case NEON::BI__builtin_neon_vrndxq_v: {
- Int = Intrinsic::rint;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndx");
- }
- case NEON::BI__builtin_neon_vrnd_v:
- case NEON::BI__builtin_neon_vrndq_v: {
- Int = Intrinsic::trunc;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnd");
- }
- case NEON::BI__builtin_neon_vrndi_v:
- case NEON::BI__builtin_neon_vrndiq_v: {
- Int = Intrinsic::nearbyint;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndi");
- }
- case NEON::BI__builtin_neon_vsqrt_v:
- case NEON::BI__builtin_neon_vsqrtq_v: {
- Int = Intrinsic::sqrt;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqrt");
- }
- case NEON::BI__builtin_neon_vceqz_v:
- case NEON::BI__builtin_neon_vceqzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OEQ,
- ICmpInst::ICMP_EQ, "vceqz");
- case NEON::BI__builtin_neon_vcgez_v:
- case NEON::BI__builtin_neon_vcgezq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGE,
- ICmpInst::ICMP_SGE, "vcgez");
- case NEON::BI__builtin_neon_vclez_v:
- case NEON::BI__builtin_neon_vclezq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLE,
- ICmpInst::ICMP_SLE, "vclez");
- case NEON::BI__builtin_neon_vcgtz_v:
- case NEON::BI__builtin_neon_vcgtzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGT,
- ICmpInst::ICMP_SGT, "vcgtz");
- case NEON::BI__builtin_neon_vcltz_v:
- case NEON::BI__builtin_neon_vcltzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLT,
- ICmpInst::ICMP_SLT, "vcltz");
- }
-}
-
-Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
- const CallExpr *E) {
if (BuiltinID == ARM::BI__clear_cache) {
assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
@@ -4422,11 +3144,6 @@
return Builder.CreateCall(F);
}
- if (BuiltinID == ARM::BI__builtin_arm_sevl) {
- Function *F = CGM.getIntrinsic(Intrinsic::arm_sevl);
- return Builder.CreateCall(F);
- }
-
// CRC32
Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic;
switch (BuiltinID) {
@@ -4471,7 +3188,7 @@
}
SmallVector<Value*, 4> Ops;
- llvm::Value *Align = 0;
+ llvm::Value *Align = nullptr;
for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
if (i == 0) {
switch (BuiltinID) {
@@ -4587,7 +3304,7 @@
llvm::APSInt Result;
const Expr *Arg = E->getArg(E->getNumArgs()-1);
if (!Arg->isIntegerConstantExpr(Result, getContext()))
- return 0;
+ return nullptr;
if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f ||
BuiltinID == ARM::BI__builtin_arm_vcvtr_d) {
@@ -4615,7 +3332,7 @@
llvm::VectorType *VTy = GetNeonType(this, Type);
llvm::Type *Ty = VTy;
if (!Ty)
- return 0;
+ return nullptr;
// Many NEON builtins have identical semantics and uses in ARM and
// AArch64. Emit these in a single function.
@@ -4629,7 +3346,7 @@
unsigned Int;
switch (BuiltinID) {
- default: return 0;
+ default: return nullptr;
case NEON::BI__builtin_neon_vld1q_lane_v:
// Handle 64-bit integer elements as a special case. Use shuffles of
// one-element vectors to avoid poor code for i64 in the backend.
@@ -4817,16 +3534,15 @@
}
}
-static Value *EmitARM64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID,
+static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID,
const CallExpr *E,
SmallVectorImpl<Value *> &Ops) {
unsigned int Int = 0;
- const char *s = NULL;
+ const char *s = nullptr;
- unsigned TblPos;
switch (BuiltinID) {
default:
- return 0;
+ return nullptr;
case NEON::BI__builtin_neon_vtbl1_v:
case NEON::BI__builtin_neon_vqtbl1_v:
case NEON::BI__builtin_neon_vqtbl1q_v:
@@ -4839,7 +3555,6 @@
case NEON::BI__builtin_neon_vtbl4_v:
case NEON::BI__builtin_neon_vqtbl4_v:
case NEON::BI__builtin_neon_vqtbl4q_v:
- TblPos = 0;
break;
case NEON::BI__builtin_neon_vtbx1_v:
case NEON::BI__builtin_neon_vqtbx1_v:
@@ -4853,7 +3568,6 @@
case NEON::BI__builtin_neon_vtbx4_v:
case NEON::BI__builtin_neon_vqtbx4_v:
case NEON::BI__builtin_neon_vqtbx4q_v:
- TblPos = 1;
break;
}
@@ -4863,16 +3577,15 @@
llvm::APSInt Result;
const Expr *Arg = E->getArg(E->getNumArgs() - 1);
if (!Arg->isIntegerConstantExpr(Result, CGF.getContext()))
- return 0;
+ return nullptr;
// Determine the type of this overloaded NEON intrinsic.
NeonTypeFlags Type(Result.getZExtValue());
llvm::VectorType *VTy = GetNeonType(&CGF, Type);
llvm::Type *Ty = VTy;
if (!Ty)
- return 0;
+ return nullptr;
- Arg = E->getArg(TblPos);
unsigned nElts = VTy->getNumElements();
CodeGen::CGBuilderTy &Builder = CGF.Builder;
@@ -4883,34 +3596,34 @@
switch (BuiltinID) {
case NEON::BI__builtin_neon_vtbl1_v: {
TblOps.push_back(Ops[0]);
- return packTBLDVectorList(CGF, TblOps, 0, Ops[1], Ty,
- Intrinsic::arm64_neon_tbl1, "vtbl1");
+ return packTBLDVectorList(CGF, TblOps, nullptr, Ops[1], Ty,
+ Intrinsic::aarch64_neon_tbl1, "vtbl1");
}
case NEON::BI__builtin_neon_vtbl2_v: {
TblOps.push_back(Ops[0]);
TblOps.push_back(Ops[1]);
- return packTBLDVectorList(CGF, TblOps, 0, Ops[2], Ty,
- Intrinsic::arm64_neon_tbl1, "vtbl1");
+ return packTBLDVectorList(CGF, TblOps, nullptr, Ops[2], Ty,
+ Intrinsic::aarch64_neon_tbl1, "vtbl1");
}
case NEON::BI__builtin_neon_vtbl3_v: {
TblOps.push_back(Ops[0]);
TblOps.push_back(Ops[1]);
TblOps.push_back(Ops[2]);
- return packTBLDVectorList(CGF, TblOps, 0, Ops[3], Ty,
- Intrinsic::arm64_neon_tbl2, "vtbl2");
+ return packTBLDVectorList(CGF, TblOps, nullptr, Ops[3], Ty,
+ Intrinsic::aarch64_neon_tbl2, "vtbl2");
}
case NEON::BI__builtin_neon_vtbl4_v: {
TblOps.push_back(Ops[0]);
TblOps.push_back(Ops[1]);
TblOps.push_back(Ops[2]);
TblOps.push_back(Ops[3]);
- return packTBLDVectorList(CGF, TblOps, 0, Ops[4], Ty,
- Intrinsic::arm64_neon_tbl2, "vtbl2");
+ return packTBLDVectorList(CGF, TblOps, nullptr, Ops[4], Ty,
+ Intrinsic::aarch64_neon_tbl2, "vtbl2");
}
case NEON::BI__builtin_neon_vtbx1_v: {
TblOps.push_back(Ops[1]);
- Value *TblRes = packTBLDVectorList(CGF, TblOps, 0, Ops[2], Ty,
- Intrinsic::arm64_neon_tbl1, "vtbl1");
+ Value *TblRes = packTBLDVectorList(CGF, TblOps, nullptr, Ops[2], Ty,
+ Intrinsic::aarch64_neon_tbl1, "vtbl1");
llvm::Constant *Eight = ConstantInt::get(VTy->getElementType(), 8);
Value* EightV = llvm::ConstantVector::getSplat(nElts, Eight);
@@ -4925,14 +3638,14 @@
TblOps.push_back(Ops[1]);
TblOps.push_back(Ops[2]);
return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[3], Ty,
- Intrinsic::arm64_neon_tbx1, "vtbx1");
+ Intrinsic::aarch64_neon_tbx1, "vtbx1");
}
case NEON::BI__builtin_neon_vtbx3_v: {
TblOps.push_back(Ops[1]);
TblOps.push_back(Ops[2]);
TblOps.push_back(Ops[3]);
- Value *TblRes = packTBLDVectorList(CGF, TblOps, 0, Ops[4], Ty,
- Intrinsic::arm64_neon_tbl2, "vtbl2");
+ Value *TblRes = packTBLDVectorList(CGF, TblOps, nullptr, Ops[4], Ty,
+ Intrinsic::aarch64_neon_tbl2, "vtbl2");
llvm::Constant *TwentyFour = ConstantInt::get(VTy->getElementType(), 24);
Value* TwentyFourV = llvm::ConstantVector::getSplat(nElts, TwentyFour);
@@ -4950,37 +3663,37 @@
TblOps.push_back(Ops[3]);
TblOps.push_back(Ops[4]);
return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[5], Ty,
- Intrinsic::arm64_neon_tbx2, "vtbx2");
+ Intrinsic::aarch64_neon_tbx2, "vtbx2");
}
case NEON::BI__builtin_neon_vqtbl1_v:
case NEON::BI__builtin_neon_vqtbl1q_v:
- Int = Intrinsic::arm64_neon_tbl1; s = "vtbl1"; break;
+ Int = Intrinsic::aarch64_neon_tbl1; s = "vtbl1"; break;
case NEON::BI__builtin_neon_vqtbl2_v:
case NEON::BI__builtin_neon_vqtbl2q_v: {
- Int = Intrinsic::arm64_neon_tbl2; s = "vtbl2"; break;
+ Int = Intrinsic::aarch64_neon_tbl2; s = "vtbl2"; break;
case NEON::BI__builtin_neon_vqtbl3_v:
case NEON::BI__builtin_neon_vqtbl3q_v:
- Int = Intrinsic::arm64_neon_tbl3; s = "vtbl3"; break;
+ Int = Intrinsic::aarch64_neon_tbl3; s = "vtbl3"; break;
case NEON::BI__builtin_neon_vqtbl4_v:
case NEON::BI__builtin_neon_vqtbl4q_v:
- Int = Intrinsic::arm64_neon_tbl4; s = "vtbl4"; break;
+ Int = Intrinsic::aarch64_neon_tbl4; s = "vtbl4"; break;
case NEON::BI__builtin_neon_vqtbx1_v:
case NEON::BI__builtin_neon_vqtbx1q_v:
- Int = Intrinsic::arm64_neon_tbx1; s = "vtbx1"; break;
+ Int = Intrinsic::aarch64_neon_tbx1; s = "vtbx1"; break;
case NEON::BI__builtin_neon_vqtbx2_v:
case NEON::BI__builtin_neon_vqtbx2q_v:
- Int = Intrinsic::arm64_neon_tbx2; s = "vtbx2"; break;
+ Int = Intrinsic::aarch64_neon_tbx2; s = "vtbx2"; break;
case NEON::BI__builtin_neon_vqtbx3_v:
case NEON::BI__builtin_neon_vqtbx3q_v:
- Int = Intrinsic::arm64_neon_tbx3; s = "vtbx3"; break;
+ Int = Intrinsic::aarch64_neon_tbx3; s = "vtbx3"; break;
case NEON::BI__builtin_neon_vqtbx4_v:
case NEON::BI__builtin_neon_vqtbx4q_v:
- Int = Intrinsic::arm64_neon_tbx4; s = "vtbx4"; break;
+ Int = Intrinsic::aarch64_neon_tbx4; s = "vtbx4"; break;
}
}
if (!Int)
- return 0;
+ return nullptr;
Function *F = CGF.CGM.getIntrinsic(Int, Ty);
return CGF.EmitNeonCall(F, Ops, s);
@@ -5007,7 +3720,7 @@
Value *CodeGenFunction::
emitVectorWrappedScalar8Intrinsic(unsigned Int, SmallVectorImpl<Value*> &Ops,
const char *Name) {
- // i8 is not a legal types for ARM64, so we can't just use
+ // i8 is not a legal types for AArch64, so we can't just use
// a normal overloaed intrinsic call for these scalar types. Instead
// we'll build 64-bit vectors w/ lane zero being our input values and
// perform the operation on that. The back end can pattern match directly
@@ -5023,7 +3736,7 @@
Value *CodeGenFunction::
emitVectorWrappedScalar16Intrinsic(unsigned Int, SmallVectorImpl<Value*> &Ops,
const char *Name) {
- // i16 is not a legal types for ARM64, so we can't just use
+ // i16 is not a legal types for AArch64, so we can't just use
// a normal overloaed intrinsic call for these scalar types. Instead
// we'll build 64-bit vectors w/ lane zero being our input values and
// perform the operation on that. The back end can pattern match directly
@@ -5036,9 +3749,9 @@
return Builder.CreateExtractElement(V, CI, "lane0");
}
-Value *CodeGenFunction::EmitARM64BuiltinExpr(unsigned BuiltinID,
- const CallExpr *E) {
- if (BuiltinID == ARM64::BI__clear_cache) {
+Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ if (BuiltinID == AArch64::BI__clear_cache) {
assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
SmallVector<Value*, 2> Ops;
@@ -5050,9 +3763,9 @@
return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops);
}
- if (BuiltinID == ARM64::BI__builtin_arm_ldrex &&
+ if (BuiltinID == AArch64::BI__builtin_arm_ldrex &&
getContext().getTypeSize(E->getType()) == 128) {
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_ldxp);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_ldxp);
Value *LdPtr = EmitScalarExpr(E->getArg(0));
Value *Val = Builder.CreateCall(F, Builder.CreateBitCast(LdPtr, Int8PtrTy),
@@ -5068,7 +3781,7 @@
Val = Builder.CreateShl(Val0, ShiftCst, "shl", true /* nuw */);
Val = Builder.CreateOr(Val, Val1);
return Builder.CreateBitCast(Val, ConvertType(E->getType()));
- } else if (BuiltinID == ARM64::BI__builtin_arm_ldrex) {
+ } else if (BuiltinID == AArch64::BI__builtin_arm_ldrex) {
Value *LoadAddr = EmitScalarExpr(E->getArg(0));
QualType Ty = E->getType();
@@ -5077,7 +3790,7 @@
getContext().getTypeSize(Ty));
LoadAddr = Builder.CreateBitCast(LoadAddr, IntResTy->getPointerTo());
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_ldxr, LoadAddr->getType());
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_ldxr, LoadAddr->getType());
Value *Val = Builder.CreateCall(F, LoadAddr, "ldxr");
if (RealResTy->isPointerTy())
@@ -5087,9 +3800,9 @@
return Builder.CreateBitCast(Val, RealResTy);
}
- if (BuiltinID == ARM64::BI__builtin_arm_strex &&
+ if (BuiltinID == AArch64::BI__builtin_arm_strex &&
getContext().getTypeSize(E->getArg(0)->getType()) == 128) {
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_stxp);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_stxp);
llvm::Type *STy = llvm::StructType::get(Int64Ty, Int64Ty, NULL);
Value *One = llvm::ConstantInt::get(Int32Ty, 1);
@@ -5106,7 +3819,7 @@
Value *StPtr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)),
Int8PtrTy);
return Builder.CreateCall3(F, Arg0, Arg1, StPtr, "stxp");
- } else if (BuiltinID == ARM64::BI__builtin_arm_strex) {
+ } else if (BuiltinID == AArch64::BI__builtin_arm_strex) {
Value *StoreVal = EmitScalarExpr(E->getArg(0));
Value *StoreAddr = EmitScalarExpr(E->getArg(1));
@@ -5122,34 +3835,34 @@
StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int64Ty);
}
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_stxr, StoreAddr->getType());
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_stxr, StoreAddr->getType());
return Builder.CreateCall2(F, StoreVal, StoreAddr, "stxr");
}
- if (BuiltinID == ARM64::BI__builtin_arm_clrex) {
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_clrex);
+ if (BuiltinID == AArch64::BI__builtin_arm_clrex) {
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_clrex);
return Builder.CreateCall(F);
}
// CRC32
Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic;
switch (BuiltinID) {
- case ARM64::BI__builtin_arm_crc32b:
- CRCIntrinsicID = Intrinsic::arm64_crc32b; break;
- case ARM64::BI__builtin_arm_crc32cb:
- CRCIntrinsicID = Intrinsic::arm64_crc32cb; break;
- case ARM64::BI__builtin_arm_crc32h:
- CRCIntrinsicID = Intrinsic::arm64_crc32h; break;
- case ARM64::BI__builtin_arm_crc32ch:
- CRCIntrinsicID = Intrinsic::arm64_crc32ch; break;
- case ARM64::BI__builtin_arm_crc32w:
- CRCIntrinsicID = Intrinsic::arm64_crc32w; break;
- case ARM64::BI__builtin_arm_crc32cw:
- CRCIntrinsicID = Intrinsic::arm64_crc32cw; break;
- case ARM64::BI__builtin_arm_crc32d:
- CRCIntrinsicID = Intrinsic::arm64_crc32x; break;
- case ARM64::BI__builtin_arm_crc32cd:
- CRCIntrinsicID = Intrinsic::arm64_crc32cx; break;
+ case AArch64::BI__builtin_arm_crc32b:
+ CRCIntrinsicID = Intrinsic::aarch64_crc32b; break;
+ case AArch64::BI__builtin_arm_crc32cb:
+ CRCIntrinsicID = Intrinsic::aarch64_crc32cb; break;
+ case AArch64::BI__builtin_arm_crc32h:
+ CRCIntrinsicID = Intrinsic::aarch64_crc32h; break;
+ case AArch64::BI__builtin_arm_crc32ch:
+ CRCIntrinsicID = Intrinsic::aarch64_crc32ch; break;
+ case AArch64::BI__builtin_arm_crc32w:
+ CRCIntrinsicID = Intrinsic::aarch64_crc32w; break;
+ case AArch64::BI__builtin_arm_crc32cw:
+ CRCIntrinsicID = Intrinsic::aarch64_crc32cw; break;
+ case AArch64::BI__builtin_arm_crc32d:
+ CRCIntrinsicID = Intrinsic::aarch64_crc32x; break;
+ case AArch64::BI__builtin_arm_crc32cd:
+ CRCIntrinsicID = Intrinsic::aarch64_crc32cx; break;
}
if (CRCIntrinsicID != Intrinsic::not_intrinsic) {
@@ -5167,9 +3880,9 @@
for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++)
Ops.push_back(EmitScalarExpr(E->getArg(i)));
- llvm::ArrayRef<NeonIntrinsicInfo> SISDMap(ARM64SISDIntrinsicMap);
+ llvm::ArrayRef<NeonIntrinsicInfo> SISDMap(AArch64SISDIntrinsicMap);
const NeonIntrinsicInfo *Builtin = findNeonIntrinsicInMap(
- SISDMap, BuiltinID, ARM64SISDIntrinsicsProvenSorted);
+ SISDMap, BuiltinID, AArch64SISDIntrinsicsProvenSorted);
if (Builtin) {
Ops.push_back(EmitScalarExpr(E->getArg(E->getNumArgs() - 1)));
@@ -5513,50 +4226,46 @@
ProductOps.push_back(vectorWrapScalar16(Ops[1]));
ProductOps.push_back(vectorWrapScalar16(EmitScalarExpr(E->getArg(2))));
llvm::Type *VTy = llvm::VectorType::get(Int32Ty, 4);
- Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_sqdmull, VTy),
+ Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmull, VTy),
ProductOps, "vqdmlXl");
Constant *CI = ConstantInt::get(Int32Ty, 0);
Ops[1] = Builder.CreateExtractElement(Ops[1], CI, "lane0");
unsigned AccumInt = BuiltinID == NEON::BI__builtin_neon_vqdmlalh_s16
- ? Intrinsic::arm64_neon_sqadd
- : Intrinsic::arm64_neon_sqsub;
+ ? Intrinsic::aarch64_neon_sqadd
+ : Intrinsic::aarch64_neon_sqsub;
return EmitNeonCall(CGM.getIntrinsic(AccumInt, Int32Ty), Ops, "vqdmlXl");
}
case NEON::BI__builtin_neon_vqshlud_n_s64: {
Ops.push_back(EmitScalarExpr(E->getArg(1)));
Ops[1] = Builder.CreateZExt(Ops[1], Int64Ty);
- llvm::Type *VTy = llvm::VectorType::get(Int64Ty, 1);
- Ops[0] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_sqshlu, VTy),
- Ops, "vqshlu_n");
- return Builder.CreateBitCast(Ops[0], Int64Ty);
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqshlu, Int64Ty),
+ Ops, "vqshlu_n");
}
case NEON::BI__builtin_neon_vqshld_n_u64:
case NEON::BI__builtin_neon_vqshld_n_s64: {
unsigned Int = BuiltinID == NEON::BI__builtin_neon_vqshld_n_u64
- ? Intrinsic::arm64_neon_uqshl
- : Intrinsic::arm64_neon_sqshl;
+ ? Intrinsic::aarch64_neon_uqshl
+ : Intrinsic::aarch64_neon_sqshl;
Ops.push_back(EmitScalarExpr(E->getArg(1)));
Ops[1] = Builder.CreateZExt(Ops[1], Int64Ty);
- llvm::Type *VTy = llvm::VectorType::get(Int64Ty, 1);
- Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, VTy), Ops, "vqshl_n");
- return Builder.CreateBitCast(Ops[0], Int64Ty);
+ return EmitNeonCall(CGM.getIntrinsic(Int, Int64Ty), Ops, "vqshl_n");
}
case NEON::BI__builtin_neon_vrshrd_n_u64:
case NEON::BI__builtin_neon_vrshrd_n_s64: {
unsigned Int = BuiltinID == NEON::BI__builtin_neon_vrshrd_n_u64
- ? Intrinsic::arm64_neon_urshl
- : Intrinsic::arm64_neon_srshl;
+ ? Intrinsic::aarch64_neon_urshl
+ : Intrinsic::aarch64_neon_srshl;
Ops.push_back(EmitScalarExpr(E->getArg(1)));
- llvm::Type *VTy = llvm::VectorType::get(Int64Ty, 1);
- Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, VTy), Ops, "vrshr_n", 1, true);
- return Builder.CreateBitCast(Ops[0], Int64Ty);
+ int SV = cast<ConstantInt>(Ops[1])->getSExtValue();
+ Ops[1] = ConstantInt::get(Int64Ty, -SV);
+ return EmitNeonCall(CGM.getIntrinsic(Int, Int64Ty), Ops, "vrshr_n");
}
case NEON::BI__builtin_neon_vrsrad_n_u64:
case NEON::BI__builtin_neon_vrsrad_n_s64: {
unsigned Int = BuiltinID == NEON::BI__builtin_neon_vrsrad_n_u64
- ? Intrinsic::arm64_neon_urshl
- : Intrinsic::arm64_neon_srshl;
+ ? Intrinsic::aarch64_neon_urshl
+ : Intrinsic::aarch64_neon_srshl;
Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty);
Ops.push_back(Builder.CreateNeg(EmitScalarExpr(E->getArg(2))));
Ops[1] = Builder.CreateCall2(CGM.getIntrinsic(Int, Int64Ty), Ops[1],
@@ -5567,38 +4276,41 @@
case NEON::BI__builtin_neon_vshld_n_u64: {
llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1)));
return Builder.CreateShl(
- Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63),
- Amt->getZExtValue())),
- "vshr_n");
+ Ops[0], ConstantInt::get(Int64Ty, Amt->getZExtValue()), "shld_n");
}
case NEON::BI__builtin_neon_vshrd_n_s64: {
llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1)));
return Builder.CreateAShr(
Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63),
Amt->getZExtValue())),
- "vshr_n");
+ "shrd_n");
}
case NEON::BI__builtin_neon_vshrd_n_u64: {
llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1)));
- return Builder.CreateLShr(
- Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63),
- Amt->getZExtValue())),
- "vshr_n");
+ uint64_t ShiftAmt = Amt->getZExtValue();
+ // Right-shifting an unsigned value by its size yields 0.
+ if (ShiftAmt == 64)
+ return ConstantInt::get(Int64Ty, 0);
+ return Builder.CreateLShr(Ops[0], ConstantInt::get(Int64Ty, ShiftAmt),
+ "shrd_n");
}
case NEON::BI__builtin_neon_vsrad_n_s64: {
llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(2)));
Ops[1] = Builder.CreateAShr(
Ops[1], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63),
Amt->getZExtValue())),
- "vshr_n");
+ "shrd_n");
return Builder.CreateAdd(Ops[0], Ops[1]);
}
case NEON::BI__builtin_neon_vsrad_n_u64: {
llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(2)));
- Ops[1] = Builder.CreateLShr(
- Ops[1], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63),
- Amt->getZExtValue())),
- "vshr_n");
+ uint64_t ShiftAmt = Amt->getZExtValue();
+ // Right-shifting an unsigned value by its size yields 0.
+ // As Op + 0 = Op, return Ops[0] directly.
+ if (ShiftAmt == 64)
+ return Ops[0];
+ Ops[1] = Builder.CreateLShr(Ops[1], ConstantInt::get(Int64Ty, ShiftAmt),
+ "shrd_n");
return Builder.CreateAdd(Ops[0], Ops[1]);
}
case NEON::BI__builtin_neon_vqdmlalh_lane_s16:
@@ -5611,7 +4323,7 @@
ProductOps.push_back(vectorWrapScalar16(Ops[1]));
ProductOps.push_back(vectorWrapScalar16(Ops[2]));
llvm::Type *VTy = llvm::VectorType::get(Int32Ty, 4);
- Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_sqdmull, VTy),
+ Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmull, VTy),
ProductOps, "vqdmlXl");
Constant *CI = ConstantInt::get(Int32Ty, 0);
Ops[1] = Builder.CreateExtractElement(Ops[1], CI, "lane0");
@@ -5619,8 +4331,8 @@
unsigned AccInt = (BuiltinID == NEON::BI__builtin_neon_vqdmlalh_lane_s16 ||
BuiltinID == NEON::BI__builtin_neon_vqdmlalh_laneq_s16)
- ? Intrinsic::arm64_neon_sqadd
- : Intrinsic::arm64_neon_sqsub;
+ ? Intrinsic::aarch64_neon_sqadd
+ : Intrinsic::aarch64_neon_sqsub;
return EmitNeonCall(CGM.getIntrinsic(AccInt, Int32Ty), Ops, "vqdmlXl");
}
case NEON::BI__builtin_neon_vqdmlals_s32:
@@ -5629,12 +4341,12 @@
ProductOps.push_back(Ops[1]);
ProductOps.push_back(EmitScalarExpr(E->getArg(2)));
Ops[1] =
- EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_sqdmulls_scalar),
+ EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmulls_scalar),
ProductOps, "vqdmlXl");
unsigned AccumInt = BuiltinID == NEON::BI__builtin_neon_vqdmlals_s32
- ? Intrinsic::arm64_neon_sqadd
- : Intrinsic::arm64_neon_sqsub;
+ ? Intrinsic::aarch64_neon_sqadd
+ : Intrinsic::aarch64_neon_sqsub;
return EmitNeonCall(CGM.getIntrinsic(AccumInt, Int64Ty), Ops, "vqdmlXl");
}
case NEON::BI__builtin_neon_vqdmlals_lane_s32:
@@ -5647,14 +4359,14 @@
ProductOps.push_back(Ops[1]);
ProductOps.push_back(Ops[2]);
Ops[1] =
- EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_sqdmulls_scalar),
+ EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmulls_scalar),
ProductOps, "vqdmlXl");
Ops.pop_back();
unsigned AccInt = (BuiltinID == NEON::BI__builtin_neon_vqdmlals_lane_s32 ||
BuiltinID == NEON::BI__builtin_neon_vqdmlals_laneq_s32)
- ? Intrinsic::arm64_neon_sqadd
- : Intrinsic::arm64_neon_sqsub;
+ ? Intrinsic::aarch64_neon_sqadd
+ : Intrinsic::aarch64_neon_sqsub;
return EmitNeonCall(CGM.getIntrinsic(AccInt, Int64Ty), Ops, "vqdmlXl");
}
}
@@ -5662,24 +4374,24 @@
llvm::VectorType *VTy = GetNeonType(this, Type);
llvm::Type *Ty = VTy;
if (!Ty)
- return 0;
+ return nullptr;
- // Not all intrinsics handled by the common case work for ARM64 yet, so only
+ // Not all intrinsics handled by the common case work for AArch64 yet, so only
// defer to common code if it's been added to our special map.
- Builtin = findNeonIntrinsicInMap(ARM64SIMDIntrinsicMap, BuiltinID,
- ARM64SIMDIntrinsicsProvenSorted);
+ Builtin = findNeonIntrinsicInMap(AArch64SIMDIntrinsicMap, BuiltinID,
+ AArch64SIMDIntrinsicsProvenSorted);
if (Builtin)
return EmitCommonNeonBuiltinExpr(
Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic,
- Builtin->NameHint, Builtin->TypeModifier, E, Ops, 0);
+ Builtin->NameHint, Builtin->TypeModifier, E, Ops, nullptr);
- if (Value *V = EmitARM64TblBuiltinExpr(*this, BuiltinID, E, Ops))
+ if (Value *V = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E, Ops))
return V;
unsigned Int;
switch (BuiltinID) {
- default: return 0;
+ default: return nullptr;
case NEON::BI__builtin_neon_vbsl_v:
case NEON::BI__builtin_neon_vbslq_v: {
llvm::Type *BitTy = llvm::VectorType::getInteger(VTy);
@@ -5780,26 +4492,26 @@
}
case NEON::BI__builtin_neon_vmull_v:
// FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
- Int = usgn ? Intrinsic::arm64_neon_umull : Intrinsic::arm64_neon_smull;
- if (Type.isPoly()) Int = Intrinsic::arm64_neon_pmull;
+ Int = usgn ? Intrinsic::aarch64_neon_umull : Intrinsic::aarch64_neon_smull;
+ if (Type.isPoly()) Int = Intrinsic::aarch64_neon_pmull;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull");
case NEON::BI__builtin_neon_vmax_v:
case NEON::BI__builtin_neon_vmaxq_v:
// FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
- Int = usgn ? Intrinsic::arm64_neon_umax : Intrinsic::arm64_neon_smax;
- if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::arm64_neon_fmax;
+ Int = usgn ? Intrinsic::aarch64_neon_umax : Intrinsic::aarch64_neon_smax;
+ if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmax;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmax");
case NEON::BI__builtin_neon_vmin_v:
case NEON::BI__builtin_neon_vminq_v:
// FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
- Int = usgn ? Intrinsic::arm64_neon_umin : Intrinsic::arm64_neon_smin;
- if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::arm64_neon_fmin;
+ Int = usgn ? Intrinsic::aarch64_neon_umin : Intrinsic::aarch64_neon_smin;
+ if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmin;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmin");
case NEON::BI__builtin_neon_vabd_v:
case NEON::BI__builtin_neon_vabdq_v:
// FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
- Int = usgn ? Intrinsic::arm64_neon_uabd : Intrinsic::arm64_neon_sabd;
- if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::arm64_neon_fabd;
+ Int = usgn ? Intrinsic::aarch64_neon_uabd : Intrinsic::aarch64_neon_sabd;
+ if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fabd;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vabd");
case NEON::BI__builtin_neon_vpadal_v:
case NEON::BI__builtin_neon_vpadalq_v: {
@@ -5809,7 +4521,7 @@
llvm::Type *ArgTy = llvm::VectorType::get(
llvm::IntegerType::get(getLLVMContext(), BitWidth/2), 2*ArgElts);
llvm::Type* Tys[2] = { VTy, ArgTy };
- Int = usgn ? Intrinsic::arm64_neon_uaddlp : Intrinsic::arm64_neon_saddlp;
+ Int = usgn ? Intrinsic::aarch64_neon_uaddlp : Intrinsic::aarch64_neon_saddlp;
SmallVector<llvm::Value*, 1> TmpOps;
TmpOps.push_back(Ops[1]);
Function *F = CGM.getIntrinsic(Int, Tys);
@@ -5820,33 +4532,33 @@
case NEON::BI__builtin_neon_vpmin_v:
case NEON::BI__builtin_neon_vpminq_v:
// FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
- Int = usgn ? Intrinsic::arm64_neon_uminp : Intrinsic::arm64_neon_sminp;
- if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::arm64_neon_fminp;
+ Int = usgn ? Intrinsic::aarch64_neon_uminp : Intrinsic::aarch64_neon_sminp;
+ if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fminp;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmin");
case NEON::BI__builtin_neon_vpmax_v:
case NEON::BI__builtin_neon_vpmaxq_v:
// FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
- Int = usgn ? Intrinsic::arm64_neon_umaxp : Intrinsic::arm64_neon_smaxp;
- if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::arm64_neon_fmaxp;
+ Int = usgn ? Intrinsic::aarch64_neon_umaxp : Intrinsic::aarch64_neon_smaxp;
+ if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmaxp;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmax");
case NEON::BI__builtin_neon_vminnm_v:
case NEON::BI__builtin_neon_vminnmq_v:
- Int = Intrinsic::arm64_neon_fminnm;
+ Int = Intrinsic::aarch64_neon_fminnm;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vminnm");
case NEON::BI__builtin_neon_vmaxnm_v:
case NEON::BI__builtin_neon_vmaxnmq_v:
- Int = Intrinsic::arm64_neon_fmaxnm;
+ Int = Intrinsic::aarch64_neon_fmaxnm;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmaxnm");
case NEON::BI__builtin_neon_vrecpss_f32: {
llvm::Type *f32Type = llvm::Type::getFloatTy(getLLVMContext());
Ops.push_back(EmitScalarExpr(E->getArg(1)));
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_frecps, f32Type),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, f32Type),
Ops, "vrecps");
}
case NEON::BI__builtin_neon_vrecpsd_f64: {
llvm::Type *f64Type = llvm::Type::getDoubleTy(getLLVMContext());
Ops.push_back(EmitScalarExpr(E->getArg(1)));
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_frecps, f64Type),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, f64Type),
Ops, "vrecps");
}
case NEON::BI__builtin_neon_vrshr_n_v:
@@ -5854,34 +4566,34 @@
// FIXME: this can be shared with 32-bit ARM, but not AArch64 at the
// moment. After the final merge it should be added to
// EmitCommonNeonBuiltinExpr.
- Int = usgn ? Intrinsic::arm64_neon_urshl : Intrinsic::arm64_neon_srshl;
+ Int = usgn ? Intrinsic::aarch64_neon_urshl : Intrinsic::aarch64_neon_srshl;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n", 1, true);
case NEON::BI__builtin_neon_vqshlu_n_v:
case NEON::BI__builtin_neon_vqshluq_n_v:
// FIXME: AArch64 and ARM use different intrinsics for this, but are
// essentially compatible. It should be in EmitCommonNeonBuiltinExpr after
// the final merge.
- Int = Intrinsic::arm64_neon_sqshlu;
+ Int = Intrinsic::aarch64_neon_sqshlu;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshlu_n", 1, false);
case NEON::BI__builtin_neon_vqshrun_n_v:
// FIXME: as above
- Int = Intrinsic::arm64_neon_sqshrun;
+ Int = Intrinsic::aarch64_neon_sqshrun;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrun_n");
case NEON::BI__builtin_neon_vqrshrun_n_v:
// FIXME: and again.
- Int = Intrinsic::arm64_neon_sqrshrun;
+ Int = Intrinsic::aarch64_neon_sqrshrun;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrun_n");
case NEON::BI__builtin_neon_vqshrn_n_v:
// FIXME: guess
- Int = usgn ? Intrinsic::arm64_neon_uqshrn : Intrinsic::arm64_neon_sqshrn;
+ Int = usgn ? Intrinsic::aarch64_neon_uqshrn : Intrinsic::aarch64_neon_sqshrn;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n");
case NEON::BI__builtin_neon_vrshrn_n_v:
// FIXME: there might be a pattern here.
- Int = Intrinsic::arm64_neon_rshrn;
+ Int = Intrinsic::aarch64_neon_rshrn;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshrn_n");
case NEON::BI__builtin_neon_vqrshrn_n_v:
// FIXME: another one
- Int = usgn ? Intrinsic::arm64_neon_uqrshrn : Intrinsic::arm64_neon_sqrshrn;
+ Int = usgn ? Intrinsic::aarch64_neon_uqrshrn : Intrinsic::aarch64_neon_sqrshrn;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n");
case NEON::BI__builtin_neon_vrnda_v:
case NEON::BI__builtin_neon_vrndaq_v: {
@@ -5900,7 +4612,7 @@
}
case NEON::BI__builtin_neon_vrndn_v:
case NEON::BI__builtin_neon_vrndnq_v: {
- Int = Intrinsic::arm64_neon_frintn;
+ Int = Intrinsic::aarch64_neon_frintn;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn");
}
case NEON::BI__builtin_neon_vrndp_v:
@@ -5987,7 +4699,7 @@
case NEON::BI__builtin_neon_vcvtaq_s64_v:
case NEON::BI__builtin_neon_vcvta_u64_v:
case NEON::BI__builtin_neon_vcvtaq_u64_v: {
- Int = usgn ? Intrinsic::arm64_neon_fcvtau : Intrinsic::arm64_neon_fcvtas;
+ Int = usgn ? Intrinsic::aarch64_neon_fcvtau : Intrinsic::aarch64_neon_fcvtas;
bool Double =
(cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
llvm::Type *InTy =
@@ -6005,7 +4717,7 @@
case NEON::BI__builtin_neon_vcvtmq_s64_v:
case NEON::BI__builtin_neon_vcvtm_u64_v:
case NEON::BI__builtin_neon_vcvtmq_u64_v: {
- Int = usgn ? Intrinsic::arm64_neon_fcvtmu : Intrinsic::arm64_neon_fcvtms;
+ Int = usgn ? Intrinsic::aarch64_neon_fcvtmu : Intrinsic::aarch64_neon_fcvtms;
bool Double =
(cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
llvm::Type *InTy =
@@ -6023,7 +4735,7 @@
case NEON::BI__builtin_neon_vcvtnq_s64_v:
case NEON::BI__builtin_neon_vcvtn_u64_v:
case NEON::BI__builtin_neon_vcvtnq_u64_v: {
- Int = usgn ? Intrinsic::arm64_neon_fcvtnu : Intrinsic::arm64_neon_fcvtns;
+ Int = usgn ? Intrinsic::aarch64_neon_fcvtnu : Intrinsic::aarch64_neon_fcvtns;
bool Double =
(cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
llvm::Type *InTy =
@@ -6041,7 +4753,7 @@
case NEON::BI__builtin_neon_vcvtpq_s64_v:
case NEON::BI__builtin_neon_vcvtp_u64_v:
case NEON::BI__builtin_neon_vcvtpq_u64_v: {
- Int = usgn ? Intrinsic::arm64_neon_fcvtpu : Intrinsic::arm64_neon_fcvtps;
+ Int = usgn ? Intrinsic::aarch64_neon_fcvtpu : Intrinsic::aarch64_neon_fcvtps;
bool Double =
(cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
llvm::Type *InTy =
@@ -6053,7 +4765,7 @@
}
case NEON::BI__builtin_neon_vmulx_v:
case NEON::BI__builtin_neon_vmulxq_v: {
- Int = Intrinsic::arm64_neon_fmulx;
+ Int = Intrinsic::aarch64_neon_fmulx;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmulx");
}
case NEON::BI__builtin_neon_vmul_lane_v:
@@ -6074,12 +4786,12 @@
return Builder.CreateNeg(EmitScalarExpr(E->getArg(0)), "vnegd");
case NEON::BI__builtin_neon_vpmaxnm_v:
case NEON::BI__builtin_neon_vpmaxnmq_v: {
- Int = Intrinsic::arm64_neon_fmaxnmp;
+ Int = Intrinsic::aarch64_neon_fmaxnmp;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmaxnm");
}
case NEON::BI__builtin_neon_vpminnm_v:
case NEON::BI__builtin_neon_vpminnmq_v: {
- Int = Intrinsic::arm64_neon_fminnmp;
+ Int = Intrinsic::aarch64_neon_fminnmp;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpminnm");
}
case NEON::BI__builtin_neon_vsqrt_v:
@@ -6090,7 +4802,7 @@
}
case NEON::BI__builtin_neon_vrbit_v:
case NEON::BI__builtin_neon_vrbitq_v: {
- Int = Intrinsic::arm64_neon_rbit;
+ Int = Intrinsic::aarch64_neon_rbit;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrbit");
}
case NEON::BI__builtin_neon_vaddv_u8:
@@ -6098,7 +4810,7 @@
usgn = true;
// FALLTHROUGH
case NEON::BI__builtin_neon_vaddv_s8: {
- Int = usgn ? Intrinsic::arm64_neon_uaddv : Intrinsic::arm64_neon_saddv;
+ Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
@@ -6112,7 +4824,7 @@
usgn = true;
// FALLTHROUGH
case NEON::BI__builtin_neon_vaddv_s16: {
- Int = usgn ? Intrinsic::arm64_neon_uaddv : Intrinsic::arm64_neon_saddv;
+ Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
@@ -6126,7 +4838,7 @@
usgn = true;
// FALLTHROUGH
case NEON::BI__builtin_neon_vaddvq_s8: {
- Int = usgn ? Intrinsic::arm64_neon_uaddv : Intrinsic::arm64_neon_saddv;
+ Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
@@ -6140,7 +4852,7 @@
usgn = true;
// FALLTHROUGH
case NEON::BI__builtin_neon_vaddvq_s16: {
- Int = usgn ? Intrinsic::arm64_neon_uaddv : Intrinsic::arm64_neon_saddv;
+ Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
@@ -6151,7 +4863,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vmaxv_u8: {
- Int = Intrinsic::arm64_neon_umaxv;
+ Int = Intrinsic::aarch64_neon_umaxv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
@@ -6162,7 +4874,7 @@
llvm::IntegerType::get(getLLVMContext(), 8));
}
case NEON::BI__builtin_neon_vmaxv_u16: {
- Int = Intrinsic::arm64_neon_umaxv;
+ Int = Intrinsic::aarch64_neon_umaxv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
@@ -6173,7 +4885,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vmaxvq_u8: {
- Int = Intrinsic::arm64_neon_umaxv;
+ Int = Intrinsic::aarch64_neon_umaxv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
@@ -6184,7 +4896,7 @@
llvm::IntegerType::get(getLLVMContext(), 8));
}
case NEON::BI__builtin_neon_vmaxvq_u16: {
- Int = Intrinsic::arm64_neon_umaxv;
+ Int = Intrinsic::aarch64_neon_umaxv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
@@ -6195,7 +4907,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vmaxv_s8: {
- Int = Intrinsic::arm64_neon_smaxv;
+ Int = Intrinsic::aarch64_neon_smaxv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
@@ -6206,7 +4918,7 @@
llvm::IntegerType::get(getLLVMContext(), 8));
}
case NEON::BI__builtin_neon_vmaxv_s16: {
- Int = Intrinsic::arm64_neon_smaxv;
+ Int = Intrinsic::aarch64_neon_smaxv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
@@ -6217,7 +4929,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vmaxvq_s8: {
- Int = Intrinsic::arm64_neon_smaxv;
+ Int = Intrinsic::aarch64_neon_smaxv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
@@ -6228,7 +4940,7 @@
llvm::IntegerType::get(getLLVMContext(), 8));
}
case NEON::BI__builtin_neon_vmaxvq_s16: {
- Int = Intrinsic::arm64_neon_smaxv;
+ Int = Intrinsic::aarch64_neon_smaxv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
@@ -6239,7 +4951,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vminv_u8: {
- Int = Intrinsic::arm64_neon_uminv;
+ Int = Intrinsic::aarch64_neon_uminv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
@@ -6250,7 +4962,7 @@
llvm::IntegerType::get(getLLVMContext(), 8));
}
case NEON::BI__builtin_neon_vminv_u16: {
- Int = Intrinsic::arm64_neon_uminv;
+ Int = Intrinsic::aarch64_neon_uminv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
@@ -6261,7 +4973,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vminvq_u8: {
- Int = Intrinsic::arm64_neon_uminv;
+ Int = Intrinsic::aarch64_neon_uminv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
@@ -6272,7 +4984,7 @@
llvm::IntegerType::get(getLLVMContext(), 8));
}
case NEON::BI__builtin_neon_vminvq_u16: {
- Int = Intrinsic::arm64_neon_uminv;
+ Int = Intrinsic::aarch64_neon_uminv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
@@ -6283,7 +4995,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vminv_s8: {
- Int = Intrinsic::arm64_neon_sminv;
+ Int = Intrinsic::aarch64_neon_sminv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
@@ -6294,7 +5006,7 @@
llvm::IntegerType::get(getLLVMContext(), 8));
}
case NEON::BI__builtin_neon_vminv_s16: {
- Int = Intrinsic::arm64_neon_sminv;
+ Int = Intrinsic::aarch64_neon_sminv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
@@ -6305,7 +5017,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vminvq_s8: {
- Int = Intrinsic::arm64_neon_sminv;
+ Int = Intrinsic::aarch64_neon_sminv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
@@ -6316,7 +5028,7 @@
llvm::IntegerType::get(getLLVMContext(), 8));
}
case NEON::BI__builtin_neon_vminvq_s16: {
- Int = Intrinsic::arm64_neon_sminv;
+ Int = Intrinsic::aarch64_neon_sminv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
@@ -6332,7 +5044,7 @@
return Builder.CreateFMul(Ops[0], RHS);
}
case NEON::BI__builtin_neon_vaddlv_u8: {
- Int = Intrinsic::arm64_neon_uaddlv;
+ Int = Intrinsic::aarch64_neon_uaddlv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
@@ -6343,7 +5055,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vaddlv_u16: {
- Int = Intrinsic::arm64_neon_uaddlv;
+ Int = Intrinsic::aarch64_neon_uaddlv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
@@ -6352,7 +5064,7 @@
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
}
case NEON::BI__builtin_neon_vaddlvq_u8: {
- Int = Intrinsic::arm64_neon_uaddlv;
+ Int = Intrinsic::aarch64_neon_uaddlv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
@@ -6363,7 +5075,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vaddlvq_u16: {
- Int = Intrinsic::arm64_neon_uaddlv;
+ Int = Intrinsic::aarch64_neon_uaddlv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
@@ -6372,7 +5084,7 @@
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
}
case NEON::BI__builtin_neon_vaddlv_s8: {
- Int = Intrinsic::arm64_neon_saddlv;
+ Int = Intrinsic::aarch64_neon_saddlv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
@@ -6383,7 +5095,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vaddlv_s16: {
- Int = Intrinsic::arm64_neon_saddlv;
+ Int = Intrinsic::aarch64_neon_saddlv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
@@ -6392,7 +5104,7 @@
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
}
case NEON::BI__builtin_neon_vaddlvq_s8: {
- Int = Intrinsic::arm64_neon_saddlv;
+ Int = Intrinsic::aarch64_neon_saddlv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
@@ -6403,7 +5115,7 @@
llvm::IntegerType::get(getLLVMContext(), 16));
}
case NEON::BI__builtin_neon_vaddlvq_s16: {
- Int = Intrinsic::arm64_neon_saddlv;
+ Int = Intrinsic::aarch64_neon_saddlv;
Ty = llvm::IntegerType::get(getLLVMContext(), 32);
VTy =
llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
@@ -6413,13 +5125,13 @@
}
case NEON::BI__builtin_neon_vsri_n_v:
case NEON::BI__builtin_neon_vsriq_n_v: {
- Int = Intrinsic::arm64_neon_vsri;
+ Int = Intrinsic::aarch64_neon_vsri;
llvm::Function *Intrin = CGM.getIntrinsic(Int, Ty);
return EmitNeonCall(Intrin, Ops, "vsri_n");
}
case NEON::BI__builtin_neon_vsli_n_v:
case NEON::BI__builtin_neon_vsliq_n_v: {
- Int = Intrinsic::arm64_neon_vsli;
+ Int = Intrinsic::aarch64_neon_vsli;
llvm::Function *Intrin = CGM.getIntrinsic(Int, Ty);
return EmitNeonCall(Intrin, Ops, "vsli_n");
}
@@ -6430,7 +5142,7 @@
return Builder.CreateAdd(Ops[0], Ops[1]);
case NEON::BI__builtin_neon_vrsra_n_v:
case NEON::BI__builtin_neon_vrsraq_n_v: {
- Int = usgn ? Intrinsic::arm64_neon_urshl : Intrinsic::arm64_neon_srshl;
+ Int = usgn ? Intrinsic::aarch64_neon_urshl : Intrinsic::aarch64_neon_srshl;
SmallVector<llvm::Value*,2> TmpOps;
TmpOps.push_back(Ops[1]);
TmpOps.push_back(Ops[2]);
@@ -6454,15 +5166,15 @@
switch (BuiltinID) {
case NEON::BI__builtin_neon_vld1_x2_v:
case NEON::BI__builtin_neon_vld1q_x2_v:
- Int = Intrinsic::arm64_neon_ld1x2;
+ Int = Intrinsic::aarch64_neon_ld1x2;
break;
case NEON::BI__builtin_neon_vld1_x3_v:
case NEON::BI__builtin_neon_vld1q_x3_v:
- Int = Intrinsic::arm64_neon_ld1x3;
+ Int = Intrinsic::aarch64_neon_ld1x3;
break;
case NEON::BI__builtin_neon_vld1_x4_v:
case NEON::BI__builtin_neon_vld1q_x4_v:
- Int = Intrinsic::arm64_neon_ld1x4;
+ Int = Intrinsic::aarch64_neon_ld1x4;
break;
}
Function *F = CGM.getIntrinsic(Int, Tys);
@@ -6483,15 +5195,15 @@
switch (BuiltinID) {
case NEON::BI__builtin_neon_vst1_x2_v:
case NEON::BI__builtin_neon_vst1q_x2_v:
- Int = Intrinsic::arm64_neon_st1x2;
+ Int = Intrinsic::aarch64_neon_st1x2;
break;
case NEON::BI__builtin_neon_vst1_x3_v:
case NEON::BI__builtin_neon_vst1q_x3_v:
- Int = Intrinsic::arm64_neon_st1x3;
+ Int = Intrinsic::aarch64_neon_st1x3;
break;
case NEON::BI__builtin_neon_vst1_x4_v:
case NEON::BI__builtin_neon_vst1q_x4_v:
- Int = Intrinsic::arm64_neon_st1x4;
+ Int = Intrinsic::aarch64_neon_st1x4;
break;
}
SmallVector<Value *, 4> IntOps(Ops.begin()+1, Ops.end());
@@ -6535,7 +5247,7 @@
llvm::Type *PTy = llvm::PointerType::getUnqual(VTy);
Ops[1] = Builder.CreateBitCast(Ops[1], PTy);
llvm::Type *Tys[2] = { VTy, PTy };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld2, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2, Tys);
Ops[1] = Builder.CreateCall(F, Ops[1], "vld2");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
@@ -6546,7 +5258,7 @@
llvm::Type *PTy = llvm::PointerType::getUnqual(VTy);
Ops[1] = Builder.CreateBitCast(Ops[1], PTy);
llvm::Type *Tys[2] = { VTy, PTy };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld3, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3, Tys);
Ops[1] = Builder.CreateCall(F, Ops[1], "vld3");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
@@ -6557,7 +5269,7 @@
llvm::Type *PTy = llvm::PointerType::getUnqual(VTy);
Ops[1] = Builder.CreateBitCast(Ops[1], PTy);
llvm::Type *Tys[2] = { VTy, PTy };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld4, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4, Tys);
Ops[1] = Builder.CreateCall(F, Ops[1], "vld4");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
@@ -6569,7 +5281,7 @@
llvm::PointerType::getUnqual(VTy->getElementType());
Ops[1] = Builder.CreateBitCast(Ops[1], PTy);
llvm::Type *Tys[2] = { VTy, PTy };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld2r, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2r, Tys);
Ops[1] = Builder.CreateCall(F, Ops[1], "vld2");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
@@ -6581,7 +5293,7 @@
llvm::PointerType::getUnqual(VTy->getElementType());
Ops[1] = Builder.CreateBitCast(Ops[1], PTy);
llvm::Type *Tys[2] = { VTy, PTy };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld3r, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3r, Tys);
Ops[1] = Builder.CreateCall(F, Ops[1], "vld3");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
@@ -6593,7 +5305,7 @@
llvm::PointerType::getUnqual(VTy->getElementType());
Ops[1] = Builder.CreateBitCast(Ops[1], PTy);
llvm::Type *Tys[2] = { VTy, PTy };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld4r, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4r, Tys);
Ops[1] = Builder.CreateCall(F, Ops[1], "vld4");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
@@ -6602,7 +5314,7 @@
case NEON::BI__builtin_neon_vld2_lane_v:
case NEON::BI__builtin_neon_vld2q_lane_v: {
llvm::Type *Tys[2] = { VTy, Ops[1]->getType() };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld2lane, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2lane, Tys);
Ops.push_back(Ops[1]);
Ops.erase(Ops.begin()+1);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
@@ -6618,7 +5330,7 @@
case NEON::BI__builtin_neon_vld3_lane_v:
case NEON::BI__builtin_neon_vld3q_lane_v: {
llvm::Type *Tys[2] = { VTy, Ops[1]->getType() };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld3lane, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3lane, Tys);
Ops.push_back(Ops[1]);
Ops.erase(Ops.begin()+1);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
@@ -6635,7 +5347,7 @@
case NEON::BI__builtin_neon_vld4_lane_v:
case NEON::BI__builtin_neon_vld4q_lane_v: {
llvm::Type *Tys[2] = { VTy, Ops[1]->getType() };
- Function *F = CGM.getIntrinsic(Intrinsic::arm64_neon_ld4lane, Tys);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4lane, Tys);
Ops.push_back(Ops[1]);
Ops.erase(Ops.begin()+1);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
@@ -6655,7 +5367,7 @@
Ops.push_back(Ops[0]);
Ops.erase(Ops.begin());
llvm::Type *Tys[2] = { VTy, Ops[2]->getType() };
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_st2, Tys),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st2, Tys),
Ops, "");
}
case NEON::BI__builtin_neon_vst2_lane_v:
@@ -6665,7 +5377,7 @@
Ops[2] = Builder.CreateZExt(Ops[2],
llvm::IntegerType::get(getLLVMContext(), 64));
llvm::Type *Tys[2] = { VTy, Ops[3]->getType() };
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_st2lane, Tys),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st2lane, Tys),
Ops, "");
}
case NEON::BI__builtin_neon_vst3_v:
@@ -6673,7 +5385,7 @@
Ops.push_back(Ops[0]);
Ops.erase(Ops.begin());
llvm::Type *Tys[2] = { VTy, Ops[3]->getType() };
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_st3, Tys),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st3, Tys),
Ops, "");
}
case NEON::BI__builtin_neon_vst3_lane_v:
@@ -6683,7 +5395,7 @@
Ops[3] = Builder.CreateZExt(Ops[3],
llvm::IntegerType::get(getLLVMContext(), 64));
llvm::Type *Tys[2] = { VTy, Ops[4]->getType() };
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_st3lane, Tys),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st3lane, Tys),
Ops, "");
}
case NEON::BI__builtin_neon_vst4_v:
@@ -6691,7 +5403,7 @@
Ops.push_back(Ops[0]);
Ops.erase(Ops.begin());
llvm::Type *Tys[2] = { VTy, Ops[4]->getType() };
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_st4, Tys),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st4, Tys),
Ops, "");
}
case NEON::BI__builtin_neon_vst4_lane_v:
@@ -6701,7 +5413,7 @@
Ops[4] = Builder.CreateZExt(Ops[4],
llvm::IntegerType::get(getLLVMContext(), 64));
llvm::Type *Tys[2] = { VTy, Ops[5]->getType() };
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_st4lane, Tys),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st4lane, Tys),
Ops, "");
}
case NEON::BI__builtin_neon_vtrn_v:
@@ -6709,7 +5421,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Value *SV = 0;
+ Value *SV = nullptr;
for (unsigned vi = 0; vi != 2; ++vi) {
SmallVector<Constant*, 16> Indices;
@@ -6729,7 +5441,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Value *SV = 0;
+ Value *SV = nullptr;
for (unsigned vi = 0; vi != 2; ++vi) {
SmallVector<Constant*, 16> Indices;
@@ -6748,7 +5460,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Value *SV = 0;
+ Value *SV = nullptr;
for (unsigned vi = 0; vi != 2; ++vi) {
SmallVector<Constant*, 16> Indices;
@@ -6764,45 +5476,45 @@
return SV;
}
case NEON::BI__builtin_neon_vqtbl1q_v: {
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_tbl1, Ty),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl1, Ty),
Ops, "vtbl1");
}
case NEON::BI__builtin_neon_vqtbl2q_v: {
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_tbl2, Ty),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl2, Ty),
Ops, "vtbl2");
}
case NEON::BI__builtin_neon_vqtbl3q_v: {
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_tbl3, Ty),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl3, Ty),
Ops, "vtbl3");
}
case NEON::BI__builtin_neon_vqtbl4q_v: {
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_tbl4, Ty),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl4, Ty),
Ops, "vtbl4");
}
case NEON::BI__builtin_neon_vqtbx1q_v: {
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_tbx1, Ty),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx1, Ty),
Ops, "vtbx1");
}
case NEON::BI__builtin_neon_vqtbx2q_v: {
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_tbx2, Ty),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx2, Ty),
Ops, "vtbx2");
}
case NEON::BI__builtin_neon_vqtbx3q_v: {
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_tbx3, Ty),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx3, Ty),
Ops, "vtbx3");
}
case NEON::BI__builtin_neon_vqtbx4q_v: {
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm64_neon_tbx4, Ty),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx4, Ty),
Ops, "vtbx4");
}
case NEON::BI__builtin_neon_vsqadd_v:
case NEON::BI__builtin_neon_vsqaddq_v: {
- Int = Intrinsic::arm64_neon_usqadd;
+ Int = Intrinsic::aarch64_neon_usqadd;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqadd");
}
case NEON::BI__builtin_neon_vuqadd_v:
case NEON::BI__builtin_neon_vuqaddq_v: {
- Int = Intrinsic::arm64_neon_suqadd;
+ Int = Intrinsic::aarch64_neon_suqadd;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vuqadd");
}
}
@@ -6860,7 +5572,7 @@
}
switch (BuiltinID) {
- default: return 0;
+ default: return nullptr;
case X86::BI_mm_prefetch: {
Value *Address = EmitScalarExpr(E->getArg(0));
Value *RW = ConstantInt::get(Int32Ty, 0);
@@ -7037,7 +5749,7 @@
// 3DNow!
case X86::BI__builtin_ia32_pswapdsf:
case X86::BI__builtin_ia32_pswapdsi: {
- const char *name = 0;
+ const char *name = nullptr;
Intrinsic::ID ID = Intrinsic::not_intrinsic;
switch(BuiltinID) {
default: llvm_unreachable("Unsupported intrinsic!");
@@ -7106,7 +5818,7 @@
Intrinsic::ID ID = Intrinsic::not_intrinsic;
switch (BuiltinID) {
- default: return 0;
+ default: return nullptr;
// vec_ld, vec_lvsl, vec_lvsr
case PPC::BI__builtin_altivec_lvx:
diff --git a/lib/CodeGen/CGCUDARuntime.cpp b/lib/CodeGen/CGCUDARuntime.cpp
index 54a28f5..29e0a91 100644
--- a/lib/CodeGen/CGCUDARuntime.cpp
+++ b/lib/CodeGen/CGCUDARuntime.cpp
@@ -37,7 +37,7 @@
eval.begin(CGF);
CGF.EmitBlock(ConfigOKBlock);
- const Decl *TargetDecl = 0;
+ const Decl *TargetDecl = nullptr;
if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E->getCallee())) {
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
TargetDecl = DRE->getDecl();
@@ -52,5 +52,5 @@
CGF.EmitBlock(ContBlock);
eval.end(CGF);
- return RValue::get(0);
+ return RValue::get(nullptr);
}
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index ef29af7..55c06f6 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -61,15 +61,15 @@
return true;
// Try to find a unique base class with a non-trivial destructor.
- const CXXRecordDecl *UniqueBase = 0;
+ const CXXRecordDecl *UniqueBase = nullptr;
for (const auto &I : Class->bases()) {
// We're in the base destructor, so skip virtual bases.
if (I.isVirtual()) continue;
// Skip base classes with trivial destructors.
- const CXXRecordDecl *Base
- = cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
+ const auto *Base =
+ cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
if (Base->hasTrivialDestructor()) continue;
// If we've already found a base class with a non-trivial
@@ -137,13 +137,13 @@
// Find the referent. Some aliases might require a bitcast, in
// which case the caller is responsible for ensuring the soundness
// of these semantics.
- llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
- llvm::Constant *Aliasee = Ref;
- if (Ref->getType() != AliasType)
- Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
+ auto *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
+ auto *Aliasee = dyn_cast<llvm::GlobalObject>(Ref);
+ if (!Aliasee)
+ Aliasee = cast<llvm::GlobalAlias>(Ref)->getAliasee();
// Instead of creating as alias to a linkonce_odr, replace all of the uses
- // of the aliassee.
+ // of the aliasee.
if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
(TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
!TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
@@ -152,7 +152,10 @@
// members with attribute "AlwaysInline" and expect no reference to
// be generated. It is desirable to reenable this optimisation after
// corresponding LLVM changes.
- Replacements[MangledName] = Aliasee;
+ llvm::Constant *Replacement = Aliasee;
+ if (Aliasee->getType() != AliasType)
+ Replacement = llvm::ConstantExpr::getBitCast(Aliasee, AliasType);
+ Replacements[MangledName] = Replacement;
return false;
}
@@ -160,7 +163,7 @@
/// If we don't have a definition for the destructor yet, don't
/// emit. We can't emit aliases to declarations; that's just not
/// how aliases work.
- if (Ref->isDeclaration())
+ if (Aliasee->isDeclaration())
return true;
}
@@ -172,8 +175,8 @@
return true;
// Create the alias with no name.
- llvm::GlobalAlias *Alias =
- new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
+ auto *Alias = llvm::GlobalAlias::create(AliasType->getElementType(), 0,
+ Linkage, "", Aliasee);
// Switch any previous uses to the alias.
if (Entry) {
@@ -211,13 +214,13 @@
const CGFunctionInfo &fnInfo =
getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
- llvm::Function *fn = cast<llvm::Function>(
+ auto *fn = cast<llvm::Function>(
GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo, true));
setFunctionLinkage(GlobalDecl(ctor, ctorType), fn);
CodeGenFunction(*this).GenerateCode(GlobalDecl(ctor, ctorType), fn, fnInfo);
- SetFunctionDefinitionAttributes(ctor, fn);
+ setFunctionDefinitionAttributes(ctor, fn);
SetLLVMFunctionAttributesForDefinition(ctor, fn);
}
@@ -268,13 +271,13 @@
const CGFunctionInfo &fnInfo =
getTypes().arrangeCXXDestructor(dtor, dtorType);
- llvm::Function *fn = cast<llvm::Function>(
- GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo, 0, true));
+ auto *fn = cast<llvm::Function>(
+ GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo, nullptr, true));
setFunctionLinkage(GlobalDecl(dtor, dtorType), fn);
CodeGenFunction(*this).GenerateCode(GlobalDecl(dtor, dtorType), fn, fnInfo);
- SetFunctionDefinitionAttributes(dtor, fn);
+ setFunctionDefinitionAttributes(dtor, fn);
SetLLVMFunctionAttributesForDefinition(dtor, fn);
}
@@ -335,9 +338,9 @@
QualType T = QualType(QTy, 0);
const RecordType *RT = T->getAs<RecordType>();
assert(RT && "BuildAppleKextVirtualCall - Qual type must be record");
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-
- if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
+ const auto *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD))
return BuildAppleKextVirtualDestructorCall(DD, Dtor_Complete, RD);
return ::BuildAppleKextVirtualCall(*this, MD, Ty, RD);
@@ -350,7 +353,7 @@
const CXXDestructorDecl *DD,
CXXDtorType Type,
const CXXRecordDecl *RD) {
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(DD);
+ const auto *MD = cast<CXXMethodDecl>(DD);
// FIXME. Dtor_Base dtor is always direct!!
// It need be somehow inline expanded into the caller.
// -O does that. But need to support -O0 as well.
@@ -361,5 +364,5 @@
llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
}
- return 0;
+ return nullptr;
}
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index 2bb3907..1f0de31 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -28,6 +28,41 @@
<< S;
}
+bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const {
+ // If RD has a non-trivial move or copy constructor, we cannot copy the
+ // argument.
+ if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialMoveConstructor())
+ return false;
+
+ // If RD has a non-trivial destructor, we cannot copy the argument.
+ if (RD->hasNonTrivialDestructor())
+ return false;
+
+ // We can only copy the argument if there exists at least one trivial,
+ // non-deleted copy or move constructor.
+ // FIXME: This assumes that all lazily declared copy and move constructors are
+ // not deleted. This assumption might not be true in some corner cases.
+ bool CopyDeleted = false;
+ bool MoveDeleted = false;
+ for (const CXXConstructorDecl *CD : RD->ctors()) {
+ if (CD->isCopyConstructor() || CD->isMoveConstructor()) {
+ assert(CD->isTrivial());
+ // We had at least one undeleted trivial copy or move ctor. Return
+ // directly.
+ if (!CD->isDeleted())
+ return true;
+ if (CD->isCopyConstructor())
+ CopyDeleted = true;
+ else
+ MoveDeleted = true;
+ }
+ }
+
+ // If all trivial copy and move constructors are deleted, we cannot copy the
+ // argument.
+ return !(CopyDeleted && MoveDeleted);
+}
+
llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
}
@@ -121,7 +156,7 @@
// FIXME: I'm not entirely sure I like using a fake decl just for code
// generation. Maybe we can come up with a better way?
ImplicitParamDecl *ThisDecl
- = ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(),
+ = ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(),
&CGM.getContext().Idents.get("this"),
MD->getThisType(CGM.getContext()));
params.push_back(ThisDecl);
@@ -159,7 +194,7 @@
QualType ElementType) {
// Should never be called.
ErrorUnsupportedABI(CGF, "array cookie initialization");
- return 0;
+ return nullptr;
}
bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
@@ -193,7 +228,7 @@
// If we don't need an array cookie, bail out early.
if (!requiresArrayCookie(expr, eltTy)) {
allocPtr = ptr;
- numElements = 0;
+ numElements = nullptr;
cookieSize = CharUnits::Zero();
return;
}
@@ -272,7 +307,7 @@
llvm_unreachable("shouldn't be called in this ABI");
ErrorUnsupportedABI(CGF, "complete object detection in ctor");
- return 0;
+ return nullptr;
}
void CGCXXABI::EmitThreadLocalInitFuncs(
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index beaec2c..615ec23 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -19,23 +19,23 @@
#include "clang/Basic/LLVM.h"
namespace llvm {
- class Constant;
- class Type;
- class Value;
+class Constant;
+class Type;
+class Value;
}
namespace clang {
- class CastExpr;
- class CXXConstructorDecl;
- class CXXDestructorDecl;
- class CXXMethodDecl;
- class CXXRecordDecl;
- class FieldDecl;
- class MangleContext;
+class CastExpr;
+class CXXConstructorDecl;
+class CXXDestructorDecl;
+class CXXMethodDecl;
+class CXXRecordDecl;
+class FieldDecl;
+class MangleContext;
namespace CodeGen {
- class CodeGenFunction;
- class CodeGenModule;
+class CodeGenFunction;
+class CodeGenModule;
/// \brief Implements C++ ABI-specific code generation functions.
class CGCXXABI {
@@ -93,8 +93,9 @@
/// when called virtually, and code generation does not support the case.
virtual bool HasThisReturn(GlobalDecl GD) const { return false; }
- /// Returns true if the given record type should be returned indirectly.
- virtual bool isReturnTypeIndirect(const CXXRecordDecl *RD) const = 0;
+ /// If the C++ ABI requires the given type be returned in a particular way,
+ /// this method sets RetAI and returns true.
+ virtual bool classifyReturnType(CGFunctionInfo &FI) const = 0;
/// Specify how one should pass an argument of a record type.
enum RecordArgABI {
@@ -111,9 +112,17 @@
RAA_Indirect
};
+ /// Returns true if C++ allows us to copy the memory of an object of type RD
+ /// when it is passed as an argument.
+ bool canCopyArgument(const CXXRecordDecl *RD) const;
+
/// Returns how an argument of the given record type should be passed.
virtual RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const = 0;
+ /// Returns true if the implicit 'sret' parameter comes after the implicit
+ /// 'this' parameter of C++ instance methods.
+ virtual bool isSRetParameterAfterThis() const { return false; }
+
/// Find the LLVM type used to represent the given member pointer
/// type.
virtual llvm::Type *
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index e26d6b2d..d0849d3 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -158,6 +158,23 @@
return CC_C;
}
+static bool isAAPCSVFP(const CGFunctionInfo &FI, const TargetInfo &Target) {
+ switch (FI.getEffectiveCallingConvention()) {
+ case llvm::CallingConv::C:
+ switch (Target.getTriple().getEnvironment()) {
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::GNUEABIHF:
+ return true;
+ default:
+ return false;
+ }
+ case llvm::CallingConv::ARM_AAPCS_VFP:
+ return true;
+ default:
+ return false;
+ }
+}
+
/// Arrange the argument and result information for a call to an
/// unknown C++ non-static member function of the given abstract type.
/// (Zero value of RD means we don't have any meaningful "this" argument type,
@@ -474,7 +491,7 @@
CGFunctionInfo::Profile(ID, IsInstanceMethod, info, required, resultType,
argTypes);
- void *insertPos = 0;
+ void *insertPos = nullptr;
CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
if (FI)
return *FI;
@@ -494,11 +511,11 @@
// them are direct or extend without a specified coerce type, specify the
// default now.
ABIArgInfo &retInfo = FI->getReturnInfo();
- if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == 0)
+ if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == nullptr)
retInfo.setCoerceToType(ConvertType(FI->getReturnType()));
for (auto &I : FI->arguments())
- if (I.info.canHaveCoerceToType() && I.info.getCoerceToType() == 0)
+ if (I.info.canHaveCoerceToType() && I.info.getCoerceToType() == nullptr)
I.info.setCoerceToType(ConvertType(I.type));
bool erased = FunctionsBeingProcessed.erase(FI); (void)erased;
@@ -525,7 +542,7 @@
FI->Required = required;
FI->HasRegParm = info.getHasRegParm();
FI->RegParm = info.getRegParm();
- FI->ArgStruct = 0;
+ FI->ArgStruct = nullptr;
FI->NumArgs = argTypes.size();
FI->getArgsBuffer()[0].type = resultType;
for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
@@ -548,7 +565,7 @@
if (RD->isUnion()) {
// Unions can be here only in degenerative cases - all the fields are same
// after flattening. Thus we have to use the "largest" field.
- const FieldDecl *LargestFD = 0;
+ const FieldDecl *LargestFD = nullptr;
CharUnits UnionSize = CharUnits::Zero();
for (const auto *FD : RD->fields()) {
@@ -596,7 +613,7 @@
if (RD->isUnion()) {
// Unions can be here only in degenerative cases - all the fields are same
// after flattening. Thus we have to use the "largest" field.
- const FieldDecl *LargestFD = 0;
+ const FieldDecl *LargestFD = nullptr;
CharUnits UnionSize = CharUnits::Zero();
for (const auto *FD : RD->fields()) {
@@ -700,8 +717,9 @@
if (DL.isBigEndian()) {
// Preserve the high bits on big-endian targets.
// That is what memory coercion does.
- uint64_t SrcSize = DL.getTypeAllocSizeInBits(Val->getType());
- uint64_t DstSize = DL.getTypeAllocSizeInBits(DestIntTy);
+ uint64_t SrcSize = DL.getTypeSizeInBits(Val->getType());
+ uint64_t DstSize = DL.getTypeSizeInBits(DestIntTy);
+
if (SrcSize > DstSize) {
Val = CGF.Builder.CreateLShr(Val, SrcSize - DstSize, "coerce.highbits");
Val = CGF.Builder.CreateTrunc(Val, DestIntTy, "coerce.val.ii");
@@ -922,8 +940,9 @@
bool Inserted = FunctionsBeingProcessed.insert(&FI); (void)Inserted;
assert(Inserted && "Recursively being processed?");
+ bool SwapThisWithSRet = false;
SmallVector<llvm::Type*, 8> argTypes;
- llvm::Type *resultType = 0;
+ llvm::Type *resultType = nullptr;
const ABIArgInfo &retAI = FI.getReturnInfo();
switch (retAI.getKind()) {
@@ -955,6 +974,8 @@
llvm::Type *ty = ConvertType(ret);
unsigned addressSpace = Context.getTargetAddressSpace(ret);
argTypes.push_back(llvm::PointerType::get(ty, addressSpace));
+
+ SwapThisWithSRet = retAI.isSRetAfterThis();
break;
}
@@ -994,8 +1015,11 @@
// If the coerce-to type is a first class aggregate, flatten it. Either
// way is semantically identical, but fast-isel and the optimizer
// generally likes scalar values better than FCAs.
+ // We cannot do this for functions using the AAPCS calling convention,
+ // as structures are treated differently by that calling convention.
llvm::Type *argType = argAI.getCoerceToType();
- if (llvm::StructType *st = dyn_cast<llvm::StructType>(argType)) {
+ llvm::StructType *st = dyn_cast<llvm::StructType>(argType);
+ if (st && !isAAPCSVFP(FI, getTarget())) {
for (unsigned i = 0, e = st->getNumElements(); i != e; ++i)
argTypes.push_back(st->getElementType(i));
} else {
@@ -1014,6 +1038,9 @@
if (llvm::StructType *ArgStruct = FI.getArgStruct())
argTypes.push_back(ArgStruct->getPointerTo());
+ if (SwapThisWithSRet)
+ std::swap(argTypes[0], argTypes[1]);
+
bool Erased = FunctionsBeingProcessed.erase(&FI); (void)Erased;
assert(Erased && "Not in set?");
@@ -1090,6 +1117,9 @@
FuncAttrs.addAttribute(llvm::Attribute::NoRedZone);
if (CodeGenOpts.NoImplicitFloat)
FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat);
+ if (CodeGenOpts.EnableSegmentedStacks &&
+ !(TargetDecl && TargetDecl->hasAttr<NoSplitStackAttr>()))
+ FuncAttrs.addAttribute("split-stack");
if (AttrOnCallSite) {
// Attributes that should go on the call site only.
@@ -1126,6 +1156,7 @@
QualType RetTy = FI.getReturnType();
unsigned Index = 1;
+ bool SwapThisWithSRet = false;
const ABIArgInfo &RetAI = FI.getReturnInfo();
switch (RetAI.getKind()) {
case ABIArgInfo::Extend:
@@ -1153,10 +1184,12 @@
SRETAttrs.addAttribute(llvm::Attribute::StructRet);
if (RetAI.getInReg())
SRETAttrs.addAttribute(llvm::Attribute::InReg);
- PAL.push_back(llvm::
- AttributeSet::get(getLLVMContext(), Index, SRETAttrs));
+ SwapThisWithSRet = RetAI.isSRetAfterThis();
+ PAL.push_back(llvm::AttributeSet::get(
+ getLLVMContext(), SwapThisWithSRet ? 2 : Index, SRETAttrs));
- ++Index;
+ if (!SwapThisWithSRet)
+ ++Index;
// sret disables readnone and readonly
FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly)
.removeAttribute(llvm::Attribute::ReadNone);
@@ -1178,6 +1211,11 @@
const ABIArgInfo &AI = I.info;
llvm::AttrBuilder Attrs;
+ // Skip over the sret parameter when it comes second. We already handled it
+ // above.
+ if (Index == 2 && SwapThisWithSRet)
+ ++Index;
+
if (AI.getPaddingType()) {
if (AI.getPaddingInReg())
PAL.push_back(llvm::AttributeSet::get(getLLVMContext(), Index,
@@ -1196,14 +1234,15 @@
else if (ParamType->isUnsignedIntegerOrEnumerationType())
Attrs.addAttribute(llvm::Attribute::ZExt);
// FALL THROUGH
- case ABIArgInfo::Direct:
+ case ABIArgInfo::Direct: {
if (AI.getInReg())
Attrs.addAttribute(llvm::Attribute::InReg);
// FIXME: handle sseregparm someday...
- if (llvm::StructType *STy =
- dyn_cast<llvm::StructType>(AI.getCoerceToType())) {
+ llvm::StructType *STy =
+ dyn_cast<llvm::StructType>(AI.getCoerceToType());
+ if (!isAAPCSVFP(FI, getTarget()) && STy) {
unsigned Extra = STy->getNumElements()-1; // 1 will be added below.
if (Attrs.hasAttributes())
for (unsigned I = 0; I < Extra; ++I)
@@ -1212,7 +1251,7 @@
Index += Extra;
}
break;
-
+ }
case ABIArgInfo::Indirect:
if (AI.getInReg())
Attrs.addAttribute(llvm::Attribute::InReg);
@@ -1312,7 +1351,7 @@
// If we're using inalloca, all the memory arguments are GEPs off of the last
// parameter, which is a pointer to the complete memory area.
- llvm::Value *ArgStruct = 0;
+ llvm::Value *ArgStruct = nullptr;
if (FI.usesInAlloca()) {
llvm::Function::arg_iterator EI = Fn->arg_end();
--EI;
@@ -1320,13 +1359,20 @@
assert(ArgStruct->getType() == FI.getArgStruct()->getPointerTo());
}
- // Name the struct return argument.
- if (CGM.ReturnTypeUsesSRet(FI)) {
+ // Name the struct return parameter, which can come first or second.
+ const ABIArgInfo &RetAI = FI.getReturnInfo();
+ bool SwapThisWithSRet = false;
+ if (RetAI.isIndirect()) {
+ SwapThisWithSRet = RetAI.isSRetAfterThis();
+ if (SwapThisWithSRet)
+ ++AI;
AI->setName("agg.result");
- AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
- AI->getArgNo() + 1,
+ AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), AI->getArgNo() + 1,
llvm::Attribute::NoAlias));
- ++AI;
+ if (SwapThisWithSRet)
+ --AI; // Go back to the beginning for 'this'.
+ else
+ ++AI; // Skip the sret parameter.
}
// Track if we received the parameter as a pointer (indirect, byval, or
@@ -1471,8 +1517,10 @@
// If the coerce-to type is a first class aggregate, we flatten it and
// pass the elements. Either way is semantically identical, but fast-isel
// and the optimizer generally likes scalar values better than FCAs.
+ // We cannot do this for functions using the AAPCS calling convention,
+ // as structures are treated differently by that calling convention.
llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
- if (STy && STy->getNumElements() > 1) {
+ if (!isAAPCSVFP(FI, getTarget()) && STy && STy->getNumElements() > 1) {
uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(STy);
llvm::Type *DstTy =
cast<llvm::PointerType>(Ptr->getType())->getElementType();
@@ -1554,6 +1602,9 @@
}
++AI;
+
+ if (ArgNo == 1 && SwapThisWithSRet)
+ ++AI; // Skip the sret parameter.
}
if (FI.usesInAlloca())
@@ -1587,8 +1638,8 @@
llvm::Value *result) {
// We must be immediately followed the cast.
llvm::BasicBlock *BB = CGF.Builder.GetInsertBlock();
- if (BB->empty()) return 0;
- if (&BB->back() != result) return 0;
+ if (BB->empty()) return nullptr;
+ if (&BB->back() != result) return nullptr;
llvm::Type *resultType = result->getType();
@@ -1606,7 +1657,7 @@
// Require the generator to be immediately followed by the cast.
if (generator->getNextNode() != bitcast)
- return 0;
+ return nullptr;
insnsToKill.push_back(bitcast);
}
@@ -1616,7 +1667,7 @@
// or
// %generator = call i8* @objc_retainAutoreleasedReturnValue(i8* %originalResult)
llvm::CallInst *call = dyn_cast<llvm::CallInst>(generator);
- if (!call) return 0;
+ if (!call) return nullptr;
bool doRetainAutorelease;
@@ -1644,7 +1695,7 @@
insnsToKill.push_back(prev);
}
} else {
- return 0;
+ return nullptr;
}
result = call->getArgOperand(0);
@@ -1677,16 +1728,16 @@
// This is only applicable to a method with an immutable 'self'.
const ObjCMethodDecl *method =
dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl);
- if (!method) return 0;
+ if (!method) return nullptr;
const VarDecl *self = method->getSelfDecl();
- if (!self->getType().isConstQualified()) return 0;
+ if (!self->getType().isConstQualified()) return nullptr;
// Look for a retain call.
llvm::CallInst *retainCall =
dyn_cast<llvm::CallInst>(result->stripPointerCasts());
if (!retainCall ||
retainCall->getCalledValue() != CGF.CGM.getARCEntrypoints().objc_retain)
- return 0;
+ return nullptr;
// Look for an ordinary load of 'self'.
llvm::Value *retainedValue = retainCall->getArgOperand(0);
@@ -1694,7 +1745,7 @@
dyn_cast<llvm::LoadInst>(retainedValue->stripPointerCasts());
if (!load || load->isAtomic() || load->isVolatile() ||
load->getPointerOperand() != CGF.GetAddrOfLocalVar(self))
- return 0;
+ return nullptr;
// Okay! Burn it all down. This relies for correctness on the
// assumption that the retain is emitted as part of the return and
@@ -1736,17 +1787,17 @@
// with noreturn cleanups.
if (!CGF.ReturnValue->hasOneUse()) {
llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock();
- if (IP->empty()) return 0;
+ if (IP->empty()) return nullptr;
llvm::StoreInst *store = dyn_cast<llvm::StoreInst>(&IP->back());
- if (!store) return 0;
- if (store->getPointerOperand() != CGF.ReturnValue) return 0;
+ if (!store) return nullptr;
+ if (store->getPointerOperand() != CGF.ReturnValue) return nullptr;
assert(!store->isAtomic() && !store->isVolatile()); // see below
return store;
}
llvm::StoreInst *store =
dyn_cast<llvm::StoreInst>(CGF.ReturnValue->user_back());
- if (!store) return 0;
+ if (!store) return nullptr;
// These aren't actually possible for non-coerced returns, and we
// only care about non-coerced returns on this code path.
@@ -1758,7 +1809,7 @@
llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock();
while (IP != StoreBB) {
if (!(IP = IP->getSinglePredecessor()))
- return 0;
+ return nullptr;
}
// Okay, the store's basic block dominates the insertion point; we
@@ -1770,13 +1821,13 @@
bool EmitRetDbgLoc,
SourceLocation EndLoc) {
// Functions with no result always return void.
- if (ReturnValue == 0) {
+ if (!ReturnValue) {
Builder.CreateRetVoid();
return;
}
llvm::DebugLoc RetDbgLoc;
- llvm::Value *RV = 0;
+ llvm::Value *RV = nullptr;
QualType RetTy = FI.getReturnType();
const ABIArgInfo &RetAI = FI.getReturnInfo();
@@ -1796,13 +1847,15 @@
break;
case ABIArgInfo::Indirect: {
+ auto AI = CurFn->arg_begin();
+ if (RetAI.isSRetAfterThis())
+ ++AI;
switch (getEvaluationKind(RetTy)) {
case TEK_Complex: {
ComplexPairTy RT =
EmitLoadOfComplex(MakeNaturalAlignAddrLValue(ReturnValue, RetTy),
EndLoc);
- EmitStoreOfComplex(RT,
- MakeNaturalAlignAddrLValue(CurFn->arg_begin(), RetTy),
+ EmitStoreOfComplex(RT, MakeNaturalAlignAddrLValue(AI, RetTy),
/*isInit*/ true);
break;
}
@@ -1811,7 +1864,7 @@
break;
case TEK_Scalar:
EmitStoreOfScalar(Builder.CreateLoad(ReturnValue),
- MakeNaturalAlignAddrLValue(CurFn->arg_begin(), RetTy),
+ MakeNaturalAlignAddrLValue(AI, RetTy),
/*isInit*/ true);
break;
}
@@ -1840,7 +1893,7 @@
// If that was the only use of the return value, nuke it as well now.
if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
- ReturnValue = 0;
+ ReturnValue = nullptr;
}
// Otherwise, we have to do a simple load.
@@ -1958,7 +2011,7 @@
assert(!isProvablyNull(srcAddr) &&
"shouldn't have writeback for provably null argument");
- llvm::BasicBlock *contBB = 0;
+ llvm::BasicBlock *contBB = nullptr;
// If the argument wasn't provably non-null, we need to null check
// before doing the store.
@@ -2039,7 +2092,7 @@
if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E->IgnoreParens()))
if (uop->getOpcode() == UO_AddrOf)
return uop->getSubExpr();
- return 0;
+ return nullptr;
}
/// Emit an argument that's being passed call-by-writeback. That is,
@@ -2093,9 +2146,9 @@
cast<llvm::PointerType>(destType->getElementType()));
CGF.Builder.CreateStore(null, temp);
}
-
- llvm::BasicBlock *contBB = 0;
- llvm::BasicBlock *originBB = 0;
+
+ llvm::BasicBlock *contBB = nullptr;
+ llvm::BasicBlock *originBB = nullptr;
// If the address is *not* known to be non-null, we need to switch.
llvm::Value *finalArgument;
@@ -2122,7 +2175,7 @@
}
}
- llvm::Value *valueToUse = 0;
+ llvm::Value *valueToUse = nullptr;
// Perform a copy if necessary.
if (shouldCopy) {
@@ -2284,16 +2337,28 @@
// In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
// However, we still have to push an EH-only cleanup in case we unwind before
// we make it to the call.
- if (HasAggregateEvalKind && args.isUsingInAlloca()) {
- assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
- AggValueSlot Slot = createPlaceholderSlot(*this, type);
- Slot.setExternallyDestructed();
+ if (HasAggregateEvalKind &&
+ CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
+ // If we're using inalloca, use the argument memory. Otherwise, use a
+ // temporary.
+ AggValueSlot Slot;
+ if (args.isUsingInAlloca())
+ Slot = createPlaceholderSlot(*this, type);
+ else
+ Slot = CreateAggTemp(type, "agg.tmp");
+
+ const CXXRecordDecl *RD = type->getAsCXXRecordDecl();
+ bool DestroyedInCallee =
+ RD && RD->hasNonTrivialDestructor() &&
+ CGM.getCXXABI().getRecordArgABI(RD) != CGCXXABI::RAA_Default;
+ if (DestroyedInCallee)
+ Slot.setExternallyDestructed();
+
EmitAggExpr(E, Slot);
RValue RV = Slot.asRValue();
args.add(RV, type);
- const CXXRecordDecl *RD = type->getAsCXXRecordDecl();
- if (RD->hasNonTrivialDestructor()) {
+ if (DestroyedInCallee) {
// Create a no-op GEP between the placeholder and the cleanup so we can
// RAUW it successfully. It also serves as a marker of the first
// instruction where the cleanup is active.
@@ -2467,7 +2532,7 @@
LValue LV = MakeAddrLValue(RV.getAggregateAddr(), Ty);
if (RD->isUnion()) {
- const FieldDecl *LargestFD = 0;
+ const FieldDecl *LargestFD = nullptr;
CharUnits UnionSize = CharUnits::Zero();
for (const auto *FD : RD->fields()) {
@@ -2544,10 +2609,16 @@
// 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 = 0;
+ llvm::Value *ArgMemory = nullptr;
if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) {
- llvm::AllocaInst *AI = new llvm::AllocaInst(
- ArgStruct, "argmem", CallArgs.getStackBase()->getNextNode());
+ llvm::Instruction *IP = CallArgs.getStackBase();
+ llvm::AllocaInst *AI;
+ if (IP) {
+ IP = IP->getNextNode();
+ AI = new llvm::AllocaInst(ArgStruct, "argmem", IP);
+ } else {
+ AI = CreateTempAlloca(ArgStruct, "argmem");
+ }
AI->setUsedWithInAlloca(true);
assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca());
ArgMemory = AI;
@@ -2555,14 +2626,20 @@
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
- llvm::Value *SRetPtr = 0;
- if (CGM.ReturnTypeUsesSRet(CallInfo) || RetAI.isInAlloca()) {
+ llvm::Value *SRetPtr = nullptr;
+ bool SwapThisWithSRet = false;
+ if (RetAI.isIndirect() || RetAI.isInAlloca()) {
SRetPtr = ReturnValue.getValue();
if (!SRetPtr)
SRetPtr = CreateMemTemp(RetTy);
- if (CGM.ReturnTypeUsesSRet(CallInfo)) {
+ if (RetAI.isIndirect()) {
Args.push_back(SRetPtr);
+ SwapThisWithSRet = RetAI.isSRetAfterThis();
+ if (SwapThisWithSRet)
+ IRArgNo = 1;
checkArgMatches(SRetPtr, IRArgNo, IRFuncTy);
+ if (SwapThisWithSRet)
+ IRArgNo = 0;
} else {
llvm::Value *Addr =
Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex());
@@ -2578,6 +2655,10 @@
const ABIArgInfo &ArgInfo = info_it->info;
RValue RV = I->RV;
+ // Skip 'sret' if it came second.
+ if (IRArgNo == 1 && SwapThisWithSRet)
+ ++IRArgNo;
+
CharUnits TypeAlign = getContext().getTypeAlignInChars(I->Ty);
// Insert a padding argument to ensure proper alignment.
@@ -2714,8 +2795,11 @@
// If the coerce-to type is a first class aggregate, we flatten it and
// pass the elements. Either way is semantically identical, but fast-isel
// and the optimizer generally likes scalar values better than FCAs.
- if (llvm::StructType *STy =
- dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType())) {
+ // We cannot do this for functions using the AAPCS calling convention,
+ // as structures are treated differently by that calling convention.
+ llvm::StructType *STy =
+ dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
+ if (STy && !isAAPCSVFP(CallInfo, getTarget())) {
llvm::Type *SrcTy =
cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
@@ -2764,6 +2848,9 @@
}
}
+ if (SwapThisWithSRet)
+ std::swap(Args[0], Args[1]);
+
if (ArgMemory) {
llvm::Value *Arg = ArgMemory;
llvm::Type *LastParamTy =
@@ -2832,7 +2919,7 @@
llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
AttributeList);
- llvm::BasicBlock *InvokeDest = 0;
+ llvm::BasicBlock *InvokeDest = nullptr;
if (!Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoUnwind))
InvokeDest = getInvokeDest();
@@ -2848,6 +2935,12 @@
if (callOrInvoke)
*callOrInvoke = CS.getInstruction();
+ if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
+ !CS.hasFnAttr(llvm::Attribute::NoInline))
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::AlwaysInline);
+
CS.setAttributes(Attrs);
CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index 2e43d1d..9510a1c 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -56,7 +56,7 @@
class CallArgList :
public SmallVector<CallArg, 16> {
public:
- CallArgList() : StackBase(0), StackBaseMem(0) {}
+ CallArgList() : StackBase(nullptr), StackBaseMem(nullptr) {}
struct Writeback {
/// The original argument. Note that the argument l-value
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 071f8b3..97bea97 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -66,8 +66,8 @@
ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
PathBegin, PathEnd);
if (Offset.isZero())
- return 0;
-
+ return nullptr;
+
llvm::Type *PtrDiffTy =
Types.ConvertType(getContext().getPointerDiffType());
@@ -114,7 +114,7 @@
CharUnits nonVirtualOffset,
llvm::Value *virtualOffset) {
// Assert that we have something to do.
- assert(!nonVirtualOffset.isZero() || virtualOffset != 0);
+ assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
// Compute the offset from the static and dynamic components.
llvm::Value *baseOffset;
@@ -143,8 +143,8 @@
assert(PathBegin != PathEnd && "Base path should not be empty!");
CastExpr::path_const_iterator Start = PathBegin;
- const CXXRecordDecl *VBase = 0;
-
+ const CXXRecordDecl *VBase = nullptr;
+
// Sema has done some convenient canonicalization here: if the
// access path involved any virtual steps, the conversion path will
// *start* with a step down to the correct virtual base subobject,
@@ -169,7 +169,7 @@
const ASTRecordLayout &layout = getContext().getASTRecordLayout(Derived);
CharUnits vBaseOffset = layout.getVBaseClassOffset(VBase);
NonVirtualOffset += vBaseOffset;
- VBase = 0; // we no longer have a virtual step
+ VBase = nullptr; // we no longer have a virtual step
}
// Get the base pointer type.
@@ -180,11 +180,11 @@
// just do a bitcast; null checks are unnecessary.
if (NonVirtualOffset.isZero() && !VBase) {
return Builder.CreateBitCast(Value, BasePtrTy);
- }
+ }
- llvm::BasicBlock *origBB = 0;
- llvm::BasicBlock *endBB = 0;
-
+ llvm::BasicBlock *origBB = nullptr;
+ llvm::BasicBlock *endBB = nullptr;
+
// Skip over the offset (and the vtable load) if we're supposed to
// null-check the pointer.
if (NullCheckValue) {
@@ -198,7 +198,7 @@
}
// Compute the virtual offset.
- llvm::Value *VirtualOffset = 0;
+ llvm::Value *VirtualOffset = nullptr;
if (VBase) {
VirtualOffset =
CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase);
@@ -246,11 +246,11 @@
// No offset, we can just cast back.
return Builder.CreateBitCast(Value, DerivedPtrTy);
}
-
- llvm::BasicBlock *CastNull = 0;
- llvm::BasicBlock *CastNotNull = 0;
- llvm::BasicBlock *CastEnd = 0;
-
+
+ llvm::BasicBlock *CastNull = nullptr;
+ llvm::BasicBlock *CastNotNull = nullptr;
+ llvm::BasicBlock *CastEnd = nullptr;
+
if (NullCheckValue) {
CastNull = createBasicBlock("cast.null");
CastNotNull = createBasicBlock("cast.notnull");
@@ -290,7 +290,7 @@
bool Delegating) {
if (!CGM.getCXXABI().NeedsVTTParameter(GD)) {
// This constructor/destructor does not need a VTT parameter.
- return 0;
+ return nullptr;
}
const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent();
@@ -454,7 +454,7 @@
switch (CGF.getEvaluationKind(T)) {
case TEK_Scalar:
- CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false);
+ CGF.EmitScalarInit(Init, /*decl*/ nullptr, LV, false);
break;
case TEK_Complex:
CGF.EmitComplexExprIntoLValue(Init, LV, /*isInit*/ true);
@@ -607,7 +607,7 @@
EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true);
break;
case TEK_Aggregate: {
- llvm::Value *ArrayIndexVar = 0;
+ llvm::Value *ArrayIndexVar = nullptr;
if (ArrayIndexes.size()) {
llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
@@ -777,8 +777,8 @@
const VarDecl *SrcRec)
: CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),
RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)),
- FirstField(0), LastField(0), FirstFieldOffset(0), LastFieldOffset(0),
- LastAddedFieldIndex(0) { }
+ FirstField(nullptr), LastField(nullptr), FirstFieldOffset(0),
+ LastFieldOffset(0), LastAddedFieldIndex(0) {}
static bool isMemcpyableField(FieldDecl *F) {
Qualifiers Qual = F->getType().getQualifiers();
@@ -788,7 +788,7 @@
}
void addMemcpyableField(FieldDecl *F) {
- if (FirstField == 0)
+ if (!FirstField)
addInitialField(F);
else
addNextField(F);
@@ -810,7 +810,7 @@
void emitMemcpy() {
// Give the subclass a chance to bail out if it feels the memcpy isn't
// worth it (e.g. Hasn't aggregated enough data).
- if (FirstField == 0) {
+ if (!FirstField) {
return;
}
@@ -844,7 +844,7 @@
}
void reset() {
- FirstField = 0;
+ FirstField = nullptr;
}
protected:
@@ -917,7 +917,7 @@
FunctionArgList &Args) {
if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
return Args[Args.size() - 1];
- return 0;
+ return nullptr;
}
// Returns true if a CXXCtorInitializer represents a member initialization
@@ -926,7 +926,7 @@
if (!MemcpyableCtor)
return false;
FieldDecl *Field = MemberInit->getMember();
- assert(Field != 0 && "No field for member init.");
+ assert(Field && "No field for member init.");
QualType FieldType = Field->getType();
CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
@@ -1014,71 +1014,71 @@
// exists. Otherwise returns null.
FieldDecl *getMemcpyableField(Stmt *S) {
if (!AssignmentsMemcpyable)
- return 0;
+ return nullptr;
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
// Recognise trivial assignments.
if (BO->getOpcode() != BO_Assign)
- return 0;
+ return nullptr;
MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS());
if (!ME)
- return 0;
+ return nullptr;
FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
if (!Field || !isMemcpyableField(Field))
- return 0;
+ return nullptr;
Stmt *RHS = BO->getRHS();
if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS))
RHS = EC->getSubExpr();
if (!RHS)
- return 0;
+ return nullptr;
MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS);
if (dyn_cast<FieldDecl>(ME2->getMemberDecl()) != Field)
- return 0;
+ return nullptr;
return Field;
} else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl());
if (!(MD && (MD->isCopyAssignmentOperator() ||
MD->isMoveAssignmentOperator()) &&
MD->isTrivial()))
- return 0;
+ return nullptr;
MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument());
if (!IOA)
- return 0;
+ return nullptr;
FieldDecl *Field = dyn_cast<FieldDecl>(IOA->getMemberDecl());
if (!Field || !isMemcpyableField(Field))
- return 0;
+ return nullptr;
MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0));
if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->getMemberDecl()))
- return 0;
+ return nullptr;
return Field;
} else if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
if (!FD || FD->getBuiltinID() != Builtin::BI__builtin_memcpy)
- return 0;
+ return nullptr;
Expr *DstPtr = CE->getArg(0);
if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr))
DstPtr = DC->getSubExpr();
UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr);
if (!DUO || DUO->getOpcode() != UO_AddrOf)
- return 0;
+ return nullptr;
MemberExpr *ME = dyn_cast<MemberExpr>(DUO->getSubExpr());
if (!ME)
- return 0;
+ return nullptr;
FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
if (!Field || !isMemcpyableField(Field))
- return 0;
+ return nullptr;
Expr *SrcPtr = CE->getArg(1);
if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr))
SrcPtr = SC->getSubExpr();
UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr);
if (!SUO || SUO->getOpcode() != UO_AddrOf)
- return 0;
+ return nullptr;
MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->getSubExpr());
if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->getMemberDecl()))
- return 0;
+ return nullptr;
return Field;
}
- return 0;
+ return nullptr;
}
bool AssignmentsMemcpyable;
@@ -1137,7 +1137,7 @@
CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
E = CD->init_end();
- llvm::BasicBlock *BaseCtorContinueBB = 0;
+ llvm::BasicBlock *BaseCtorContinueBB = nullptr;
if (ClassDecl->getNumVBases() &&
!CGM.getTarget().getCXXABI().hasConstructorVariants()) {
// The ABIs that don't have constructor variants need to put a branch
@@ -1374,7 +1374,7 @@
public:
CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
: ShouldDeleteCondition(ShouldDeleteCondition) {
- assert(ShouldDeleteCondition != NULL);
+ assert(ShouldDeleteCondition != nullptr);
}
void Emit(CodeGenFunction &CGF, Flags flags) override {
@@ -1552,7 +1552,7 @@
// because of GCC extensions that permit zero-length arrays. There
// are probably legitimate places where we could assume that this
// doesn't happen, but it's not clear that it's worth it.
- llvm::BranchInst *zeroCheckBranch = 0;
+ llvm::BranchInst *zeroCheckBranch = nullptr;
// Optimize for a constant count.
llvm::ConstantInt *constantCount
@@ -1870,7 +1870,7 @@
return;
// Compute where to store the address point.
- llvm::Value *VirtualOffset = 0;
+ llvm::Value *VirtualOffset = nullptr;
CharUnits NonVirtualOffset = CharUnits::Zero();
if (NeedsVirtualOffset) {
@@ -1968,7 +1968,7 @@
// Initialize the vtable pointers for this class and all of its bases.
VisitedVirtualBasesSetTy VBases;
InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()),
- /*NearestVBase=*/0,
+ /*NearestVBase=*/nullptr,
/*OffsetFromNearestVBase=*/CharUnits::Zero(),
/*BaseIsNonVirtualPrimaryBase=*/false, RD, VBases);
@@ -2177,7 +2177,7 @@
assert(MD->isFunctionTemplateSpecialization());
const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *CorrespondingCallOpSpecialization =
CallOpTemplate->findSpecialization(TAL->data(), TAL->size(), InsertPos);
assert(CorrespondingCallOpSpecialization);
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index 8748224..ed9f96d 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -50,7 +50,7 @@
CodeGenFunction::ComplexPairTy V = rv.getComplexVal();
llvm::Type *ComplexTy =
llvm::StructType::get(V.first->getType(), V.second->getType(),
- (void*) 0);
+ (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));
@@ -245,7 +245,7 @@
assert(BranchFixups.size() >= MinSize && "fixup stack out of order");
while (BranchFixups.size() > MinSize &&
- BranchFixups.back().Destination == 0)
+ BranchFixups.back().Destination == nullptr)
BranchFixups.pop_back();
}
@@ -263,7 +263,7 @@
// Set that as the active flag in the cleanup.
EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin());
- assert(cleanup.getActiveFlag() == 0 && "cleanup already has active flag?");
+ assert(!cleanup.getActiveFlag() && "cleanup already has active flag?");
cleanup.setActiveFlag(active);
if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup();
@@ -283,7 +283,7 @@
for (unsigned I = 0, E = CGF.EHStack.getNumBranchFixups(); I != E; ++I) {
// Skip this fixup if its destination isn't set.
BranchFixup &Fixup = CGF.EHStack.getBranchFixup(I);
- if (Fixup.Destination == 0) continue;
+ if (Fixup.Destination == nullptr) continue;
// If there isn't an OptimisticBranchBlock, then InitialBranch is
// still pointing directly to its destination; forward it to the
@@ -293,7 +293,7 @@
// lbl:
// i.e. where there's an unresolved fixup inside a single cleanup
// entry which we're currently popping.
- if (Fixup.OptimisticBranchBlock == 0) {
+ if (Fixup.OptimisticBranchBlock == nullptr) {
new llvm::StoreInst(CGF.Builder.getInt32(Fixup.DestinationIndex),
CGF.getNormalCleanupDestSlot(),
Fixup.InitialBranch);
@@ -347,7 +347,7 @@
BranchFixup &Fixup = EHStack.getBranchFixup(I);
if (Fixup.Destination != Block) continue;
- Fixup.Destination = 0;
+ Fixup.Destination = nullptr;
ResolvedAny = true;
// If it doesn't have an optimistic branch block, LatestBranch is
@@ -473,7 +473,7 @@
// If there's an active flag, load it and skip the cleanup if it's
// false.
- llvm::BasicBlock *ContBB = 0;
+ llvm::BasicBlock *ContBB = nullptr;
if (ActiveFlag) {
ContBB = CGF.createBasicBlock("cleanup.done");
llvm::BasicBlock *CleanupBB = CGF.createBasicBlock("cleanup.action");
@@ -568,15 +568,15 @@
// Remember activation information.
bool IsActive = Scope.isActive();
llvm::Value *NormalActiveFlag =
- Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag() : 0;
+ Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag() : nullptr;
llvm::Value *EHActiveFlag =
- Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag() : 0;
+ Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag() : nullptr;
// Check whether we need an EH cleanup. This is only true if we've
// generated a lazy EH cleanup block.
llvm::BasicBlock *EHEntry = Scope.getCachedEHDispatchBlock();
- assert(Scope.hasEHBranches() == (EHEntry != 0));
- bool RequiresEHCleanup = (EHEntry != 0);
+ assert(Scope.hasEHBranches() == (EHEntry != nullptr));
+ bool RequiresEHCleanup = (EHEntry != nullptr);
EHScopeStack::stable_iterator EHParent = Scope.getEnclosingEHScope();
// Check the three conditions which might require a normal cleanup:
@@ -590,7 +590,7 @@
// - whether there's a fallthrough
llvm::BasicBlock *FallthroughSource = Builder.GetInsertBlock();
- bool HasFallthrough = (FallthroughSource != 0 && IsActive);
+ bool HasFallthrough = (FallthroughSource != nullptr && IsActive);
// Branch-through fall-throughs leave the insertion point set to the
// end of the last cleanup, which points to the current scope. The
@@ -720,7 +720,7 @@
// - if fall-through is a branch-through
// - if there are fixups that will be optimistically forwarded
// to the enclosing cleanup
- llvm::BasicBlock *BranchThroughDest = 0;
+ llvm::BasicBlock *BranchThroughDest = nullptr;
if (Scope.hasBranchThroughs() ||
(FallthroughSource && FallthroughIsBranchThrough) ||
(HasFixups && HasEnclosingCleanups)) {
@@ -729,7 +729,7 @@
BranchThroughDest = CreateNormalEntry(*this, cast<EHCleanupScope>(S));
}
- llvm::BasicBlock *FallthroughDest = 0;
+ llvm::BasicBlock *FallthroughDest = nullptr;
SmallVector<llvm::Instruction*, 2> InstsToAppend;
// If there's exactly one branch-after and no other threads,
@@ -943,7 +943,7 @@
Fixup.Destination = Dest.getBlock();
Fixup.DestinationIndex = Dest.getDestIndex();
Fixup.InitialBranch = BI;
- Fixup.OptimisticBranchBlock = 0;
+ Fixup.OptimisticBranchBlock = nullptr;
Builder.ClearInsertionPoint();
return;
diff --git a/lib/CodeGen/CGCleanup.h b/lib/CodeGen/CGCleanup.h
index fed75bc..066cdb2 100644
--- a/lib/CodeGen/CGCleanup.h
+++ b/lib/CodeGen/CGCleanup.h
@@ -96,7 +96,7 @@
enum Kind { Cleanup, Catch, Terminate, Filter };
EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
- : CachedLandingPad(0), CachedEHDispatchBlock(0),
+ : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),
EnclosingEHScope(enclosingEHScope) {
CommonBits.Kind = kind;
}
@@ -150,7 +150,7 @@
/// The catch handler for this type.
llvm::BasicBlock *Block;
- bool isCatchAll() const { return Type == 0; }
+ bool isCatchAll() const { return Type == nullptr; }
};
private:
@@ -180,7 +180,7 @@
}
void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
- setHandler(I, /*catchall*/ 0, Block);
+ setHandler(I, /*catchall*/ nullptr, Block);
}
void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) {
@@ -268,7 +268,7 @@
EHScopeStack::stable_iterator enclosingNormal,
EHScopeStack::stable_iterator enclosingEH)
: EHScope(EHScope::Cleanup, enclosingEH), EnclosingNormal(enclosingNormal),
- NormalBlock(0), ActiveFlag(0), ExtInfo(0) {
+ NormalBlock(nullptr), ActiveFlag(nullptr), ExtInfo(nullptr) {
CleanupBits.IsNormalCleanup = isNormal;
CleanupBits.IsEHCleanup = isEH;
CleanupBits.IsActive = isActive;
@@ -455,7 +455,7 @@
explicit iterator(char *Ptr) : Ptr(Ptr) {}
public:
- iterator() : Ptr(0) {}
+ iterator() : Ptr(nullptr) {}
EHScope *get() const {
return reinterpret_cast<EHScope*>(Ptr);
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 0e94b51..e2ba70a 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -112,17 +112,14 @@
if (LexicalBlockStack.empty()) return;
SourceManager &SM = CGM.getContext().getSourceManager();
+ llvm::DIScope Scope(LexicalBlockStack.back());
PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
- PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);
- if (PCLoc.isInvalid() || PPLoc.isInvalid() ||
- !strcmp(PPLoc.getFilename(), PCLoc.getFilename()))
+ if (PCLoc.isInvalid() || Scope.getFilename() == PCLoc.getFilename())
return;
- llvm::MDNode *LB = LexicalBlockStack.back();
- llvm::DIScope Scope = llvm::DIScope(LB);
if (Scope.isLexicalBlockFile()) {
- llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(LB);
+ llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(Scope);
llvm::DIDescriptor D
= DBuilder.createLexicalBlockFile(LBF.getScope(),
getOrCreateFile(CurLoc));
@@ -317,11 +314,18 @@
/// CreateCompileUnit - Create new compile unit.
void CGDebugInfo::CreateCompileUnit() {
+ // Should we be asking the SourceManager for the main file name, instead of
+ // accepting it as an argument? This just causes the main file name to
+ // mismatch with source locations and create extra lexical scopes or
+ // mismatched debug info (a CU with a DW_AT_file of "-", because that's what
+ // the driver passed, but functions/other things have DW_AT_file of "<stdin>"
+ // because that's what the SourceManager says)
+
// Get absolute path name.
SourceManager &SM = CGM.getContext().getSourceManager();
std::string MainFileName = CGM.getCodeGenOpts().MainFileName;
if (MainFileName.empty())
- MainFileName = "<unknown>";
+ MainFileName = "<stdin>";
// The main file name provided via the "-main-file-name" option contains just
// the file name itself with no path information. This file name may have had
@@ -344,7 +348,7 @@
std::string SplitDwarfFile = CGM.getCodeGenOpts().SplitDwarfFile;
StringRef SplitDwarfFilename = internString(SplitDwarfFile);
- unsigned LangTag;
+ llvm::dwarf::SourceLanguage LangTag;
const LangOptions &LO = CGM.getLangOpts();
if (LO.CPlusPlus) {
if (LO.ObjC1)
@@ -379,7 +383,7 @@
/// CreateType - Get the Basic type from the cache or create a new
/// one if necessary.
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
- unsigned Encoding = 0;
+ llvm::dwarf::TypeKind Encoding;
StringRef BTName;
switch (BT->getKind()) {
#define BUILTIN_TYPE(Id, SingletonId)
@@ -393,11 +397,10 @@
case BuiltinType::Void:
return llvm::DIType();
case BuiltinType::ObjCClass:
- if (ClassTy)
- return ClassTy;
- ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- "objc_class", TheCU,
- getOrCreateMainFile(), 0);
+ if (!ClassTy)
+ ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ "objc_class", TheCU,
+ getOrCreateMainFile(), 0);
return ClassTy;
case BuiltinType::ObjCId: {
// typedef struct objc_class *Class;
@@ -426,12 +429,10 @@
return ObjTy;
}
case BuiltinType::ObjCSel: {
- if (SelTy)
- return SelTy;
- SelTy =
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- "objc_selector", TheCU, getOrCreateMainFile(),
- 0);
+ if (!SelTy)
+ SelTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ "objc_selector", TheCU,
+ getOrCreateMainFile(), 0);
return SelTy;
}
@@ -506,7 +507,7 @@
llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
// Bit size, align and offset of the type.
- unsigned Encoding = llvm::dwarf::DW_ATE_complex_float;
+ llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
if (Ty->isComplexIntegerType())
Encoding = llvm::dwarf::DW_ATE_lo_user;
@@ -531,7 +532,7 @@
// We will create one Derived type for one qualifier and recurse to handle any
// additional ones.
- unsigned Tag;
+ llvm::dwarf::Tag Tag;
if (Qc.hasConst()) {
Tag = llvm::dwarf::DW_TAG_const_type;
Qc.removeConst();
@@ -611,7 +612,7 @@
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
- unsigned Tag = 0;
+ llvm::dwarf::Tag Tag;
if (RD->isStruct() || RD->isInterface())
Tag = llvm::dwarf::DW_TAG_structure_type;
else if (RD->isUnion())
@@ -623,11 +624,13 @@
// Create the type.
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
- return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line, 0, 0, 0,
- FullName);
+ llvm::DICompositeType RetTy = DBuilder.createReplaceableForwardDecl(
+ Tag, RDName, Ctx, DefUnit, Line, 0, 0, 0, FullName);
+ ReplaceMap.push_back(std::make_pair(Ty, static_cast<llvm::Value *>(RetTy)));
+ return RetTy;
}
-llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
+llvm::DIType CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
const Type *Ty,
QualType PointeeTy,
llvm::DIFile Unit) {
@@ -719,12 +722,35 @@
return BlockLiteralGeneric;
}
+llvm::DIType CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, llvm::DIFile Unit) {
+ assert(Ty->isTypeAlias());
+ llvm::DIType Src = getOrCreateType(Ty->getAliasedType(), Unit);
+
+ SmallString<128> NS;
+ llvm::raw_svector_ostream OS(NS);
+ Ty->getTemplateName().print(OS, CGM.getContext().getPrintingPolicy(), /*qualified*/ false);
+
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, Ty->getArgs(), Ty->getNumArgs(),
+ CGM.getContext().getPrintingPolicy());
+
+ TypeAliasDecl *AliasDecl =
+ cast<TypeAliasTemplateDecl>(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);
+}
+
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);
- if (!Src)
- return llvm::DIType();
// We don't set size information, but do specify where the typedef was
// declared.
SourceLocation Loc = Ty->getDecl()->getLocation();
@@ -808,7 +834,7 @@
unsigned fieldno = 0;
for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(),
E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) {
- const LambdaExpr::Capture C = *I;
+ const LambdaCapture &C = *I;
if (C.capturesVariable()) {
VarDecl *V = C.getCapturedVar();
llvm::DIFile VUnit = getOrCreateFile(C.getLocation());
@@ -852,7 +878,7 @@
unsigned LineNumber = getLineNumber(Var->getLocation());
StringRef VName = Var->getName();
- llvm::Constant *C = NULL;
+ llvm::Constant *C = nullptr;
if (Var->getInit()) {
const APValue *Value = Var->evaluateValue();
if (Value) {
@@ -1096,7 +1122,7 @@
MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/ false,
Virtuality, VIndex, ContainingType,
- Flags, CGM.getLangOpts().Optimize, NULL,
+ Flags, CGM.getLangOpts().Optimize, nullptr,
TParamsArray);
SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP);
@@ -1224,7 +1250,7 @@
->getTypeForDecl())
: CGM.getContext().getPointerType(D->getType());
llvm::DIType TTy = getOrCreateType(T, Unit);
- llvm::Value *V = 0;
+ llvm::Value *V = nullptr;
// Variable pointer template parameters have a value that is the address
// of the variable.
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
@@ -1256,7 +1282,7 @@
case TemplateArgument::NullPtr: {
QualType T = TA.getNullPtrType();
llvm::DIType TTy = getOrCreateType(T, Unit);
- llvm::Value *V = 0;
+ llvm::Value *V = nullptr;
// Special case member data pointer null values since they're actually -1
// instead of zero.
if (const MemberPointerType *MPT =
@@ -1286,7 +1312,7 @@
llvm::DITemplateValueParameter TVP =
DBuilder.createTemplateParameterPack(
TheCU, Name, llvm::DIType(),
- CollectTemplateParams(NULL, TA.getPackAsArray(), Unit));
+ CollectTemplateParams(nullptr, TA.getPackAsArray(), Unit));
TemplateParams.push_back(TVP);
} break;
case TemplateArgument::Expression: {
@@ -1330,14 +1356,11 @@
llvm::DIArray CGDebugInfo::
CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial,
llvm::DIFile Unit) {
- llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *>
- PU = TSpecial->getSpecializedTemplateOrPartial();
-
- TemplateParameterList *TPList = PU.is<ClassTemplateDecl *>() ?
- PU.get<ClassTemplateDecl *>()->getTemplateParameters() :
- PU.get<ClassTemplatePartialSpecializationDecl *>()->getTemplateParameters();
- const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs();
+ // Always get the full list of parameters, not just the ones from
+ // the specialization.
+ TemplateParameterList *TPList =
+ TSpecial->getSpecializedTemplate()->getTemplateParameters();
+ const TemplateArgumentList &TAList = TSpecial->getTemplateArgs();
return CollectTemplateParams(TPList, TAList.asArray(), Unit);
}
@@ -1408,6 +1431,21 @@
return T;
}
+void CGDebugInfo::completeType(const EnumDecl *ED) {
+ if (DebugKind <= CodeGenOptions::DebugLineTablesOnly)
+ return;
+ QualType Ty = CGM.getContext().getEnumType(ED);
+ void* TyPtr = Ty.getAsOpaquePtr();
+ auto I = TypeCache.find(TyPtr);
+ if (I == TypeCache.end() ||
+ !llvm::DIType(cast<llvm::MDNode>(static_cast<llvm::Value *>(I->second)))
+ .isForwardDecl())
+ return;
+ llvm::DIType Res = CreateTypeDefinition(Ty->castAs<EnumType>());
+ assert(!Res.isForwardDecl());
+ TypeCache[TyPtr] = Res;
+}
+
void CGDebugInfo::completeType(const RecordDecl *RD) {
if (DebugKind > CodeGenOptions::LimitedDebugInfo ||
!CGM.getLangOpts().CPlusPlus)
@@ -1433,11 +1471,13 @@
return;
QualType Ty = CGM.getContext().getRecordType(RD);
void* TyPtr = Ty.getAsOpaquePtr();
- if (CompletedTypeCache.count(TyPtr))
+ auto I = TypeCache.find(TyPtr);
+ if (I != TypeCache.end() &&
+ !llvm::DIType(cast<llvm::MDNode>(static_cast<llvm::Value *>(I->second)))
+ .isForwardDecl())
return;
llvm::DIType Res = CreateTypeDefinition(Ty->castAs<RecordType>());
assert(!Res.isForwardDecl());
- CompletedTypeCache[TyPtr] = Res;
TypeCache[TyPtr] = Res;
}
@@ -1525,9 +1565,6 @@
LexicalBlockStack.push_back(&*FwdDecl);
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
- // Add this to the completed-type cache while we're completing it recursively.
- CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
-
// Convert all the elements.
SmallVector<llvm::Value *, 16> EltTys;
// what about nested types?
@@ -1599,20 +1636,28 @@
// Get overall information about the record type for the debug info.
llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
unsigned Line = getLineNumber(ID->getLocation());
- unsigned RuntimeLang = TheCU.getLanguage();
+ llvm::dwarf::SourceLanguage RuntimeLang = TheCU.getLanguage();
// 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.
ObjCInterfaceDecl *Def = ID->getDefinition();
- if (!Def) {
- llvm::DIType FwdDecl =
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- ID->getName(), TheCU, DefUnit, Line,
- RuntimeLang);
+ if (!Def || !Def->getImplementation()) {
+ llvm::DIType FwdDecl = DBuilder.createReplaceableForwardDecl(
+ llvm::dwarf::DW_TAG_structure_type, ID->getName(), TheCU, DefUnit, Line,
+ RuntimeLang);
+ ObjCInterfaceCache.push_back(ObjCInterfaceCacheEntry(Ty, FwdDecl, Unit));
return FwdDecl;
}
- ID = Def;
+
+ return CreateTypeDefinition(Ty, Unit);
+}
+
+llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, llvm::DIFile Unit) {
+ ObjCInterfaceDecl *ID = Ty->getDecl();
+ llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
+ unsigned Line = getLineNumber(ID->getLocation());
+ unsigned RuntimeLang = TheCU.getLanguage();
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
@@ -1627,10 +1672,8 @@
Line, Size, Align, Flags,
llvm::DIType(), llvm::DIArray(), RuntimeLang);
- // Otherwise, insert it into the CompletedTypeCache so that recursive uses
- // will find it and we're emitting the complete type.
- QualType QualTy = QualType(Ty, 0);
- CompletedTypeCache[QualTy.getAsOpaquePtr()] = RealDecl;
+ QualType QTy(Ty, 0);
+ TypeCache[QTy.getAsOpaquePtr()] = RealDecl;
// Push the struct on region stack.
LexicalBlockStack.push_back(static_cast<llvm::MDNode*>(RealDecl));
@@ -1722,7 +1765,7 @@
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
Flags = llvm::DIDescriptor::FlagPrivate;
- llvm::MDNode *PropertyNode = NULL;
+ llvm::MDNode *PropertyNode = nullptr;
if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {
if (ObjCPropertyImplDecl *PImpD =
ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
@@ -1754,12 +1797,6 @@
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
RealDecl.setTypeArray(Elements);
- // If the implementation is not yet set, we do not want to mark it
- // as complete. An implementation may declare additional
- // private ivars that we would miss otherwise.
- if (ID->getImplementation() == 0)
- CompletedTypeCache.erase(QualTy.getAsOpaquePtr());
-
LexicalBlockStack.pop_back();
return RealDecl;
}
@@ -1890,11 +1927,27 @@
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
StringRef EDName = ED->getName();
- return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_enumeration_type,
- EDName, EDContext, DefUnit, Line, 0,
- Size, Align, FullName);
+ llvm::DIType RetTy = DBuilder.createReplaceableForwardDecl(
+ llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line,
+ 0, Size, Align, FullName);
+ ReplaceMap.push_back(std::make_pair(Ty, static_cast<llvm::Value *>(RetTy)));
+ return RetTy;
}
+ return CreateTypeDefinition(Ty);
+}
+
+llvm::DIType CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
+ const EnumDecl *ED = Ty->getDecl();
+ uint64_t Size = 0;
+ uint64_t Align = 0;
+ if (!ED->getTypeForDecl()->isIncompleteType()) {
+ Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
+ Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ }
+
+ SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+
// Create DIEnumerator elements for each enumerator.
SmallVector<llvm::Value *, 16> Enumerators;
ED = ED->getDefinition();
@@ -1932,9 +1985,12 @@
switch (T->getTypeClass()) {
default:
return C.getQualifiedType(T.getTypePtr(), Quals);
- case Type::TemplateSpecialization:
- T = cast<TemplateSpecializationType>(T)->desugar();
- break;
+ case Type::TemplateSpecialization: {
+ const auto *Spec = cast<TemplateSpecializationType>(T);
+ if (Spec->isTypeAlias())
+ return C.getQualifiedType(T.getTypePtr(), Quals);
+ T = Spec->desugar();
+ break; }
case Type::TypeOfExpr:
T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
break;
@@ -1979,16 +2035,7 @@
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
- // Check for existing entry.
- if (Ty->getTypeClass() == Type::ObjCInterface) {
- llvm::Value *V = getCachedInterfaceTypeOrNull(Ty);
- if (V)
- return llvm::DIType(cast<llvm::MDNode>(V));
- else return llvm::DIType();
- }
-
- llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
- TypeCache.find(Ty.getAsOpaquePtr());
+ auto it = TypeCache.find(Ty.getAsOpaquePtr());
if (it != TypeCache.end()) {
// Verify that the debug info still exists.
if (llvm::Value *V = it->second)
@@ -1998,27 +2045,6 @@
return llvm::DIType();
}
-/// getCompletedTypeOrNull - Get the type from the cache or return null if it
-/// doesn't exist.
-llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) {
-
- // Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
-
- // Check for existing entry.
- llvm::Value *V = 0;
- llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
- CompletedTypeCache.find(Ty.getAsOpaquePtr());
- if (it != CompletedTypeCache.end())
- V = it->second;
- else {
- V = getCachedInterfaceTypeOrNull(Ty);
- }
-
- // Verify that any cached debug info still exists.
- return llvm::DIType(cast_or_null<llvm::MDNode>(V));
-}
-
void CGDebugInfo::completeTemplateDefinition(
const ClassTemplateSpecializationDecl &SD) {
if (DebugKind <= CodeGenOptions::DebugLineTablesOnly)
@@ -2030,22 +2056,6 @@
RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr());
}
-/// getCachedInterfaceTypeOrNull - Get the type from the interface
-/// cache, unless it needs to regenerated. Otherwise return null.
-llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) {
- // Is there a cached interface that hasn't changed?
- llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
- ::iterator it1 = ObjCInterfaceCache.find(Ty.getAsOpaquePtr());
-
- if (it1 != ObjCInterfaceCache.end())
- if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty))
- if (Checksum(Decl) == it1->second.second)
- // Return cached forward declaration.
- return it1->second.first;
-
- return 0;
-}
-
/// getOrCreateType - Get the type from the cache or create a new
/// one if necessary.
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
@@ -2055,7 +2065,7 @@
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
- if (llvm::DIType T = getCompletedTypeOrNull(Ty))
+ if (llvm::DIType T = getTypeOrNull(Ty))
return T;
// Otherwise create the type.
@@ -2065,39 +2075,6 @@
// And update the type cache.
TypeCache[TyPtr] = Res;
- // FIXME: this getTypeOrNull call seems silly when we just inserted the type
- // into the cache - but getTypeOrNull has a special case for cached interface
- // types. We should probably just pull that out as a special case for the
- // "else" block below & skip the otherwise needless lookup.
- llvm::DIType TC = getTypeOrNull(Ty);
- if (TC && TC.isForwardDecl())
- ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
- else if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty)) {
- // Interface types may have elements added to them by a
- // subsequent implementation or extension, so we keep them in
- // the ObjCInterfaceCache together with a checksum. Instead of
- // the (possibly) incomplete interface type, we return a forward
- // declaration that gets RAUW'd in CGDebugInfo::finalize().
- std::pair<llvm::WeakVH, unsigned> &V = ObjCInterfaceCache[TyPtr];
- if (V.first)
- return llvm::DIType(cast<llvm::MDNode>(V.first));
- TC = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- Decl->getName(), TheCU, Unit,
- getLineNumber(Decl->getLocation()),
- TheCU.getLanguage());
- // Store the forward declaration in the cache.
- V.first = TC;
- V.second = Checksum(Decl);
-
- // Register the type for replacement in finalize().
- ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
-
- return TC;
- }
-
- if (!Res.isForwardDecl())
- CompletedTypeCache[TyPtr] = Res;
-
return Res;
}
@@ -2109,7 +2086,7 @@
// a checksum.
unsigned Sum = 0;
for (const ObjCIvarDecl *Ivar = ID->all_declared_ivar_begin();
- Ivar != 0; Ivar = Ivar->getNextIvar())
+ Ivar != nullptr; Ivar = Ivar->getNextIvar())
++Sum;
return Sum;
@@ -2123,7 +2100,7 @@
case Type::ObjCInterface:
return cast<ObjCInterfaceType>(Ty)->getDecl();
default:
- return 0;
+ return nullptr;
}
}
@@ -2133,7 +2110,7 @@
if (Ty.hasLocalQualifiers())
return CreateQualifiedType(Ty, Unit);
- const char *Diag = 0;
+ const char *Diag = nullptr;
// Work out details of type.
switch (Ty->getTypeClass()) {
@@ -2191,8 +2168,10 @@
case Type::Atomic:
return CreateType(cast<AtomicType>(Ty), Unit);
- case Type::Attributed:
case Type::TemplateSpecialization:
+ return CreateType(cast<TemplateSpecializationType>(Ty), Unit);
+
+ case Type::Attributed:
case Type::Elaborated:
case Type::Paren:
case Type::SubstTemplateTypeParm:
@@ -2236,10 +2215,6 @@
// correct order if the full type is needed.
Res.setTypeArray(T.getTypeArray());
- if (T && T.isForwardDecl())
- ReplaceMap.push_back(
- std::make_pair(QTy.getAsOpaquePtr(), static_cast<llvm::Value *>(T)));
-
// And update the type cache.
TypeCache[QTy.getAsOpaquePtr()] = Res;
return Res;
@@ -2259,13 +2234,6 @@
// If we ended up creating the type during the context chain construction,
// just return that.
- // FIXME: this could be dealt with better if the type was recorded as
- // completed before we started this (see the CompletedTypeCache usage in
- // CGDebugInfo::CreateTypeDefinition(const RecordType*) - that would need to
- // be pushed to before context creation, but after it was known to be
- // destined for completion (might still have an issue if this caller only
- // required a declaration but the context construction ended up creating a
- // definition)
llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD)));
if (T && (!T.isForwardDecl() || !RD->getDefinition()))
return T;
@@ -2473,7 +2441,10 @@
}
/// EmitFunctionStart - Constructs the debug code for entering a function.
-void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
+void CGDebugInfo::EmitFunctionStart(GlobalDecl GD,
+ SourceLocation Loc,
+ SourceLocation ScopeLoc,
+ QualType FnType,
llvm::Function *Fn,
CGBuilderTy &Builder) {
@@ -2483,24 +2454,7 @@
FnBeginRegionCount.push_back(LexicalBlockStack.size());
const Decl *D = GD.getDecl();
-
- // Use the location of the start of the function to determine where
- // the function definition is located. By default use the location
- // of the declaration as the location for the subprogram. A function
- // may lack a declaration in the source code if it is created by code
- // gen. (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk).
- bool HasDecl = (D != 0);
- SourceLocation Loc;
- if (HasDecl) {
- Loc = D->getLocation();
-
- // If this is a function specialization then use the pattern body
- // as the location for the function.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- if (const FunctionDecl *SpecDecl = FD->getTemplateInstantiationPattern())
- if (SpecDecl->hasBody(SpecDecl))
- Loc = SpecDecl->getLocation();
- }
+ bool HasDecl = (D != nullptr);
unsigned Flags = 0;
llvm::DIFile Unit = getOrCreateFile(Loc);
@@ -2560,9 +2514,14 @@
if (!Name.empty() && Name[0] == '\01')
Name = Name.substr(1);
- unsigned LineNo = getLineNumber(Loc);
- if (!HasDecl || D->isImplicit())
+ if (!HasDecl || D->isImplicit()) {
Flags |= llvm::DIDescriptor::FlagArtificial;
+ // Artificial functions without a location should not silently reuse CurLoc.
+ if (Loc.isInvalid())
+ CurLoc = SourceLocation();
+ }
+ unsigned LineNo = getLineNumber(Loc);
+ unsigned ScopeLine = getLineNumber(ScopeLoc);
// FIXME: The function declaration we're constructing here is mostly reusing
// declarations from CXXMethodDecl and not constructing new ones for arbitrary
@@ -2573,7 +2532,7 @@
DBuilder.createFunction(FDContext, Name, LinkageName, Unit, LineNo,
getOrCreateFunctionType(D, FnType, Unit),
Fn->hasInternalLinkage(), true /*definition*/,
- getLineNumber(CurLoc), Flags,
+ ScopeLine, Flags,
CGM.getLangOpts().Optimize, Fn, TParamsArray,
getFunctionDeclaration(D));
if (HasDecl)
@@ -2731,7 +2690,7 @@
}
FType = Type;
- llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ llvm::DIType FieldTy = getOrCreateType(FType, Unit);
FieldSize = CGM.getContext().getTypeSize(FType);
FieldAlign = CGM.getContext().toBits(Align);
@@ -2751,7 +2710,7 @@
}
/// EmitDeclare - Emit local variable declaration debug info.
-void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
+void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::LLVMConstants Tag,
llvm::Value *Storage,
unsigned ArgNo, CGBuilderTy &Builder) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@@ -2888,7 +2847,6 @@
llvm::DIType Ty) {
llvm::DIType CachedTy = getTypeOrNull(QualTy);
if (CachedTy) Ty = CachedTy;
- else DEBUG(llvm::dbgs() << "No cached type for self.");
return DBuilder.createObjectPointerType(Ty);
}
@@ -2899,7 +2857,7 @@
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
- if (Builder.GetInsertBlock() == 0)
+ if (Builder.GetInsertBlock() == nullptr)
return;
bool isByRef = VD->hasAttr<BlocksAttr>();
@@ -3029,7 +2987,7 @@
BlockLayoutChunk chunk;
chunk.OffsetInBits =
blockLayout->getElementOffsetInBits(block.CXXThisIndex);
- chunk.Capture = 0;
+ chunk.Capture = nullptr;
chunks.push_back(chunk);
}
@@ -3149,6 +3107,37 @@
return T;
}
+/// 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 GV;
+
+ for (const auto *Field : RD->fields()) {
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ StringRef FieldName = Field->getName();
+
+ // Ignore unnamed fields, but recurse into anonymous records.
+ if (FieldName.empty()) {
+ const RecordType *RT = dyn_cast<RecordType>(Field->getType());
+ if (RT)
+ GV = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName,
+ Var, DContext);
+ continue;
+ }
+ // Use VarDecl's Tag, Scope and Line number.
+ GV = DBuilder.createStaticVariable(DContext, FieldName, LinkageName, Unit,
+ LineNo, FieldTy,
+ Var->hasInternalLinkage(), Var,
+ llvm::DIDerivedType());
+ }
+ return GV;
+}
+
/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
@@ -3169,19 +3158,35 @@
T = CGM.getContext().getConstantArrayType(ET, ConstVal,
ArrayType::Normal, 0);
}
+
StringRef DeclName = D->getName();
StringRef LinkageName;
- if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext())
- && !isa<ObjCMethodDecl>(D->getDeclContext()))
+ if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext()) &&
+ !isa<ObjCMethodDecl>(D->getDeclContext()))
LinkageName = Var->getName();
if (LinkageName == DeclName)
LinkageName = StringRef();
+
llvm::DIDescriptor DContext =
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
- llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
- DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
- Var->hasInternalLinkage(), Var,
- getOrCreateStaticDataMemberDeclarationOrNull(D));
+
+ // Attempt to store one global variable for the declaration - even if we
+ // emit a lot of fields.
+ llvm::DIGlobalVariable GV;
+
+ // If this is an anonymous union then we'll want to emit a global
+ // variable for each member of the anonymous union so that it's possible
+ // to find the name of any field in the union.
+ if (T->isUnionType() && DeclName.empty()) {
+ const RecordDecl *RD = cast<RecordType>(T)->getDecl();
+ assert(RD->isAnonymousStructOrUnion() && "unnamed non-anonymous struct or union?");
+ GV = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
+ } else {
+ GV = DBuilder.createStaticVariable(
+ DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
+ Var->hasInternalLinkage(), Var,
+ getOrCreateStaticDataMemberDeclarationOrNull(D));
+ }
DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(GV)));
}
@@ -3227,10 +3232,20 @@
// Do not use DIGlobalVariable for enums.
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()))
+ return;
+ VD = cast<ValueDecl>(VD->getCanonicalDecl());
+ auto pair = DeclCache.insert(std::make_pair(VD, llvm::WeakVH()));
+ if (!pair.second)
+ return;
+ llvm::DIDescriptor DContext =
+ getContextDescriptor(dyn_cast<Decl>(VD->getDeclContext()));
llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
- Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init,
+ DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty,
+ true, Init,
getOrCreateStaticDataMemberDeclarationOrNull(cast<VarDecl>(VD)));
- DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV)));
+ pair.first->second = llvm::WeakVH(GV);
}
llvm::DIScope CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
@@ -3266,20 +3281,20 @@
llvm::DIImportedEntity
CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) {
if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
- return llvm::DIImportedEntity(0);
+ return llvm::DIImportedEntity(nullptr);
llvm::WeakVH &VH = NamespaceAliasCache[&NA];
if (VH)
return llvm::DIImportedEntity(cast<llvm::MDNode>(VH));
- llvm::DIImportedEntity R(0);
+ llvm::DIImportedEntity R(nullptr);
if (const NamespaceAliasDecl *Underlying =
dyn_cast<NamespaceAliasDecl>(NA.getAliasedNamespace()))
// This could cache & dedup here rather than relying on metadata deduping.
- R = DBuilder.createImportedModule(
+ R = DBuilder.createImportedDeclaration(
getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())),
EmitNamespaceAlias(*Underlying), getLineNumber(NA.getLocation()),
NA.getName());
else
- R = DBuilder.createImportedModule(
+ R = DBuilder.createImportedDeclaration(
getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())),
getOrCreateNameSpace(cast<NamespaceDecl>(NA.getAliasedNamespace())),
getLineNumber(NA.getLocation()), NA.getName());
@@ -3308,23 +3323,27 @@
}
void CGDebugInfo::finalize() {
- for (std::vector<std::pair<void *, llvm::WeakVH> >::const_iterator VI
- = ReplaceMap.begin(), VE = ReplaceMap.end(); VI != VE; ++VI) {
- llvm::DIType Ty, RepTy;
- // Verify that the debug info still exists.
- if (llvm::Value *V = VI->second)
- Ty = llvm::DIType(cast<llvm::MDNode>(V));
+ // Creating types might create further types - invalidating the current
+ // 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::DenseMap<void *, llvm::WeakVH>::iterator it =
- TypeCache.find(VI->first);
- if (it != TypeCache.end()) {
- // Verify that the debug info still exists.
- if (llvm::Value *V = it->second)
- RepTy = llvm::DIType(cast<llvm::MDNode>(V));
- }
+ for (auto p : ReplaceMap) {
+ assert(p.second);
+ llvm::DIType Ty(cast<llvm::MDNode>(p.second));
+ assert(Ty.isForwardDecl());
- if (Ty && Ty.isForwardDecl() && RepTy)
- Ty.replaceAllUsesWith(RepTy);
+ 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);
}
// We keep our own list of retained types, because we need to look
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 52784da..0da6179 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -65,21 +65,27 @@
llvm::DIType BlockLiteralGeneric;
/// TypeCache - Cache of previously constructed Types.
- llvm::DenseMap<void *, llvm::WeakVH> TypeCache;
+ llvm::DenseMap<const void *, llvm::WeakVH> TypeCache;
+
+ struct ObjCInterfaceCacheEntry {
+ const ObjCInterfaceType *Type;
+ llvm::DIType Decl;
+ llvm::DIFile Unit;
+ ObjCInterfaceCacheEntry(const ObjCInterfaceType *Type, llvm::DIType Decl,
+ llvm::DIFile Unit)
+ : Type(Type), Decl(Decl), Unit(Unit) {}
+ };
/// ObjCInterfaceCache - Cache of previously constructed interfaces
- /// which may change. Storing a pair of DIType and checksum.
- llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned> > ObjCInterfaceCache;
+ /// which may change.
+ llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;
/// RetainedTypes - list of interfaces we want to keep even if orphaned.
std::vector<void *> RetainedTypes;
- /// CompleteTypeCache - Cache of previously constructed complete RecordTypes.
- llvm::DenseMap<void *, llvm::WeakVH> CompletedTypeCache;
-
/// ReplaceMap - Cache of forward declared types to RAUW at the end of
/// compilation.
- std::vector<std::pair<void *, llvm::WeakVH> >ReplaceMap;
+ std::vector<std::pair<const TagType *, llvm::WeakVH>> ReplaceMap;
// LexicalBlockStack - Keep track of our current nested lexical block.
std::vector<llvm::TrackingVH<llvm::MDNode> > LexicalBlockStack;
@@ -109,6 +115,7 @@
llvm::DIType CreateType(const ComplexType *Ty);
llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile Fg);
llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile Fg);
+ llvm::DIType CreateType(const TemplateSpecializationType *Ty, llvm::DIFile Fg);
llvm::DIType CreateType(const ObjCObjectPointerType *Ty,
llvm::DIFile F);
llvm::DIType CreateType(const PointerType *Ty, llvm::DIFile F);
@@ -119,6 +126,7 @@
llvm::DICompositeType CreateLimitedType(const RecordType *Ty);
void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType 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);
llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F);
@@ -127,9 +135,9 @@
llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F);
llvm::DIType CreateEnumType(const EnumType *Ty);
+ llvm::DIType CreateTypeDefinition(const EnumType *Ty);
llvm::DIType CreateSelfType(const QualType &QualTy, llvm::DIType Ty);
llvm::DIType getTypeOrNull(const QualType);
- llvm::DIType getCompletedTypeOrNull(const QualType);
llvm::DICompositeType getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile F);
llvm::DICompositeType getOrCreateInstanceMethodType(
@@ -139,7 +147,7 @@
llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);
llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N);
llvm::DIType getOrCreateTypeDeclaration(QualType PointeeTy, llvm::DIFile F);
- llvm::DIType CreatePointerLikeType(unsigned Tag,
+ llvm::DIType CreatePointerLikeType(llvm::dwarf::Tag Tag,
const Type *Ty, QualType PointeeTy,
llvm::DIFile F);
@@ -219,8 +227,12 @@
/// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
/// start of a new function.
- void EmitFunctionStart(GlobalDecl GD, QualType FnType,
- llvm::Function *Fn, CGBuilderTy &Builder);
+ /// \param Loc The location of the function header.
+ /// \param ScopeLoc The location of the function body.
+ void EmitFunctionStart(GlobalDecl GD,
+ SourceLocation Loc, SourceLocation ScopeLoc,
+ QualType FnType, llvm::Function *Fn,
+ CGBuilderTy &Builder);
/// EmitFunctionEnd - Constructs the debug code for exiting a function.
void EmitFunctionEnd(CGBuilderTy &Builder);
@@ -284,6 +296,7 @@
llvm::DIType getOrCreateInterfaceType(QualType Ty,
SourceLocation Loc);
+ void completeType(const EnumDecl *ED);
void completeType(const RecordDecl *RD);
void completeRequiredType(const RecordDecl *RD);
void completeClassData(const RecordDecl *RD);
@@ -292,8 +305,10 @@
private:
/// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
- void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
- unsigned ArgNo, CGBuilderTy &Builder);
+ /// Tag accepts custom types DW_TAG_arg_variable and DW_TAG_auto_variable,
+ /// otherwise would be of type llvm::dwarf::Tag.
+ void EmitDeclare(const VarDecl *decl, llvm::dwarf::LLVMConstants Tag,
+ llvm::Value *AI, unsigned ArgNo, CGBuilderTy &Builder);
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
@@ -357,6 +372,13 @@
llvm::DIDerivedType
getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D);
+ /// 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);
+
/// getFunctionName - Get function name for the given FunctionDecl. If the
/// name is constructed on demand (e.g. C++ destructor) then the name
/// is stored on the side.
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 9db3c91..1869c1c 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -126,17 +126,11 @@
void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
if (D.isStaticLocal()) {
llvm::GlobalValue::LinkageTypes Linkage =
- llvm::GlobalValue::InternalLinkage;
+ CGM.getLLVMLinkageVarDefinition(&D, /*isConstant=*/false);
- // If the variable is externally visible, it must have weak linkage so it
- // can be uniqued.
- if (D.isExternallyVisible()) {
- Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
-
- // FIXME: We need to force the emission/use of a guard variable for
- // some variables even if we can constant-evaluate them because
- // we can't guarantee every translation unit will constant-evaluate them.
- }
+ // FIXME: We need to force the emission/use of a guard variable for
+ // some variables even if we can constant-evaluate them because
+ // we can't guarantee every translation unit will constant-evaluate them.
return EmitStaticVarDecl(D, Linkage);
}
@@ -203,7 +197,7 @@
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), LTy,
Ty.isConstant(getContext()), Linkage,
- CGM.EmitNullConstant(D.getType()), Name, 0,
+ CGM.EmitNullConstant(D.getType()), Name, nullptr,
llvm::GlobalVariable::NotThreadLocal,
AddrSpace);
GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
@@ -297,7 +291,7 @@
void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage) {
llvm::Value *&DMEntry = LocalDeclMap[&D];
- assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
+ assert(!DMEntry && "Decl already exists in localdeclmap!");
// Check to see if we already have a global variable for this
// declaration. This can happen when double-emitting function
@@ -394,7 +388,7 @@
// Along the exceptions path we always execute the dtor.
bool NRVO = flags.isForNormalCleanup() && NRVOFlag;
- llvm::BasicBlock *SkipDtorBB = 0;
+ llvm::BasicBlock *SkipDtorBB = nullptr;
if (NRVO) {
// If we exited via NRVO, we skip the destructor call.
llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused");
@@ -621,7 +615,7 @@
}
// Emit the initializer.
- llvm::Value *value = 0;
+ llvm::Value *value = nullptr;
switch (lifetime) {
case Qualifiers::OCL_None:
@@ -874,7 +868,7 @@
CGM.isTypeConstant(Ty, true)) {
EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
- emission.Address = 0; // signal this condition to later callbacks
+ emission.Address = nullptr; // signal this condition to later callbacks
assert(emission.wasEmittedAsGlobal());
return emission;
}
@@ -969,7 +963,7 @@
}
llvm::Value *&DMEntry = LocalDeclMap[&D];
- assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
+ assert(!DMEntry && "Decl already exists in localdeclmap!");
DMEntry = DeclPtr;
emission.Address = DeclPtr;
@@ -1089,7 +1083,7 @@
llvm::Value *Loc =
capturedByInit ? emission.Address : emission.getObjectAddress(*this);
- llvm::Constant *constant = 0;
+ llvm::Constant *constant = nullptr;
if (emission.IsConstantAggregate || D.isConstexpr()) {
assert(!capturedByInit && "constant init contains a capturing block?");
constant = CGM.EmitConstantInit(D, this);
@@ -1216,7 +1210,7 @@
QualType type = var->getType();
CleanupKind cleanupKind = NormalAndEHCleanup;
- CodeGenFunction::Destroyer *destroyer = 0;
+ CodeGenFunction::Destroyer *destroyer = nullptr;
switch (dtorKind) {
case QualType::DK_none:
@@ -1626,7 +1620,7 @@
// The only implicit argument a block has is its literal.
if (BlockInfo) {
LocalDeclMap[&D] = Arg;
- llvm::Value *LocalAddr = 0;
+ llvm::Value *LocalAddr = nullptr;
if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
// Allocate a stack slot to let the debug info survive the RA.
llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
@@ -1740,7 +1734,7 @@
EmitStoreOfScalar(Arg, lv, /* isInitialization */ true);
llvm::Value *&DMEntry = LocalDeclMap[&D];
- assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
+ assert(!DMEntry && "Decl already exists in localdeclmap!");
DMEntry = DeclPtr;
// Emit debug info for param declaration.
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index bc8620d..c287740 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -17,6 +17,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/Support/Path.h"
using namespace clang;
using namespace CodeGen;
@@ -89,7 +90,7 @@
// Special-case non-array C++ destructors, where there's a function
// with the right signature that we can just call.
- const CXXRecordDecl *record = 0;
+ const CXXRecordDecl *record = nullptr;
if (dtorKind == QualType::DK_cxx_destructor &&
(record = type->getAsCXXRecordDecl())) {
assert(!record->hasTrivialDestructor());
@@ -178,8 +179,7 @@
CodeGenFunction CGF(CGM);
CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn,
- CGM.getTypes().arrangeNullaryFunction(), FunctionArgList(),
- SourceLocation());
+ CGM.getTypes().arrangeNullaryFunction(), FunctionArgList());
llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
@@ -294,10 +294,12 @@
// have unordered initialization.
//
// As a consequence, we can put them into their own llvm.global_ctors entry.
- // This should allow GlobalOpt to fire more often, and allow us to implement
- // the Microsoft C++ ABI, which uses COMDAT elimination to avoid double
- // initializaiton.
- AddGlobalCtor(Fn);
+ //
+ // In addition, put the initializer into a COMDAT group with the global
+ // being initialized. On most platforms, this is a 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, Addr);
DelayedCXXInitPosition.erase(D);
} else {
llvm::DenseMap<const Decl *, unsigned>::iterator I =
@@ -305,7 +307,7 @@
if (I == DelayedCXXInitPosition.end()) {
CXXGlobalInits.push_back(Fn);
} else {
- assert(CXXGlobalInits[I->second] == 0);
+ assert(CXXGlobalInits[I->second] == nullptr);
CXXGlobalInits[I->second] = Fn;
DelayedCXXInitPosition.erase(I);
}
@@ -313,7 +315,7 @@
}
void CodeGenModule::EmitCXXThreadLocalInitFunc() {
- llvm::Function *InitFn = 0;
+ llvm::Function *InitFn = nullptr;
if (!CXXThreadLocalInits.empty()) {
// Generate a guarded initialization function.
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
@@ -363,7 +365,7 @@
// Compute the function suffix from priority. Prepend with zeroes to make
// sure the function names are also ordered as priorities.
std::string PrioritySuffix = llvm::utostr(Priority);
- // Priority is always <= 65535 (enforced by sema)..
+ // Priority is always <= 65535 (enforced by sema).
PrioritySuffix = std::string(6-PrioritySuffix.size(), '0')+PrioritySuffix;
llvm::Function *Fn =
CreateGlobalInitOrDestructFunction(*this, FTy,
@@ -377,8 +379,20 @@
}
}
- llvm::Function *Fn =
- CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");
+ // Include the filename in the symbol name. Including "sub_" matches gcc and
+ // makes sure these symbols appear lexicographically behind the symbols with
+ // priority emitted above.
+ SourceManager &SM = Context.getSourceManager();
+ SmallString<128> FileName(llvm::sys::path::filename(
+ SM.getFileEntryForID(SM.getMainFileID())->getName()));
+ for (size_t i = 0; i < FileName.size(); ++i) {
+ // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens
+ // to be the set of C preprocessing numbers.
+ if (!isPreprocessingNumberBody(FileName[i]))
+ FileName[i] = '_';
+ }
+ llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
+ *this, FTy, llvm::Twine("_GLOBAL__sub_I_", FileName));
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
AddGlobalCtor(Fn);
@@ -408,17 +422,17 @@
bool PerformInit) {
// Check if we need to emit debug info for variable initializer.
if (D->hasAttr<NoDebugAttr>())
- DebugInfo = NULL; // disable debug info indefinitely for this function
+ DebugInfo = nullptr; // disable debug info indefinitely for this function
StartFunction(GlobalDecl(D), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(),
- FunctionArgList(), D->getInit()->getExprLoc());
+ FunctionArgList(), D->getLocation(),
+ D->getInit()->getExprLoc());
// Use guarded initialization if the global variable is weak. This
// occurs for, e.g., instantiated static data members and
// definitions explicitly marked weak.
- if (Addr->getLinkage() == llvm::GlobalValue::WeakODRLinkage ||
- Addr->getLinkage() == llvm::GlobalValue::WeakAnyLinkage) {
+ if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage()) {
EmitCXXGuardedInit(*D, Addr, PerformInit);
} else {
EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
@@ -431,44 +445,49 @@
CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Constant *> Decls,
llvm::GlobalVariable *Guard) {
- StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
- getTypes().arrangeNullaryFunction(),
- FunctionArgList(), SourceLocation());
+ {
+ ArtificialLocation AL(*this, Builder);
+ StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
+ getTypes().arrangeNullaryFunction(), FunctionArgList());
+ // Emit an artificial location for this function.
+ AL.Emit();
- llvm::BasicBlock *ExitBlock = 0;
- if (Guard) {
- // If we have a guard variable, check whether we've already performed these
- // initializations. This happens for TLS initialization functions.
- llvm::Value *GuardVal = Builder.CreateLoad(Guard);
- llvm::Value *Uninit = Builder.CreateIsNull(GuardVal, "guard.uninitialized");
- // Mark as initialized before initializing anything else. If the
- // initializers use previously-initialized thread_local vars, that's
- // probably supposed to be OK, but the standard doesn't say.
- Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1), Guard);
- llvm::BasicBlock *InitBlock = createBasicBlock("init");
- ExitBlock = createBasicBlock("exit");
- Builder.CreateCondBr(Uninit, InitBlock, ExitBlock);
- EmitBlock(InitBlock);
- }
+ llvm::BasicBlock *ExitBlock = nullptr;
+ if (Guard) {
+ // If we have a guard variable, check whether we've already performed
+ // these initializations. This happens for TLS initialization functions.
+ llvm::Value *GuardVal = Builder.CreateLoad(Guard);
+ llvm::Value *Uninit = Builder.CreateIsNull(GuardVal,
+ "guard.uninitialized");
+ // Mark as initialized before initializing anything else. If the
+ // initializers use previously-initialized thread_local vars, that's
+ // probably supposed to be OK, but the standard doesn't say.
+ Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
+ llvm::BasicBlock *InitBlock = createBasicBlock("init");
+ ExitBlock = createBasicBlock("exit");
+ Builder.CreateCondBr(Uninit, InitBlock, ExitBlock);
+ EmitBlock(InitBlock);
+ }
- RunCleanupsScope Scope(*this);
+ RunCleanupsScope Scope(*this);
- // When building in Objective-C++ ARC mode, create an autorelease pool
- // around the global initializers.
- if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) {
- llvm::Value *token = EmitObjCAutoreleasePoolPush();
- EmitObjCAutoreleasePoolCleanup(token);
- }
+ // When building in Objective-C++ ARC mode, create an autorelease pool
+ // around the global initializers.
+ if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) {
+ llvm::Value *token = EmitObjCAutoreleasePoolPush();
+ EmitObjCAutoreleasePoolCleanup(token);
+ }
- for (unsigned i = 0, e = Decls.size(); i != e; ++i)
- if (Decls[i])
- EmitRuntimeCall(Decls[i]);
+ for (unsigned i = 0, e = Decls.size(); i != e; ++i)
+ if (Decls[i])
+ EmitRuntimeCall(Decls[i]);
- Scope.ForceCleanup();
+ Scope.ForceCleanup();
- if (ExitBlock) {
- Builder.CreateBr(ExitBlock);
- EmitBlock(ExitBlock);
+ if (ExitBlock) {
+ Builder.CreateBr(ExitBlock);
+ EmitBlock(ExitBlock);
+ }
}
FinishFunction();
@@ -477,18 +496,22 @@
void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn,
const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
&DtorsAndObjects) {
- StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
- getTypes().arrangeNullaryFunction(),
- FunctionArgList(), SourceLocation());
+ {
+ ArtificialLocation AL(*this, Builder);
+ StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
+ getTypes().arrangeNullaryFunction(), FunctionArgList());
+ // Emit an artificial location for this function.
+ AL.Emit();
- // Emit the dtors, in reverse order from construction.
- for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
- llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
- llvm::CallInst *CI = Builder.CreateCall(Callee,
- DtorsAndObjects[e - i - 1].second);
- // Make sure the call and the callee agree on calling convention.
- if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
- CI->setCallingConv(F->getCallingConv());
+ // Emit the dtors, in reverse order from construction.
+ for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
+ llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
+ llvm::CallInst *CI = Builder.CreateCall(Callee,
+ DtorsAndObjects[e - i - 1].second);
+ // Make sure the call and the callee agree on calling convention.
+ if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
+ CI->setCallingConv(F->getCallingConv());
+ }
}
FinishFunction();
@@ -500,7 +523,8 @@
llvm::Constant *addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray, const VarDecl *VD) {
FunctionArgList args;
- ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy);
+ ImplicitParamDecl dst(getContext(), nullptr, SourceLocation(), nullptr,
+ getContext().VoidPtrTy);
args.push_back(&dst);
const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
@@ -509,7 +533,7 @@
llvm::Function *fn =
CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
- StartFunction(VD, getContext().VoidTy, fn, FI, args, SourceLocation());
+ StartFunction(VD, getContext().VoidTy, fn, FI, args);
emitDestroy(addr, type, destroyer, useEHCleanupForArray);
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index ca31717..9fa478c 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -164,18 +164,21 @@
};
}
-const EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", 0 };
-const EHPersonality EHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", 0 };
-const EHPersonality EHPersonality::NeXT_ObjC = { "__objc_personality_v0", 0 };
-const EHPersonality EHPersonality::GNU_CPlusPlus = { "__gxx_personality_v0", 0};
+const EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", nullptr };
const EHPersonality
-EHPersonality::GNU_CPlusPlus_SJLJ = { "__gxx_personality_sj0", 0 };
+EHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", nullptr };
+const EHPersonality
+EHPersonality::NeXT_ObjC = { "__objc_personality_v0", nullptr };
+const EHPersonality
+EHPersonality::GNU_CPlusPlus = { "__gxx_personality_v0", nullptr };
+const EHPersonality
+EHPersonality::GNU_CPlusPlus_SJLJ = { "__gxx_personality_sj0", nullptr };
const EHPersonality
EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0", "objc_exception_throw"};
const EHPersonality
-EHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", 0 };
+EHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", nullptr };
const EHPersonality
-EHPersonality::GNUstep_ObjC = { "__gnustep_objc_personality_v0", 0 };
+EHPersonality::GNUstep_ObjC = { "__gnustep_objc_personality_v0", nullptr };
static const EHPersonality &getCPersonality(const LangOptions &L) {
if (L.SjLjExceptions)
@@ -418,6 +421,11 @@
void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E,
bool KeepInsertionPoint) {
+ if (CGM.getTarget().getTriple().isWindowsMSVCEnvironment()) {
+ ErrorUnsupported(E, "throw expression");
+ return;
+ }
+
if (!E->getSubExpr()) {
EmitNoreturnRuntimeCallOrInvoke(getReThrowFn(CGM),
ArrayRef<llvm::Value*>());
@@ -462,7 +470,7 @@
// The address of the destructor. If the exception type has a
// trivial destructor (or isn't a record), we just pass null.
- llvm::Constant *Dtor = 0;
+ llvm::Constant *Dtor = nullptr;
if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
if (!Record->hasTrivialDestructor()) {
@@ -487,10 +495,16 @@
return;
const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
- if (FD == 0)
+ if (!FD) {
+ // Check if CapturedDecl is nothrow and create terminate scope for it.
+ if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) {
+ if (CD->isNothrow())
+ EHStack.pushTerminate();
+ }
return;
+ }
const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
- if (Proto == 0)
+ if (!Proto)
return;
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
@@ -555,10 +569,16 @@
return;
const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
- if (FD == 0)
+ if (!FD) {
+ // Check if CapturedDecl is nothrow and pop terminate scope for it.
+ if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) {
+ if (CD->isNothrow())
+ EHStack.popTerminate();
+ }
return;
+ }
const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
- if (Proto == 0)
+ if (!Proto)
return;
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
@@ -574,6 +594,11 @@
}
void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
+ if (CGM.getTarget().getTriple().isWindowsMSVCEnvironment()) {
+ ErrorUnsupported(&S, "try statement");
+ return;
+ }
+
EnterCXXTryStmt(S);
EmitStmt(S.getTryBlock());
ExitCXXTryStmt(S);
@@ -597,7 +622,7 @@
QualType CaughtType = C->getCaughtType();
CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType();
- llvm::Value *TypeInfo = 0;
+ llvm::Value *TypeInfo = nullptr;
if (CaughtType->isObjCObjectPointerType())
TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
else
@@ -675,7 +700,7 @@
assert(!EHStack.empty());
if (!CGM.getLangOpts().Exceptions)
- return 0;
+ return nullptr;
// Check the innermost scope for a cached landing pad. If this is
// a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad.
@@ -1422,7 +1447,7 @@
llvm::Constant *beginCatchFn,
llvm::Constant *endCatchFn,
llvm::Constant *rethrowFn) {
- assert((beginCatchFn != 0) == (endCatchFn != 0) &&
+ assert((beginCatchFn != nullptr) == (endCatchFn != nullptr) &&
"begin/end catch functions not paired");
assert(rethrowFn && "rethrow function is required");
@@ -1437,7 +1462,7 @@
llvm::FunctionType *rethrowFnTy =
cast<llvm::FunctionType>(
cast<llvm::PointerType>(rethrowFn->getType())->getElementType());
- SavedExnVar = 0;
+ SavedExnVar = nullptr;
if (rethrowFnTy->getNumParams())
SavedExnVar = CGF.CreateTempAlloca(CGF.Int8PtrTy, "finally.exn");
@@ -1487,7 +1512,7 @@
CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveAndClearIP();
CGF.EmitBlock(catchBB);
- llvm::Value *exn = 0;
+ llvm::Value *exn = nullptr;
// If there's a begin-catch function, call it.
if (BeginCatchFn) {
@@ -1651,7 +1676,7 @@
// This can always be a call because we necessarily didn't find
// anything on the EH stack which needs our help.
const char *RethrowName = Personality.CatchallRethrowFn;
- if (RethrowName != 0 && !isCleanup) {
+ if (RethrowName != nullptr && !isCleanup) {
EmitRuntimeCall(getCatchallRethrowFn(CGM, RethrowName),
getExceptionFromSlot())
->setDoesNotReturn();
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 1bdd094..966edc4 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -21,6 +21,7 @@
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Attr.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/IR/DataLayout.h"
@@ -53,13 +54,13 @@
llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty,
const Twine &Name) {
if (!Builder.isNamePreserving())
- return new llvm::AllocaInst(Ty, 0, "", AllocaInsertPt);
- return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);
+ return new llvm::AllocaInst(Ty, nullptr, "", AllocaInsertPt);
+ return new llvm::AllocaInst(Ty, nullptr, Name, AllocaInsertPt);
}
void CodeGenFunction::InitTempAlloca(llvm::AllocaInst *Var,
llvm::Value *Init) {
- llvm::StoreInst *Store = new llvm::StoreInst(Init, Var);
+ auto *Store = new llvm::StoreInst(Init, Var);
llvm::BasicBlock *Block = AllocaInsertPt->getParent();
Block->getInstList().insertAfter(&*AllocaInsertPt, Store);
}
@@ -241,11 +242,11 @@
}
}
- CXXDestructorDecl *ReferenceTemporaryDtor = 0;
+ CXXDestructorDecl *ReferenceTemporaryDtor = nullptr;
if (const RecordType *RT =
E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
// Get the destructor for the reference temporary.
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ auto *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
if (!ClassDecl->hasTrivialDestructor())
ReferenceTemporaryDtor = ClassDecl->getDestructor();
}
@@ -323,7 +324,7 @@
llvm::Value *Object = createReferenceTemporary(*this, M, E);
LValue RefTempDst = MakeAddrLValue(Object, M->getType());
- if (llvm::GlobalVariable *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
+ if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
// We should not have emitted the initializer for this temporary as a
// constant.
assert(!Var->hasInitializer());
@@ -343,7 +344,7 @@
for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I)
EmitIgnoredExpr(CommaLHSs[I]);
- if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E)) {
+ if (const auto *opaque = dyn_cast<OpaqueValueExpr>(E)) {
if (opaque->getType()->isRecordType()) {
assert(Adjustments.empty());
return EmitOpaqueValueLValue(opaque);
@@ -352,7 +353,7 @@
// Create and initialize the reference temporary.
llvm::Value *Object = createReferenceTemporary(*this, M, E);
- if (llvm::GlobalVariable *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
+ if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
// If the temporary is a global and has a constant initializer, we may
// have already initialized it.
if (!Var->hasInitializer()) {
@@ -452,8 +453,8 @@
if (Address->getType()->getPointerAddressSpace())
return;
- llvm::Value *Cond = 0;
- llvm::BasicBlock *Done = 0;
+ llvm::Value *Cond = nullptr;
+ llvm::BasicBlock *Done = nullptr;
if (SanOpts->Null) {
// The glvalue must not be an empty glvalue.
@@ -467,7 +468,7 @@
llvm::BasicBlock *Rest = createBasicBlock("not.null");
Builder.CreateCondBr(Cond, Rest, Done);
EmitBlock(Rest);
- Cond = 0;
+ Cond = nullptr;
}
}
@@ -590,7 +591,7 @@
// For compatibility with existing code, we treat arrays of length 0 or
// 1 as flexible array members.
const ArrayType *AT = E->getType()->castAsArrayTypeUnsafe();
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
if (CAT->getSize().ugt(1))
return false;
} else if (!isa<IncompleteArrayType>(AT))
@@ -599,10 +600,10 @@
E = E->IgnoreParens();
// A flexible array member must be the last member in the class.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ if (const auto *ME = dyn_cast<MemberExpr>(E)) {
// FIXME: If the base type of the member expr is not FD->getParent(),
// this should not be treated as a flexible array member access.
- if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
+ if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
RecordDecl::field_iterator FI(
DeclContext::decl_iterator(const_cast<FieldDecl *>(FD)));
return ++FI == FD->getParent()->field_end();
@@ -624,19 +625,19 @@
Base = Base->IgnoreParens();
- if (const CastExpr *CE = dyn_cast<CastExpr>(Base)) {
+ if (const auto *CE = dyn_cast<CastExpr>(Base)) {
if (CE->getCastKind() == CK_ArrayToPointerDecay &&
!isFlexibleArrayMemberExpr(CE->getSubExpr())) {
IndexedType = CE->getSubExpr()->getType();
const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe();
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
return CGF.Builder.getInt(CAT->getSize());
- else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT))
+ else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
return CGF.getVLASize(VAT).first;
}
}
- return 0;
+ return nullptr;
}
void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
@@ -705,7 +706,7 @@
RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
if (Ty->isVoidType())
- return RValue::get(0);
+ return RValue::get(nullptr);
switch (getEvaluationKind(Ty)) {
case TEK_Complex: {
@@ -820,7 +821,7 @@
return EmitLambdaLValue(cast<LambdaExpr>(E));
case Expr::ExprWithCleanupsClass: {
- const ExprWithCleanups *cleanups = cast<ExprWithCleanups>(E);
+ const auto *cleanups = cast<ExprWithCleanups>(E);
enterFullExpression(cleanups);
RunCleanupsScope Scope(*this);
return EmitLValue(cleanups->getSubExpr());
@@ -888,8 +889,8 @@
// Otherwise, all object types satisfy this except C++ classes with
// mutable subobjects or non-trivial copy/destroy behavior.
- if (const RecordType *RT = dyn_cast<RecordType>(type))
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (const auto *RT = dyn_cast<RecordType>(type))
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
if (RD->hasMutableFields() || !RD->isTrivial())
return false;
@@ -911,7 +912,7 @@
};
static ConstantEmissionKind checkVarTypeForConstantEmission(QualType type) {
type = type.getCanonicalType();
- if (const ReferenceType *ref = dyn_cast<ReferenceType>(type)) {
+ if (const auto *ref = dyn_cast<ReferenceType>(type)) {
if (isConstantEmittableObjectType(ref->getPointeeType()))
return CEK_AsValueOrReference;
return CEK_AsReferenceOnly;
@@ -934,7 +935,7 @@
ConstantEmissionKind CEK;
if (isa<ParmVarDecl>(value)) {
CEK = CEK_None;
- } else if (VarDecl *var = dyn_cast<VarDecl>(value)) {
+ } else if (auto *var = dyn_cast<VarDecl>(value)) {
CEK = checkVarTypeForConstantEmission(var->getType());
} else if (isa<EnumConstantDecl>(value)) {
CEK = CEK_AsValueOnly;
@@ -1047,7 +1048,7 @@
llvm::APInt Min, End;
if (!getRangeForType(*this, Ty, Min, End,
CGM.getCodeGenOpts().StrictEnums))
- return 0;
+ return nullptr;
llvm::MDBuilder MDHelper(getLLVMContext());
return MDHelper.createRange(Min, End);
@@ -1065,7 +1066,7 @@
const llvm::Type *EltTy =
cast<llvm::PointerType>(Addr->getType())->getElementType();
- const llvm::VectorType *VTy = cast<llvm::VectorType>(EltTy);
+ const auto *VTy = cast<llvm::VectorType>(EltTy);
// Handle vectors of size 3, like size 4 for better performance.
if (VTy->getNumElements() == 3) {
@@ -1181,7 +1182,7 @@
// Handle vectors differently to get better performance.
if (Ty->isVectorType()) {
llvm::Type *SrcTy = Value->getType();
- llvm::VectorType *VecTy = cast<llvm::VectorType>(SrcTy);
+ auto *VecTy = cast<llvm::VectorType>(SrcTy);
// Handle vec3 special.
if (VecTy->getNumElements() == 3) {
llvm::LLVMContext &VMContext = getLLVMContext();
@@ -1202,7 +1203,7 @@
MaskV, "extractVec");
SrcTy = llvm::VectorType::get(VecTy->getElementType(), 4);
}
- llvm::PointerType *DstPtr = cast<llvm::PointerType>(Addr->getType());
+ auto *DstPtr = cast<llvm::PointerType>(Addr->getType());
if (DstPtr->getElementType() != SrcTy) {
llvm::Type *MemTy =
llvm::PointerType::get(SrcTy, DstPtr->getAddressSpace());
@@ -1276,6 +1277,10 @@
if (LV.isExtVectorElt())
return EmitLoadOfExtVectorElementLValue(LV);
+ // Global Register variables always invoke intrinsics
+ if (LV.isGlobalReg())
+ return EmitLoadOfGlobalRegLValue(LV);
+
assert(LV.isBitField() && "Unknown LValue type!");
return EmitLoadOfBitfieldLValue(LV);
}
@@ -1343,6 +1348,16 @@
return RValue::get(Vec);
}
+/// @brief Load of global gamed gegisters are always calls to intrinsics.
+RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) {
+ assert(LV.getType()->isIntegerType() && "Bad type for register variable");
+ llvm::MDNode *RegName = dyn_cast<llvm::MDNode>(LV.getGlobalReg());
+ assert(RegName && "Register LValue is not metadata");
+ llvm::Type *Types[] = { CGM.getTypes().ConvertType(LV.getType()) };
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
+ llvm::Value* Call = Builder.CreateCall(F, RegName);
+ return RValue::get(Call);
+}
/// EmitStoreThroughLValue - Store the specified rvalue into the specified
@@ -1370,6 +1385,9 @@
if (Dst.isExtVectorElt())
return EmitStoreThroughExtVectorComponentLValue(Src, Dst);
+ if (Dst.isGlobalReg())
+ return EmitStoreThroughGlobalRegLValue(Src, Dst);
+
assert(Dst.isBitField() && "Unknown LValue type");
return EmitStoreThroughBitfieldLValue(Src, Dst);
}
@@ -1581,7 +1599,18 @@
Store->setAlignment(Dst.getAlignment().getQuantity());
}
-// setObjCGCLValueClass - sets class of he lvalue for the purpose of
+/// @brief Store of global named registers are always calls to intrinsics.
+void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst) {
+ assert(Dst.getType()->isIntegerType() && "Bad type for register variable");
+ llvm::MDNode *RegName = dyn_cast<llvm::MDNode>(Dst.getGlobalReg());
+ assert(RegName && "Register LValue is not metadata");
+ llvm::Type *Types[] = { CGM.getTypes().ConvertType(Dst.getType()) };
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
+ llvm::Value *Value = Src.getScalarVal();
+ Builder.CreateCall2(F, RegName, Value);
+}
+
+// setObjCGCLValueClass - sets class of the lvalue for the purpose of
// generating write-barries API. It is currently a global, ivar,
// or neither.
static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
@@ -1603,14 +1632,14 @@
}
}
LV.setObjCIvar(true);
- ObjCIvarRefExpr *Exp = cast<ObjCIvarRefExpr>(const_cast<Expr*>(E));
+ auto *Exp = cast<ObjCIvarRefExpr>(const_cast<Expr *>(E));
LV.setBaseIvarExp(Exp->getBase());
LV.setObjCArray(E->getType()->isArrayType());
return;
}
- if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
+ if (const auto *Exp = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
if (VD->hasGlobalStorage()) {
LV.setGlobalObjCRef(true);
LV.setThreadLocalRef(VD->getTLSKind() != VarDecl::TLS_None);
@@ -1620,12 +1649,12 @@
return;
}
- if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E)) {
+ if (const auto *Exp = dyn_cast<UnaryOperator>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
return;
}
- if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) {
+ if (const auto *Exp = dyn_cast<ParenExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
if (LV.isObjCIvar()) {
// If cast is to a structure pointer, follow gcc's behavior and make it
@@ -1639,27 +1668,27 @@
return;
}
- if (const GenericSelectionExpr *Exp = dyn_cast<GenericSelectionExpr>(E)) {
+ if (const auto *Exp = dyn_cast<GenericSelectionExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getResultExpr(), LV);
return;
}
- if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E)) {
+ if (const auto *Exp = dyn_cast<ImplicitCastExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
return;
}
- if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E)) {
+ if (const auto *Exp = dyn_cast<CStyleCastExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
return;
}
- if (const ObjCBridgedCastExpr *Exp = dyn_cast<ObjCBridgedCastExpr>(E)) {
+ if (const auto *Exp = dyn_cast<ObjCBridgedCastExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
return;
}
- if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
+ if (const auto *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
if (LV.isObjCIvar() && !LV.isObjCArray())
// Using array syntax to assigning to what an ivar points to is not
@@ -1672,7 +1701,7 @@
return;
}
- if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
+ if (const auto *Exp = dyn_cast<MemberExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getBase(), LV, true);
// We don't know if member is an 'ivar', but this flag is looked at
// only in the context of LV.isObjCIvar().
@@ -1740,14 +1769,44 @@
return CGF.EmitLValueForField(LV, FD);
}
+/// Named Registers are named metadata pointing to the register name
+/// which will be read from/written to as an argument to the intrinsic
+/// @llvm.read/write_register.
+/// So far, only the name is being passed down, but other options such as
+/// register type, allocation type or even optimization options could be
+/// passed down via the metadata node.
+static LValue EmitGlobalNamedRegister(const VarDecl *VD,
+ CodeGenModule &CGM,
+ CharUnits Alignment) {
+ SmallString<64> Name("llvm.named.register.");
+ AsmLabelAttr *Asm = VD->getAttr<AsmLabelAttr>();
+ assert(Asm->getLabel().size() < 64-Name.size() &&
+ "Register name too big");
+ Name.append(Asm->getLabel());
+ llvm::NamedMDNode *M =
+ CGM.getModule().getOrInsertNamedMetadata(Name);
+ if (M->getNumOperands() == 0) {
+ llvm::MDString *Str = llvm::MDString::get(CGM.getLLVMContext(),
+ Asm->getLabel());
+ llvm::Value *Ops[] = { Str };
+ M->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops));
+ }
+ return LValue::MakeGlobalReg(M->getOperand(0), VD->getType(), Alignment);
+}
+
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const NamedDecl *ND = E->getDecl();
CharUnits Alignment = getContext().getDeclAlign(ND);
QualType T = E->getType();
- // A DeclRefExpr for a reference initialized by a constant expression can
- // appear without being odr-used. Directly emit the constant initializer.
- if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ if (const auto *VD = dyn_cast<VarDecl>(ND)) {
+ // Global Named registers access via intrinsics only
+ if (VD->getStorageClass() == SC_Register &&
+ VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
+ return EmitGlobalNamedRegister(VD, CGM, Alignment);
+
+ // A DeclRefExpr for a reference initialized by a constant expression can
+ // appear without being odr-used. Directly emit the constant initializer.
const Expr *Init = VD->getAnyInitializer(VD);
if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() &&
VD->isUsableInConstantExpressions(getContext()) &&
@@ -1768,12 +1827,12 @@
"Should not use decl without marking it used!");
if (ND->hasAttr<WeakRefAttr>()) {
- const ValueDecl *VD = cast<ValueDecl>(ND);
+ const auto *VD = cast<ValueDecl>(ND);
llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD);
return MakeAddrLValue(Aliasee, T, Alignment);
}
- if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ if (const auto *VD = dyn_cast<VarDecl>(ND)) {
// Check if this is a global variable.
if (VD->hasLinkage() || VD->isStaticDataMember())
return EmitGlobalVarDeclLValue(*this, E, VD);
@@ -1832,7 +1891,7 @@
return LV;
}
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND))
return EmitFunctionDeclLValue(*this, E, FD);
llvm_unreachable("Unhandled DeclRefExpr");
@@ -1922,11 +1981,9 @@
/*Pascal = */false,
Ty, Loc);
llvm::Constant *C = CGM.GetConstantArrayFromStringLiteral(SL);
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), C->getType(),
- !CGM.getLangOpts().WritableStrings,
- llvm::GlobalValue::PrivateLinkage,
- C, GlobalName);
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), C->getType(), !CGM.getLangOpts().WritableStrings,
+ llvm::GlobalValue::PrivateLinkage, C, GlobalName);
const unsigned WideAlignment =
Context.getTypeAlignInChars(Ty).getQuantity();
GV->setAlignment(WideAlignment);
@@ -1953,37 +2010,31 @@
case PredefinedExpr::Function:
case PredefinedExpr::LFunction:
case PredefinedExpr::FuncDName:
+ case PredefinedExpr::FuncSig:
case PredefinedExpr::PrettyFunction: {
PredefinedExpr::IdentType IdentType = E->getIdentType();
- std::string GlobalVarName;
+ std::string GVName;
+ // FIXME: We should use the string literal mangling for the Microsoft C++
+ // ABI so that strings get merged.
switch (IdentType) {
default: llvm_unreachable("Invalid type");
- case PredefinedExpr::Func:
- GlobalVarName = "__func__.";
- break;
- case PredefinedExpr::Function:
- GlobalVarName = "__FUNCTION__.";
- break;
- case PredefinedExpr::FuncDName:
- GlobalVarName = "__FUNCDNAME__.";
- break;
- case PredefinedExpr::LFunction:
- GlobalVarName = "L__FUNCTION__.";
- break;
- case PredefinedExpr::PrettyFunction:
- GlobalVarName = "__PRETTY_FUNCTION__.";
- break;
+ case PredefinedExpr::Func: GVName = "__func__."; break;
+ case PredefinedExpr::Function: GVName = "__FUNCTION__."; break;
+ case PredefinedExpr::FuncDName: GVName = "__FUNCDNAME__."; break;
+ case PredefinedExpr::FuncSig: GVName = "__FUNCSIG__."; break;
+ case PredefinedExpr::LFunction: GVName = "L__FUNCTION__."; break;
+ case PredefinedExpr::PrettyFunction: GVName = "__PRETTY_FUNCTION__."; break;
}
StringRef FnName = CurFn->getName();
if (FnName.startswith("\01"))
FnName = FnName.substr(1);
- GlobalVarName += FnName;
+ GVName += FnName;
// If this is outside of a function use the top level decl.
const Decl *CurDecl = CurCodeDecl;
- if (CurDecl == 0 || isa<VarDecl>(CurDecl))
+ if (!CurDecl || isa<VarDecl>(CurDecl))
CurDecl = getContext().getTranslationUnitDecl();
const Type *ElemType = E->getType()->getArrayElementTypeNoTypeQual();
@@ -2010,15 +2061,13 @@
getContext().getTypeSizeInChars(ElemType).getQuantity(),
FunctionName, RawChars);
C = GetAddrOfConstantWideString(RawChars,
- GlobalVarName.c_str(),
+ GVName.c_str(),
getContext(),
E->getType(),
E->getLocation(),
CGM);
} else {
- C = CGM.GetAddrOfConstantCString(FunctionName,
- GlobalVarName.c_str(),
- 1);
+ C = CGM.GetAddrOfConstantCString(FunctionName, GVName.c_str(), 1);
}
return MakeAddrLValue(C, E->getType());
}
@@ -2036,7 +2085,7 @@
/// integer, 1 for a floating point value, and -1 for anything else.
llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
// Only emit each type's descriptor once.
- if (llvm::Constant *C = CGM.getTypeDescriptor(T))
+ if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T))
return C;
uint16_t TypeKind = -1;
@@ -2056,7 +2105,7 @@
SmallString<32> Buffer;
CGM.getDiags().ConvertArgToString(DiagnosticsEngine::ak_qualtype,
(intptr_t)T.getAsOpaquePtr(),
- 0, 0, 0, 0, 0, 0, Buffer,
+ nullptr, 0, nullptr, 0, nullptr, 0, Buffer,
ArrayRef<intptr_t>());
llvm::Constant *Components[] = {
@@ -2065,15 +2114,13 @@
};
llvm::Constant *Descriptor = llvm::ConstantStruct::getAnon(Components);
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Descriptor->getType(),
- /*isConstant=*/true,
- llvm::GlobalVariable::PrivateLinkage,
- Descriptor);
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), Descriptor->getType(),
+ /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, Descriptor);
GV->setUnnamedAddr(true);
// Remember the descriptor for this type.
- CGM.setTypeDescriptor(T, GV);
+ CGM.setTypeDescriptorInMap(T, GV);
return GV;
}
@@ -2153,7 +2200,7 @@
EmitBlock(Handler);
llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
- llvm::GlobalValue *InfoPtr =
+ auto *InfoPtr =
new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false,
llvm::GlobalVariable::PrivateLinkage, Info);
InfoPtr->setUnnamedAddr(true);
@@ -2232,14 +2279,14 @@
/// array to pointer, return the array subexpression.
static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
// If this isn't just an array->pointer decay, bail out.
- const CastExpr *CE = dyn_cast<CastExpr>(E);
- if (CE == 0 || CE->getCastKind() != CK_ArrayToPointerDecay)
+ const auto *CE = dyn_cast<CastExpr>(E);
+ if (!CE || CE->getCastKind() != CK_ArrayToPointerDecay)
return 0;
// If this is a decay from variable width array, bail out.
const Expr *SubExpr = CE->getSubExpr();
if (SubExpr->getType()->isVariableArrayType())
- return 0;
+ return nullptr;
return SubExpr;
}
@@ -2271,7 +2318,7 @@
// We know that the pointer points to a type of the correct size, unless the
// size is a VLA or Objective-C interface.
- llvm::Value *Address = 0;
+ llvm::Value *Address = nullptr;
CharUnits ArrayAlignment;
if (const VariableArrayType *vla =
getContext().getAsVariableArrayType(E->getType())) {
@@ -2317,7 +2364,7 @@
LValue ArrayLV;
// For simple multidimensional array indexing, set the 'accessed' flag for
// better bounds-checking of the base expression.
- if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(Array))
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Array))
ArrayLV = EmitArraySubscriptExpr(ASE, /*Accessed*/ true);
else
ArrayLV = EmitLValue(Array);
@@ -2444,16 +2491,16 @@
BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess);
NamedDecl *ND = E->getMemberDecl();
- if (FieldDecl *Field = dyn_cast<FieldDecl>(ND)) {
+ if (auto *Field = dyn_cast<FieldDecl>(ND)) {
LValue LV = EmitLValueForField(BaseLV, Field);
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
- if (VarDecl *VD = dyn_cast<VarDecl>(ND))
+ if (auto *VD = dyn_cast<VarDecl>(ND))
return EmitGlobalVarDeclLValue(*this, E, VD);
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND))
return EmitFunctionDeclLValue(*this, E, FD);
llvm_unreachable("Unhandled member declaration!");
@@ -2769,7 +2816,7 @@
case CK_Dynamic: {
LValue LV = EmitLValue(E->getSubExpr());
llvm::Value *V = LV.getAddress();
- const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(E);
+ const auto *DCE = cast<CXXDynamicCastExpr>(E);
return MakeAddrLValue(EmitDynamicCast(V, DCE), E->getType());
}
@@ -2785,8 +2832,7 @@
case CK_DerivedToBase: {
const RecordType *DerivedClassTy =
E->getSubExpr()->getType()->getAs<RecordType>();
- CXXRecordDecl *DerivedClassDecl =
- cast<CXXRecordDecl>(DerivedClassTy->getDecl());
+ auto *DerivedClassDecl = cast<CXXRecordDecl>(DerivedClassTy->getDecl());
LValue LV = EmitLValue(E->getSubExpr());
llvm::Value *This = LV.getAddress();
@@ -2803,8 +2849,7 @@
return EmitAggExprToLValue(E);
case CK_BaseToDerived: {
const RecordType *DerivedClassTy = E->getType()->getAs<RecordType>();
- CXXRecordDecl *DerivedClassDecl =
- cast<CXXRecordDecl>(DerivedClassTy->getDecl());
+ auto *DerivedClassDecl = cast<CXXRecordDecl>(DerivedClassTy->getDecl());
LValue LV = EmitLValue(E->getSubExpr());
@@ -2824,7 +2869,7 @@
}
case CK_LValueBitCast: {
// This must be a reinterpret_cast (or c-style equivalent).
- const ExplicitCastExpr *CE = cast<ExplicitCastExpr>(E);
+ const auto *CE = cast<ExplicitCastExpr>(E);
LValue LV = EmitLValue(E->getSubExpr());
llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
@@ -2876,6 +2921,10 @@
SourceLocation Loc = E->getLocStart();
// Force column info to be generated so we can differentiate
// multiple call sites on the same line in the debug info.
+ // FIXME: This is insufficient. Two calls coming from the same macro
+ // expansion will still get the same line/column and break debug info. It's
+ // possible that LLVM can be fixed to not rely on this uniqueness, at which
+ // point this workaround can be removed.
const FunctionDecl* Callee = E->getDirectCallee();
bool ForceColumnInfo = Callee && Callee->isInlineSpecified();
DI->EmitLocation(Builder, Loc, ForceColumnInfo);
@@ -2885,10 +2934,10 @@
if (E->getCallee()->getType()->isBlockPointerType())
return EmitBlockCallExpr(E, ReturnValue);
- if (const CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(E))
+ if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E))
return EmitCXXMemberCallExpr(CE, ReturnValue);
- if (const CUDAKernelCallExpr *CE = dyn_cast<CUDAKernelCallExpr>(E))
+ if (const auto *CE = dyn_cast<CUDAKernelCallExpr>(E))
return EmitCUDAKernelCallExpr(CE, ReturnValue);
const Decl *TargetDecl = E->getCalleeDecl();
@@ -2897,12 +2946,12 @@
return EmitBuiltinExpr(FD, builtinID, E);
}
- if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E))
+ if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E))
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl))
return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue);
- if (const CXXPseudoDestructorExpr *PseudoDtor
- = dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
+ if (const auto *PseudoDtor =
+ dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
QualType DestroyedType = PseudoDtor->getDestroyedType();
if (getLangOpts().ObjCAutoRefCount &&
DestroyedType->isObjCLifetimeType() &&
@@ -2912,7 +2961,7 @@
// If the pseudo-expression names a retainable object with weak or
// strong lifetime, the object shall be released.
Expr *BaseExpr = PseudoDtor->getBase();
- llvm::Value *BaseValue = NULL;
+ llvm::Value *BaseValue = nullptr;
Qualifiers BaseQuals;
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
@@ -2952,7 +3001,7 @@
EmitScalarExpr(E->getCallee());
}
- return RValue::get(0);
+ return RValue::get(nullptr);
}
llvm::Value *Callee = EmitScalarExpr(E->getCallee());
@@ -3098,7 +3147,7 @@
LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
// FIXME: A lot of the code below could be shared with EmitMemberExpr.
- llvm::Value *BaseValue = 0;
+ llvm::Value *BaseValue = nullptr;
const Expr *BaseExpr = E->getBase();
Qualifiers BaseQuals;
QualType ObjectTy;
@@ -3140,11 +3189,15 @@
CalleeType = getContext().getCanonicalType(CalleeType);
- const FunctionType *FnType
- = cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
+ const auto *FnType =
+ cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
// Force column info to differentiate multiple inlined call sites on
// the same line, analoguous to EmitCallExpr.
+ // FIXME: This is insufficient. Two calls coming from the same macro expansion
+ // will still get the same line/column and break debug info. It's possible
+ // that LLVM can be fixed to not rely on this uniqueness, at which point this
+ // workaround can be removed.
bool ForceColumnInfo = false;
if (const FunctionDecl* FD = dyn_cast_or_null<const FunctionDecl>(TargetDecl))
ForceColumnInfo = FD->isInlineSpecified();
@@ -3297,7 +3350,7 @@
// If this semantic expression is an opaque value, bind it
// to the result of its source expression.
- if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
+ if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
// If this is the result expression, we may need to evaluate
// directly into the slot.
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 6c50521..760e6f1 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -389,9 +389,9 @@
// already-constructed members if an initializer throws.
// For that, we'll need an EH cleanup.
QualType::DestructionKind dtorKind = elementType.isDestructedType();
- llvm::AllocaInst *endOfInit = 0;
+ llvm::AllocaInst *endOfInit = nullptr;
EHScopeStack::stable_iterator cleanup;
- llvm::Instruction *cleanupDominator = 0;
+ llvm::Instruction *cleanupDominator = nullptr;
if (CGF.needsEHCleanup(dtorKind)) {
// In principle we could tell the cleanup where we are more
// directly, but the control flow can get so varied here that it
@@ -539,7 +539,7 @@
if (castE->getCastKind() == CK_NoOp)
continue;
}
- return 0;
+ return nullptr;
}
}
@@ -1044,7 +1044,7 @@
return;
case TEK_Scalar:
if (LV.isSimple()) {
- CGF.EmitScalarInit(E, /*D=*/0, LV, /*Captured=*/false);
+ CGF.EmitScalarInit(E, /*D=*/nullptr, LV, /*Captured=*/false);
} else {
CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV);
}
@@ -1165,7 +1165,7 @@
// We'll need to enter cleanup scopes in case any of the member
// initializers throw an exception.
SmallVector<EHScopeStack::stable_iterator, 16> cleanups;
- llvm::Instruction *cleanupDominator = 0;
+ llvm::Instruction *cleanupDominator = nullptr;
// Here we iterate over the fields; this makes it simpler to both
// default-initialize fields and skip over unnamed fields.
@@ -1252,7 +1252,7 @@
// If this is an initlist expr, sum up the size of sizes of the (present)
// elements. If this is something weird, assume the whole thing is non-zero.
const InitListExpr *ILE = dyn_cast<InitListExpr>(E);
- if (ILE == 0 || !CGF.getTypes().isZeroInitializable(ILE->getType()))
+ if (!ILE || !CGF.getTypes().isZeroInitializable(ILE->getType()))
return CGF.getContext().getTypeSizeInChars(E->getType());
// InitListExprs for structs have to be handled carefully. If there are
@@ -1301,7 +1301,8 @@
CodeGenFunction &CGF) {
// If the slot is already known to be zeroed, nothing to do. Don't mess with
// volatile stores.
- if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == 0) return;
+ if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == nullptr)
+ return;
// C++ objects with a user-declared constructor don't need zero'ing.
if (CGF.getLangOpts().CPlusPlus)
@@ -1348,7 +1349,7 @@
void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot) {
assert(E && hasAggregateEvaluationKind(E->getType()) &&
"Invalid aggregate expression to emit");
- assert((Slot.getAddr() != 0 || Slot.isIgnored()) &&
+ assert((Slot.getAddr() != nullptr || Slot.isIgnored()) &&
"slot has bits but no address");
// Optimize the slot if possible.
@@ -1468,10 +1469,10 @@
// memcpy, as well as the TBAA tags for the members of the struct, in case
// the optimizer wishes to expand it in to scalar memory operations.
llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty);
-
+
Builder.CreateMemCpy(DestPtr, SrcPtr,
llvm::ConstantInt::get(IntPtrTy,
TypeInfo.first.getQuantity()),
alignment.getQuantity(), isVolatile,
- /*TBAATag=*/0, TBAAStructTag);
+ /*TBAATag=*/nullptr, TBAAStructTag);
}
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index f71a3de..548cd48 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -95,7 +95,7 @@
const Expr *Base = ME->getBase();
bool CanUseVirtualCall = MD->isVirtual() && !ME->hasQualifier();
- const CXXMethodDecl *DevirtualizedMethod = NULL;
+ const CXXMethodDecl *DevirtualizedMethod = nullptr;
if (CanUseVirtualCall && CanDevirtualizeMemberFunctionCall(Base, MD)) {
const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();
DevirtualizedMethod = MD->getCorrespondingMethodInClass(BestDynamicDecl);
@@ -111,7 +111,7 @@
// one or the one of the full expression, we would have to build
// a derived-to-base cast to compute the correct this pointer, but
// we don't have support for that yet, so do a virtual call.
- DevirtualizedMethod = NULL;
+ DevirtualizedMethod = nullptr;
}
// If the return types are not the same, this might be a case where more
// code needs to run to compensate for it. For example, the derived
@@ -121,7 +121,7 @@
if (DevirtualizedMethod &&
DevirtualizedMethod->getReturnType().getCanonicalType() !=
MD->getReturnType().getCanonicalType())
- DevirtualizedMethod = NULL;
+ DevirtualizedMethod = nullptr;
}
llvm::Value *This;
@@ -132,10 +132,10 @@
if (MD->isTrivial()) {
- if (isa<CXXDestructorDecl>(MD)) return RValue::get(0);
+ if (isa<CXXDestructorDecl>(MD)) return RValue::get(nullptr);
if (isa<CXXConstructorDecl>(MD) &&
cast<CXXConstructorDecl>(MD)->isDefaultConstructor())
- return RValue::get(0);
+ return RValue::get(nullptr);
if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) {
// We don't like to generate the trivial copy/move assignment operator
@@ -158,7 +158,7 @@
// Compute the function type we're calling.
const CXXMethodDecl *CalleeDecl = DevirtualizedMethod ? DevirtualizedMethod : MD;
- const CGFunctionInfo *FInfo = 0;
+ const CGFunctionInfo *FInfo = nullptr;
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(CalleeDecl))
FInfo = &CGM.getTypes().arrangeCXXDestructor(Dtor,
Dtor_Complete);
@@ -199,9 +199,9 @@
Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty);
}
EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
- /*ImplicitParam=*/0, QualType(), 0, 0);
+ /*ImplicitParam=*/nullptr, QualType(), nullptr,nullptr);
}
- return RValue::get(0);
+ return RValue::get(nullptr);
}
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
@@ -226,7 +226,7 @@
}
return EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
- /*ImplicitParam=*/0, QualType(),
+ /*ImplicitParam=*/nullptr, QualType(),
CE->arg_begin(), CE->arg_end());
}
@@ -299,7 +299,7 @@
llvm::Value *Callee = EmitCXXOperatorMemberCallee(E, MD, This);
return EmitCXXMemberCall(MD, E->getExprLoc(), Callee, ReturnValue, This,
- /*ImplicitParam=*/0, QualType(),
+ /*ImplicitParam=*/nullptr, QualType(),
E->arg_begin() + 1, E->arg_end());
}
@@ -586,7 +586,7 @@
// size := sizeWithoutCookie + cookieSize
// and check whether it overflows.
- llvm::Value *hasOverflow = 0;
+ llvm::Value *hasOverflow = nullptr;
// If numElementsWidth > sizeWidth, then one way or another, we're
// going to have to do a comparison for (2), and this happens to
@@ -726,8 +726,8 @@
CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType);
switch (CGF.getEvaluationKind(AllocType)) {
case TEK_Scalar:
- CGF.EmitScalarInit(Init, 0, CGF.MakeAddrLValue(NewPtr, AllocType,
- Alignment),
+ CGF.EmitScalarInit(Init, nullptr, CGF.MakeAddrLValue(NewPtr, AllocType,
+ Alignment),
false);
return;
case TEK_Complex:
@@ -764,10 +764,10 @@
unsigned initializerElements = 0;
const Expr *Init = E->getInitializer();
- llvm::AllocaInst *endOfInit = 0;
+ llvm::AllocaInst *endOfInit = nullptr;
QualType::DestructionKind dtorKind = elementType.isDestructedType();
EHScopeStack::stable_iterator cleanup;
- llvm::Instruction *cleanupDominator = 0;
+ llvm::Instruction *cleanupDominator = nullptr;
// If the initializer is an initializer list, first do the explicit elements.
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
@@ -814,20 +814,22 @@
explicitPtr = Builder.CreateBitCast(explicitPtr, beginPtr->getType());
}
+ llvm::ConstantInt *constNum = dyn_cast<llvm::ConstantInt>(numElements);
+
+ // If all elements have already been initialized, skip the whole loop.
+ if (constNum && constNum->getZExtValue() <= initializerElements) {
+ // If there was a cleanup, deactivate it.
+ if (cleanupDominator)
+ DeactivateCleanupBlock(cleanup, cleanupDominator);
+ return;
+ }
+
// Create the continuation block.
llvm::BasicBlock *contBB = createBasicBlock("new.loop.end");
// If the number of elements isn't constant, we have to now check if there is
// anything left to initialize.
- if (llvm::ConstantInt *constNum = dyn_cast<llvm::ConstantInt>(numElements)) {
- // If all elements have already been initialized, skip the whole loop.
- if (constNum->getZExtValue() <= initializerElements) {
- // If there was a cleanup, deactivate it.
- if (cleanupDominator)
- DeactivateCleanupBlock(cleanup, cleanupDominator);
- return;
- }
- } else {
+ if (!constNum) {
llvm::BasicBlock *nonEmptyBB = createBasicBlock("new.loop.nonempty");
llvm::Value *isEmpty = Builder.CreateICmpEQ(explicitPtr, endPtr,
"array.isempty");
@@ -1159,8 +1161,8 @@
minElements = ILE->getNumInits();
}
- llvm::Value *numElements = 0;
- llvm::Value *allocSizeWithoutCookie = 0;
+ llvm::Value *numElements = nullptr;
+ llvm::Value *allocSizeWithoutCookie = nullptr;
llvm::Value *allocSize =
EmitCXXNewAllocSize(*this, E, minElements, numElements,
allocSizeWithoutCookie);
@@ -1194,8 +1196,8 @@
bool nullCheck = allocatorType->isNothrow(getContext()) &&
(!allocType.isPODType(getContext()) || E->hasInitializer());
- llvm::BasicBlock *nullCheckBB = 0;
- llvm::BasicBlock *contBB = 0;
+ llvm::BasicBlock *nullCheckBB = nullptr;
+ llvm::BasicBlock *contBB = nullptr;
llvm::Value *allocation = RV.getScalarVal();
unsigned AS = allocation->getType()->getPointerAddressSpace();
@@ -1219,7 +1221,7 @@
// If there's an operator delete, enter a cleanup to call it if an
// exception is thrown.
EHScopeStack::stable_iterator operatorDeleteCleanup;
- llvm::Instruction *cleanupDominator = 0;
+ llvm::Instruction *cleanupDominator = nullptr;
if (E->getOperatorDelete() &&
!E->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocatorArgs);
@@ -1286,7 +1288,7 @@
CallArgList DeleteArgs;
// Check if we need to pass the size to the delete operator.
- llvm::Value *Size = 0;
+ llvm::Value *Size = nullptr;
QualType SizeTy;
if (DeleteFTy->getNumParams() == 2) {
SizeTy = DeleteFTy->getParamType(1);
@@ -1332,7 +1334,7 @@
bool UseGlobalDelete) {
// Find the destructor for the type, if applicable. If the
// destructor is virtual, we'll just emit the vcall and return.
- const CXXDestructorDecl *Dtor = 0;
+ const CXXDestructorDecl *Dtor = nullptr;
if (const RecordType *RT = ElementType->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (RD->hasDefinition() && !RD->hasTrivialDestructor()) {
@@ -1469,8 +1471,8 @@
const CXXDeleteExpr *E,
llvm::Value *deletedPtr,
QualType elementType) {
- llvm::Value *numElements = 0;
- llvm::Value *allocatedPtr = 0;
+ llvm::Value *numElements = nullptr;
+ llvm::Value *allocatedPtr = nullptr;
CharUnits cookieSize;
CGF.CGM.getCXXABI().ReadArrayCookie(CGF, deletedPtr, E, elementType,
numElements, allocatedPtr, cookieSize);
@@ -1818,9 +1820,9 @@
// If the value of v is a null pointer value in the pointer case, the result
// is the null pointer value of type T.
bool ShouldNullCheckSrcValue = SrcTy->isPointerType();
-
- llvm::BasicBlock *CastNull = 0;
- llvm::BasicBlock *CastNotNull = 0;
+
+ llvm::BasicBlock *CastNull = nullptr;
+ llvm::BasicBlock *CastNotNull = nullptr;
llvm::BasicBlock *CastEnd = createBasicBlock("dynamic_cast.end");
if (ShouldNullCheckSrcValue) {
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 1f84c86..7244b9e 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -306,7 +306,7 @@
unsigned ComplexAlign = C.getTypeAlignInChars(ComplexTy).getQuantity();
unsigned AlignI = std::min(AlignR, ComplexAlign);
- llvm::Value *Real=0, *Imag=0;
+ llvm::Value *Real=nullptr, *Imag=nullptr;
if (!IgnoreReal || isVolatile) {
llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0,
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 82382dd..b2f08c3 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -530,7 +530,7 @@
ConstStructBuilder Builder(CGM, CGF);
if (!Builder.Build(ILE))
- return 0;
+ return nullptr;
return Builder.Finalize(ILE->getType());
}
@@ -572,7 +572,7 @@
//===--------------------------------------------------------------------===//
llvm::Constant *VisitStmt(Stmt *S) {
- return 0;
+ return nullptr;
}
llvm::Constant *VisitParenExpr(ParenExpr *PE) {
@@ -599,7 +599,7 @@
llvm::Constant *VisitCastExpr(CastExpr* E) {
Expr *subExpr = E->getSubExpr();
llvm::Constant *C = CGM.EmitConstantExpr(subExpr, subExpr->getType(), CGF);
- if (!C) return 0;
+ if (!C) return nullptr;
llvm::Type *destType = ConvertType(E->getType());
@@ -660,7 +660,7 @@
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
- return 0;
+ return nullptr;
// These don't need to be handled here because Evaluate knows how to
// evaluate them in the cases where they can be folded.
@@ -701,7 +701,7 @@
case CK_FloatingToBoolean:
case CK_FloatingCast:
case CK_ZeroToOCLEvent:
- return 0;
+ return nullptr;
}
llvm_unreachable("Invalid CastKind");
}
@@ -743,7 +743,7 @@
Expr *Init = ILE->getInit(i);
llvm::Constant *C = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
if (!C)
- return 0;
+ return nullptr;
RewriteType |= (C->getType() != ElemTy);
Elts.push_back(C);
}
@@ -756,7 +756,7 @@
else
fillC = llvm::Constant::getNullValue(ElemTy);
if (!fillC)
- return 0;
+ return nullptr;
RewriteType |= (fillC->getType() != ElemTy);
Elts.resize(NumElements, fillC);
@@ -789,12 +789,12 @@
if (ILE->getType()->isRecordType())
return EmitRecordInitialization(ILE);
- return 0;
+ return nullptr;
}
llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E) {
if (!E->getConstructor()->isTrivial())
- return 0;
+ return nullptr;
QualType Ty = E->getType();
@@ -806,8 +806,8 @@
// If the class doesn't have a trivial destructor, we can't emit it as a
// constant expr.
if (!RD->hasTrivialDestructor())
- return 0;
-
+ return nullptr;
+
// Only copy and default constructors can be trivial.
@@ -836,7 +836,10 @@
// as an inline array.
std::string Str;
CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str);
- const ConstantArrayType *CAT = cast<ConstantArrayType>(E->getType());
+ QualType T = E->getType();
+ if (T->getTypeClass() == Type::TypeOfExpr)
+ T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
+ const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
// Resize the string to the right size, adding zeros at the end, or
// truncating as needed.
@@ -869,7 +872,7 @@
return CGM.getStaticLocalDeclAddress(VD);
}
}
- return 0;
+ return nullptr;
}
Expr *E = const_cast<Expr*>(LVBase.get<const Expr*>());
@@ -886,7 +889,7 @@
C = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
E->getType().isConstant(CGM.getContext()),
llvm::GlobalValue::InternalLinkage,
- C, ".compoundliteral", 0,
+ C, ".compoundliteral", nullptr,
llvm::GlobalVariable::NotThreadLocal,
CGM.getContext().getTargetAddressSpace(E->getType()));
return C;
@@ -967,7 +970,7 @@
}
}
- return 0;
+ return nullptr;
}
};
@@ -1001,7 +1004,7 @@
// interprets that as the (pointer) value of the reference, rather than the
// desired value of the referee.
if (D.getType()->isReferenceType())
- return 0;
+ return nullptr;
const Expr *E = D.getInit();
assert(E && "No initializer to emit");
@@ -1026,7 +1029,7 @@
else
Success = E->EvaluateAsRValue(Result, Context);
- llvm::Constant *C = 0;
+ llvm::Constant *C = nullptr;
if (Success && !Result.HasSideEffects)
C = EmitConstantValue(Result.Val, DestType, CGF);
else
@@ -1063,7 +1066,9 @@
// Apply offset if necessary.
if (!Offset->isNullValue()) {
- llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
+ 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);
C = llvm::ConstantExpr::getPointerCast(Casted, C->getType());
}
@@ -1169,13 +1174,13 @@
Elts.reserve(NumElements);
// Emit array filler, if there is one.
- llvm::Constant *Filler = 0;
+ llvm::Constant *Filler = nullptr;
if (Value.hasArrayFiller())
Filler = EmitConstantValueForMemory(Value.getArrayFiller(),
CAT->getElementType(), CGF);
// Emit initializer elements.
- llvm::Type *CommonElementType = 0;
+ llvm::Type *CommonElementType = nullptr;
for (unsigned I = 0; I < NumElements; ++I) {
llvm::Constant *C = Filler;
if (I < NumInitElts)
@@ -1186,7 +1191,7 @@
if (I == 0)
CommonElementType = C->getType();
else if (C->getType() != CommonElementType)
- CommonElementType = 0;
+ CommonElementType = nullptr;
Elts.push_back(C);
}
@@ -1225,7 +1230,7 @@
llvm::Constant *
CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
assert(E->isFileScope() && "not a file-scope compound literal expr");
- return ConstExprEmitter(*this, 0).EmitLValue(E);
+ return ConstExprEmitter(*this, nullptr).EmitLValue(E);
}
llvm::Constant *
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 5f932b0..1ee3ce8 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -365,7 +365,7 @@
}
Value *VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
CGF.EmitCXXDeleteExpr(E);
- return 0;
+ return nullptr;
}
Value *VisitTypeTraitExpr(const TypeTraitExpr *E) {
@@ -387,7 +387,7 @@
// effect is the evaluation of the postfix-expression before the dot or
// arrow.
CGF.EmitScalarExpr(E->getBase());
- return 0;
+ return nullptr;
}
Value *VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
@@ -396,7 +396,7 @@
Value *VisitCXXThrowExpr(const CXXThrowExpr *E) {
CGF.EmitCXXThrowExpr(E);
- return 0;
+ return nullptr;
}
Value *VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
@@ -559,7 +559,7 @@
llvm::Type *SrcTy = Src->getType();
- llvm::Value *Check = 0;
+ llvm::Value *Check = nullptr;
if (llvm::IntegerType *IntTy = dyn_cast<llvm::IntegerType>(SrcTy)) {
// Integer to floating-point. This can fail for unsigned short -> __half
// or unsigned __int128 -> float.
@@ -693,7 +693,7 @@
DstType = CGF.getContext().getCanonicalType(DstType);
if (SrcType == DstType) return Src;
- if (DstType->isVoidType()) return 0;
+ if (DstType->isVoidType()) return nullptr;
llvm::Value *OrigSrc = Src;
QualType OrigSrcType = SrcType;
@@ -758,7 +758,7 @@
return Builder.CreateBitCast(Src, DstTy, "conv");
// Finally, we have the arithmetic types: real int/float.
- Value *Res = NULL;
+ Value *Res = nullptr;
llvm::Type *ResTy = DstTy;
// An overflowing conversion has undefined behavior if either the source type
@@ -887,7 +887,7 @@
Value *ScalarExprEmitter::VisitExpr(Expr *E) {
CGF.ErrorUnsupported(E, "scalar expression");
if (E->getType()->isVoidType())
- return 0;
+ return nullptr;
return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
}
@@ -1013,7 +1013,7 @@
}
// We have the arithmetic types: real int/float.
- Value *Res = NULL;
+ Value *Res = nullptr;
if (isa<llvm::IntegerType>(SrcEltTy)) {
bool InputSigned = SrcEltType->isSignedIntegerOrEnumerationType();
@@ -1133,7 +1133,7 @@
if (EI->getVectorOperandType()->getNumElements() == ResElts) {
llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand());
- Value *LHS = 0, *RHS = 0;
+ Value *LHS = nullptr, *RHS = nullptr;
if (CurIdx == 0) {
// insert into undef -> shuffle (src, undef)
Args.push_back(C);
@@ -1450,7 +1450,7 @@
case CK_ToVoid: {
CGF.EmitIgnoredExpr(E);
- return 0;
+ return nullptr;
}
case CK_VectorSplat: {
llvm::Type *DstTy = ConvertType(DestTy);
@@ -1460,7 +1460,7 @@
// Splat the element across to all elements
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
- return Builder.CreateVectorSplat(NumElements, Elt, "splat");;
+ return Builder.CreateVectorSplat(NumElements, Elt, "splat");
}
case CK_IntegralCast:
@@ -1507,7 +1507,7 @@
llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(),
!E->getType()->isVoidType());
if (!RetAlloca)
- return 0;
+ return nullptr;
return CGF.EmitLoadOfScalar(CGF.MakeAddrLValue(RetAlloca, E->getType()),
E->getExprLoc());
}
@@ -1545,7 +1545,7 @@
bool isInc, bool isPre) {
QualType type = E->getSubExpr()->getType();
- llvm::PHINode *atomicPHI = 0;
+ llvm::PHINode *atomicPHI = nullptr;
llvm::Value *value;
llvm::Value *input;
@@ -1819,7 +1819,7 @@
QualType CurrentType = E->getTypeSourceInfo()->getType();
for (unsigned i = 0; i != n; ++i) {
OffsetOfExpr::OffsetOfNode ON = E->getComponent(i);
- llvm::Value *Offset = 0;
+ llvm::Value *Offset = nullptr;
switch (ON.getKind()) {
case OffsetOfExpr::OffsetOfNode::Array: {
// Compute the index
@@ -2009,7 +2009,7 @@
// Load/convert the LHS.
LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
- llvm::PHINode *atomicPHI = 0;
+ llvm::PHINode *atomicPHI = nullptr;
if (const AtomicType *atomicTy = LHSTy->getAs<AtomicType>()) {
QualType type = atomicTy->getValueType();
if (!type->isBooleanType() && type->isIntegerType() &&
@@ -2108,7 +2108,7 @@
// If the result is clearly ignored, return now.
if (Ignore)
- return 0;
+ return nullptr;
// The result of an assignment in C is the assigned r-value.
if (!CGF.getLangOpts().CPlusPlus)
@@ -2124,7 +2124,7 @@
void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
- llvm::Value *Cond = 0;
+ llvm::Value *Cond = nullptr;
if (CGF.SanOpts->IntegerDivideByZero)
Cond = Builder.CreateICmpNE(Ops.RHS, Zero);
@@ -2428,12 +2428,12 @@
// Check whether this op is marked as fusable.
if (!op.FPContractable)
- return 0;
+ return nullptr;
// Check whether -ffp-contract=on. (If -ffp-contract=off/fast, fusing is
// either disabled, or handled entirely by the LLVM backend).
if (CGF.CGM.getCodeGenOpts().getFPContractMode() != CodeGenOptions::FPC_On)
- return 0;
+ return nullptr;
// We have a potentially fusable op. Look for a mul on one of the operands.
if (llvm::BinaryOperator* LHSBinOp = dyn_cast<llvm::BinaryOperator>(op.LHS)) {
@@ -2451,7 +2451,7 @@
}
}
- return 0;
+ return nullptr;
}
Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
@@ -2533,7 +2533,7 @@
const BinaryOperator *expr = cast<BinaryOperator>(op.E);
QualType elementType = expr->getLHS()->getType()->getPointeeType();
- llvm::Value *divisor = 0;
+ llvm::Value *divisor = nullptr;
// For a variable-length array, this is going to be non-constant.
if (const VariableArrayType *vla
@@ -2861,7 +2861,7 @@
// If the result is clearly ignored, return now.
if (Ignore)
- return 0;
+ return nullptr;
// The result of an assignment in C is the assigned r-value.
if (!CGF.getLangOpts().CPlusPlus)
@@ -3152,7 +3152,7 @@
if (!LHS) {
// If the conditional has void type, make sure we return a null Value*.
assert(!RHS && "LHS and RHS types must match");
- return 0;
+ return nullptr;
}
return Builder.CreateSelect(CondV, LHS, RHS, "cond");
}
@@ -3199,6 +3199,10 @@
}
Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
+ QualType Ty = VE->getType();
+ if (Ty->isVariablyModifiedType())
+ CGF.EmitVariablyModifiedType(Ty);
+
llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr());
llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType());
@@ -3345,7 +3349,7 @@
LValue CodeGenFunction::EmitCompoundAssignmentLValue(
const CompoundAssignOperator *E) {
ScalarExprEmitter Scalar(*this);
- Value *Result = 0;
+ Value *Result = nullptr;
switch (E->getOpcode()) {
#define COMPOUND_OP(Op) \
case BO_##Op##Assign: \
diff --git a/lib/CodeGen/CGLoopInfo.cpp b/lib/CodeGen/CGLoopInfo.cpp
new file mode 100644
index 0000000..7b154b2
--- /dev/null
+++ b/lib/CodeGen/CGLoopInfo.cpp
@@ -0,0 +1,112 @@
+//===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGLoopInfo.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Metadata.h"
+using namespace clang;
+using namespace CodeGen;
+using namespace llvm;
+
+static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
+
+ if (!Attrs.IsParallel && Attrs.VectorizerWidth == 0 &&
+ Attrs.VectorizerUnroll == 0 &&
+ Attrs.VectorizerEnable == LoopAttributes::VecUnspecified)
+ return nullptr;
+
+ SmallVector<Value *, 4> Args;
+ // Reserve operand 0 for loop id self reference.
+ MDNode *TempNode = MDNode::getTemporary(Ctx, None);
+ Args.push_back(TempNode);
+
+ // Setting vectorizer.width
+ if (Attrs.VectorizerWidth > 0) {
+ Value *Vals[] = { MDString::get(Ctx, "llvm.vectorizer.width"),
+ ConstantInt::get(Type::getInt32Ty(Ctx),
+ Attrs.VectorizerWidth) };
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
+ // Setting vectorizer.unroll
+ if (Attrs.VectorizerUnroll > 0) {
+ Value *Vals[] = { MDString::get(Ctx, "llvm.vectorizer.unroll"),
+ ConstantInt::get(Type::getInt32Ty(Ctx),
+ Attrs.VectorizerUnroll) };
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
+ // Setting vectorizer.enable
+ if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) {
+ Value *Vals[] = { MDString::get(Ctx, "llvm.vectorizer.enable"),
+ ConstantInt::get(Type::getInt1Ty(Ctx),
+ (Attrs.VectorizerEnable ==
+ LoopAttributes::VecEnable)) };
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
+ MDNode *LoopID = MDNode::get(Ctx, Args);
+ assert(LoopID->use_empty() && "LoopID should not be used");
+
+ // Set the first operand to itself.
+ LoopID->replaceOperandWith(0, LoopID);
+ MDNode::deleteTemporary(TempNode);
+ return LoopID;
+}
+
+LoopAttributes::LoopAttributes(bool IsParallel)
+ : IsParallel(IsParallel), VectorizerEnable(LoopAttributes::VecUnspecified),
+ VectorizerWidth(0), VectorizerUnroll(0) {}
+
+void LoopAttributes::clear() {
+ IsParallel = false;
+ VectorizerWidth = 0;
+ VectorizerUnroll = 0;
+ VectorizerEnable = LoopAttributes::VecUnspecified;
+}
+
+LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
+ : LoopID(nullptr), Header(Header), Attrs(Attrs) {
+ LoopID = createMetadata(Header->getContext(), Attrs);
+}
+
+void LoopInfoStack::push(BasicBlock *Header) {
+ Active.push_back(LoopInfo(Header, StagedAttrs));
+ // Clear the attributes so nested loops do not inherit them.
+ StagedAttrs.clear();
+}
+
+void LoopInfoStack::pop() {
+ assert(!Active.empty() && "No active loops to pop");
+ Active.pop_back();
+}
+
+void LoopInfoStack::InsertHelper(Instruction *I) const {
+ if (!hasInfo())
+ return;
+
+ const LoopInfo &L = getInfo();
+ if (!L.getLoopID())
+ return;
+
+ if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
+ for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
+ if (TI->getSuccessor(i) == L.getHeader()) {
+ TI->setMetadata("llvm.loop", L.getLoopID());
+ break;
+ }
+ return;
+ }
+
+ if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
+ I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
+}
diff --git a/lib/CodeGen/CGLoopInfo.h b/lib/CodeGen/CGLoopInfo.h
new file mode 100644
index 0000000..f4a8dca
--- /dev/null
+++ b/lib/CodeGen/CGLoopInfo.h
@@ -0,0 +1,136 @@
+//===---- CGLoopInfo.h - LLVM CodeGen for loop metadata -*- C++ -*---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal state used for llvm translation for loop statement
+// metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGLOOPINFO_H
+#define CLANG_CODEGEN_CGLOOPINFO_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+class BasicBlock;
+class Instruction;
+class MDNode;
+} // end namespace llvm
+
+namespace clang {
+namespace CodeGen {
+
+/// \brief Attributes that may be specified on loops.
+struct LoopAttributes {
+ explicit LoopAttributes(bool IsParallel = false);
+ void clear();
+
+ /// \brief Generate llvm.loop.parallel metadata for loads and stores.
+ bool IsParallel;
+
+ /// \brief Values of llvm.vectorizer.enable metadata.
+ enum LVEnableState { VecUnspecified, VecEnable, VecDisable };
+
+ /// \brief llvm.vectorizer.enable
+ LVEnableState VectorizerEnable;
+
+ /// \brief llvm.vectorizer.width
+ unsigned VectorizerWidth;
+
+ /// \brief llvm.vectorizer.unroll
+ unsigned VectorizerUnroll;
+};
+
+/// \brief Information used when generating a structured loop.
+class LoopInfo {
+public:
+ /// \brief Construct a new LoopInfo for the loop with entry Header.
+ LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs);
+
+ /// \brief Get the loop id metadata for this loop.
+ llvm::MDNode *getLoopID() const { return LoopID; }
+
+ /// \brief Get the header block of this loop.
+ llvm::BasicBlock *getHeader() const { return Header; }
+
+ /// \brief Get the set of attributes active for this loop.
+ const LoopAttributes &getAttributes() const { return Attrs; }
+
+private:
+ /// \brief Loop ID metadata.
+ llvm::MDNode *LoopID;
+ /// \brief Header block of this loop.
+ llvm::BasicBlock *Header;
+ /// \brief The attributes for this loop.
+ LoopAttributes Attrs;
+};
+
+/// \brief A stack of loop information corresponding to loop nesting levels.
+/// This stack can be used to prepare attributes which are applied when a loop
+/// is emitted.
+class LoopInfoStack {
+ LoopInfoStack(const LoopInfoStack &) LLVM_DELETED_FUNCTION;
+ void operator=(const LoopInfoStack &) LLVM_DELETED_FUNCTION;
+
+public:
+ LoopInfoStack() {}
+
+ /// \brief Begin a new structured loop. The set of staged attributes will be
+ /// applied to the loop and then cleared.
+ void push(llvm::BasicBlock *Header);
+
+ /// \brief End the current loop.
+ void pop();
+
+ /// \brief Return the top loop id metadata.
+ llvm::MDNode *getCurLoopID() const { return getInfo().getLoopID(); }
+
+ /// \brief Return true if the top loop is parallel.
+ bool getCurLoopParallel() const {
+ return hasInfo() ? getInfo().getAttributes().IsParallel : false;
+ }
+
+ /// \brief Function called by the CodeGenFunction when an instruction is
+ /// created.
+ void InsertHelper(llvm::Instruction *I) const;
+
+ /// \brief Set the next pushed loop as parallel.
+ void setParallel(bool Enable = true) { StagedAttrs.IsParallel = Enable; }
+
+ /// \brief Set the next pushed loop 'vectorizer.enable'
+ void setVectorizerEnable(bool Enable = true) {
+ StagedAttrs.VectorizerEnable =
+ Enable ? LoopAttributes::VecEnable : LoopAttributes::VecDisable;
+ }
+
+ /// \brief Set the vectorizer width for the next loop pushed.
+ void setVectorizerWidth(unsigned W) { StagedAttrs.VectorizerWidth = W; }
+
+ /// \brief Set the vectorizer unroll for the next loop pushed.
+ void setVectorizerUnroll(unsigned U) { StagedAttrs.VectorizerUnroll = U; }
+
+private:
+ /// \brief Returns true if there is LoopInfo on the stack.
+ bool hasInfo() const { return !Active.empty(); }
+ /// \brief Return the LoopInfo for the current loop. HasInfo should be called
+ /// first to ensure LoopInfo is present.
+ const LoopInfo &getInfo() const { return Active.back(); }
+ /// \brief The set of attributes that will be applied to the next pushed loop.
+ LoopAttributes StagedAttrs;
+ /// \brief Stack of active loops.
+ llvm::SmallVector<LoopInfo, 4> Active;
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif // CLANG_CODEGEN_CGLOOPINFO_H
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index f78bb0b..8c54bba 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -90,7 +90,7 @@
llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
const ObjCMethodDecl *MethodWithObjects) {
ASTContext &Context = CGM.getContext();
- const ObjCDictionaryLiteral *DLE = 0;
+ const ObjCDictionaryLiteral *DLE = nullptr;
const ObjCArrayLiteral *ALE = dyn_cast<ObjCArrayLiteral>(E);
if (!ALE)
DLE = cast<ObjCDictionaryLiteral>(E);
@@ -106,8 +106,8 @@
ArrayType::Normal, /*IndexTypeQuals=*/0);
// Allocate the temporary array(s).
- llvm::Value *Objects = CreateMemTemp(ElementArrayType, "objects");
- llvm::Value *Keys = 0;
+ llvm::Value *Objects = CreateMemTemp(ElementArrayType, "objects");
+ llvm::Value *Keys = nullptr;
if (DLE)
Keys = CreateMemTemp(ElementArrayType, "keys");
@@ -314,10 +314,10 @@
CGObjCRuntime &Runtime = CGM.getObjCRuntime();
bool isSuperMessage = false;
bool isClassMessage = false;
- ObjCInterfaceDecl *OID = 0;
+ ObjCInterfaceDecl *OID = nullptr;
// Find the receiver
QualType ReceiverType;
- llvm::Value *Receiver = 0;
+ llvm::Value *Receiver = nullptr;
switch (E->getReceiverKind()) {
case ObjCMessageExpr::Instance:
ReceiverType = E->getInstanceReceiver()->getType();
@@ -466,7 +466,7 @@
FunctionArgList args;
// Check if we should generate debug info for this method.
if (OMD->hasAttr<NoDebugAttr>())
- DebugInfo = NULL; // disable debug info indefinitely for this function
+ DebugInfo = nullptr; // disable debug info indefinitely for this function
llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD);
@@ -481,7 +481,8 @@
CurGD = OMD;
- StartFunction(OMD, OMD->getReturnType(), Fn, FI, args, StartLoc);
+ StartFunction(OMD, OMD->getReturnType(), Fn, FI, args,
+ OMD->getLocation(), StartLoc);
// In ARC, certain methods get an extra cleanup.
if (CGM.getLangOpts().ObjCAutoRefCount &&
@@ -819,7 +820,7 @@
if (!hasTrivialGetExpr(propImpl)) {
if (!AtomicHelperFn) {
ReturnStmt ret(SourceLocation(), propImpl->getGetterCXXConstructor(),
- /*nrvo*/ 0);
+ /*nrvo*/ nullptr);
EmitReturnStmt(ret);
}
else {
@@ -900,7 +901,7 @@
RValue RV = EmitCall(getTypes().arrangeFreeFunctionCall(propType, args,
FunctionType::ExtInfo(),
RequiredArgs::All),
- getPropertyFn, ReturnValueSlot(), args, 0,
+ getPropertyFn, ReturnValueSlot(), args, nullptr,
&CallInstruction);
if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction))
call->setTailCall();
@@ -1145,9 +1146,9 @@
case PropertyImplStrategy::GetSetProperty:
case PropertyImplStrategy::SetPropertyAndExpressionGet: {
-
- llvm::Value *setOptimizedPropertyFn = 0;
- llvm::Value *setPropertyFn = 0;
+
+ llvm::Value *setOptimizedPropertyFn = nullptr;
+ llvm::Value *setPropertyFn = nullptr;
if (UseOptimizedSetter(CGM)) {
// 10.8 and iOS 6.0 code and GC is off
setOptimizedPropertyFn =
@@ -1330,7 +1331,7 @@
QualType::DestructionKind dtorKind = type.isDestructedType();
if (!dtorKind) continue;
- CodeGenFunction::Destroyer *destroyer = 0;
+ CodeGenFunction::Destroyer *destroyer = nullptr;
// Use a call to objc_storeStrong to destroy strong ivars, for the
// general benefit of the tools.
@@ -1870,7 +1871,7 @@
};
llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args);
- if (ignored) return 0;
+ if (ignored) return nullptr;
return CGF.Builder.CreateBitCast(result, origType);
}
@@ -2068,7 +2069,7 @@
};
EmitNounwindRuntimeCall(fn, args);
- if (ignored) return 0;
+ if (ignored) return nullptr;
return value;
}
@@ -2563,7 +2564,7 @@
// The desired result type, if it differs from the type of the
// ultimate opaque expression.
- llvm::Type *resultType = 0;
+ llvm::Type *resultType = nullptr;
while (true) {
e = e->IgnoreParens();
@@ -2869,16 +2870,16 @@
const ObjCPropertyImplDecl *PID) {
if (!getLangOpts().CPlusPlus ||
!getLangOpts().ObjCRuntime.hasAtomicCopyHelper())
- return 0;
+ return nullptr;
QualType Ty = PID->getPropertyIvarDecl()->getType();
if (!Ty->isRecordType())
- return 0;
+ return nullptr;
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
if ((!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic)))
- return 0;
- llvm::Constant * HelperFn = 0;
+ return nullptr;
+ llvm::Constant *HelperFn = nullptr;
if (hasTrivialSetExpr(PID))
- return 0;
+ return nullptr;
assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null");
if ((HelperFn = CGM.getAtomicSetterHelperFnMap(Ty)))
return HelperFn;
@@ -2889,20 +2890,20 @@
FunctionDecl *FD = FunctionDecl::Create(C,
C.getTranslationUnitDecl(),
SourceLocation(),
- SourceLocation(), II, C.VoidTy, 0,
- SC_Static,
+ SourceLocation(), II, C.VoidTy,
+ nullptr, SC_Static,
false,
false);
-
+
QualType DestTy = C.getPointerType(Ty);
QualType SrcTy = Ty;
SrcTy.addConst();
SrcTy = C.getPointerType(SrcTy);
FunctionArgList args;
- ImplicitParamDecl dstDecl(FD, SourceLocation(), 0, DestTy);
+ ImplicitParamDecl dstDecl(getContext(), FD, SourceLocation(), nullptr,DestTy);
args.push_back(&dstDecl);
- ImplicitParamDecl srcDecl(FD, SourceLocation(), 0, SrcTy);
+ ImplicitParamDecl srcDecl(getContext(), FD, SourceLocation(), nullptr, SrcTy);
args.push_back(&srcDecl);
const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
@@ -2915,7 +2916,7 @@
"__assign_helper_atomic_property_",
&CGM.getModule());
- StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
+ StartFunction(FD, C.VoidTy, Fn, FI, args);
DeclRefExpr DstExpr(&dstDecl, false, DestTy,
VK_RValue, SourceLocation());
@@ -2946,17 +2947,17 @@
const ObjCPropertyImplDecl *PID) {
if (!getLangOpts().CPlusPlus ||
!getLangOpts().ObjCRuntime.hasAtomicCopyHelper())
- return 0;
+ return nullptr;
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
QualType Ty = PD->getType();
if (!Ty->isRecordType())
- return 0;
+ return nullptr;
if ((!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic)))
- return 0;
- llvm::Constant * HelperFn = 0;
-
+ return nullptr;
+ llvm::Constant *HelperFn = nullptr;
+
if (hasTrivialGetExpr(PID))
- return 0;
+ return nullptr;
assert(PID->getGetterCXXConstructor() && "getGetterCXXConstructor - null");
if ((HelperFn = CGM.getAtomicGetterHelperFnMap(Ty)))
return HelperFn;
@@ -2968,20 +2969,20 @@
FunctionDecl *FD = FunctionDecl::Create(C,
C.getTranslationUnitDecl(),
SourceLocation(),
- SourceLocation(), II, C.VoidTy, 0,
- SC_Static,
+ SourceLocation(), II, C.VoidTy,
+ nullptr, SC_Static,
false,
false);
-
+
QualType DestTy = C.getPointerType(Ty);
QualType SrcTy = Ty;
SrcTy.addConst();
SrcTy = C.getPointerType(SrcTy);
FunctionArgList args;
- ImplicitParamDecl dstDecl(FD, SourceLocation(), 0, DestTy);
+ ImplicitParamDecl dstDecl(getContext(), FD, SourceLocation(), nullptr,DestTy);
args.push_back(&dstDecl);
- ImplicitParamDecl srcDecl(FD, SourceLocation(), 0, SrcTy);
+ ImplicitParamDecl srcDecl(getContext(), FD, SourceLocation(), nullptr, SrcTy);
args.push_back(&srcDecl);
const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
@@ -2993,7 +2994,7 @@
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__copy_helper_atomic_property_", &CGM.getModule());
- StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
+ StartFunction(FD, C.VoidTy, Fn, FI, args);
DeclRefExpr SrcExpr(&srcDecl, false, SrcTy,
VK_RValue, SourceLocation());
@@ -3058,11 +3059,11 @@
RValue Result;
Result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(),
Ty, CopySelector,
- Val, CallArgList(), 0, 0);
+ Val, CallArgList(), nullptr, nullptr);
Val = Result.getScalarVal();
Result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(),
Ty, AutoreleaseSelector,
- Val, CallArgList(), 0, 0);
+ Val, CallArgList(), nullptr, nullptr);
Val = Result.getScalarVal();
return Val;
}
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 2689d7b..3ca0378 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -53,7 +53,8 @@
/// Constructor leaves this class uninitialized, because it is intended to
/// be used as a field in another class and not all of the types that are
/// used as arguments will necessarily be available at construction time.
- LazyRuntimeFunction() : CGM(0), FunctionName(0), Function(0) {}
+ LazyRuntimeFunction()
+ : CGM(nullptr), FunctionName(nullptr), Function(nullptr) {}
/// Initialises the lazy function with the name, return type, and the types
/// of the arguments.
@@ -62,7 +63,7 @@
llvm::Type *RetTy, ...) {
CGM =Mod;
FunctionName = name;
- Function = 0;
+ Function = nullptr;
ArgTys.clear();
va_list Args;
va_start(Args, RetTy);
@@ -76,7 +77,7 @@
/// LLVM constant.
operator llvm::Constant*() {
if (!Function) {
- if (0 == FunctionName) return 0;
+ if (!FunctionName) return nullptr;
// We put the return type on the end of the vector, so pop it back off
llvm::Type *RetTy = ArgTys.back();
ArgTys.pop_back();
@@ -564,7 +565,7 @@
llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
bool Weak = false) override {
- return 0;
+ return nullptr;
}
};
/// Class representing the legacy GCC Objective-C ABI. This is the default when
@@ -605,10 +606,11 @@
public:
CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) {
// IMP objc_msg_lookup(id, SEL);
- MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, NULL);
+ MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy,
+ nullptr);
// IMP objc_msg_lookup_super(struct objc_super*, SEL);
MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
- PtrToObjCSuperTy, SelectorTy, NULL);
+ PtrToObjCSuperTy, SelectorTy, nullptr);
}
};
/// Class used when targeting the new GNUstep runtime ABI.
@@ -696,51 +698,51 @@
const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
llvm::StructType *SlotStructTy = llvm::StructType::get(PtrTy,
- PtrTy, PtrTy, IntTy, IMPTy, NULL);
+ PtrTy, PtrTy, IntTy, IMPTy, nullptr);
SlotTy = llvm::PointerType::getUnqual(SlotStructTy);
// Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy,
- SelectorTy, IdTy, NULL);
+ SelectorTy, IdTy, nullptr);
// Slot_t objc_msg_lookup_super(struct objc_super*, SEL);
SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
- PtrToObjCSuperTy, SelectorTy, NULL);
+ PtrToObjCSuperTy, SelectorTy, nullptr);
// If we're in ObjC++ mode, then we want to make
if (CGM.getLangOpts().CPlusPlus) {
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
// void *__cxa_begin_catch(void *e)
- EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy, NULL);
+ EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy, nullptr);
// void __cxa_end_catch(void)
- ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy, NULL);
+ ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy, nullptr);
// void _Unwind_Resume_or_Rethrow(void*)
ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy,
- PtrTy, NULL);
+ PtrTy, nullptr);
} else if (R.getVersion() >= VersionTuple(1, 7)) {
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
// id objc_begin_catch(void *e)
- EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy, NULL);
+ EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy, nullptr);
// void objc_end_catch(void)
- ExitCatchFn.init(&CGM, "objc_end_catch", VoidTy, NULL);
+ ExitCatchFn.init(&CGM, "objc_end_catch", VoidTy, nullptr);
// void _Unwind_Resume_or_Rethrow(void*)
ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy,
- PtrTy, NULL);
+ PtrTy, nullptr);
}
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
SetPropertyAtomic.init(&CGM, "objc_setProperty_atomic", VoidTy, IdTy,
- SelectorTy, IdTy, PtrDiffTy, NULL);
+ SelectorTy, IdTy, PtrDiffTy, nullptr);
SetPropertyAtomicCopy.init(&CGM, "objc_setProperty_atomic_copy", VoidTy,
- IdTy, SelectorTy, IdTy, PtrDiffTy, NULL);
+ IdTy, SelectorTy, IdTy, PtrDiffTy, nullptr);
SetPropertyNonAtomic.init(&CGM, "objc_setProperty_nonatomic", VoidTy,
- IdTy, SelectorTy, IdTy, PtrDiffTy, NULL);
+ IdTy, SelectorTy, IdTy, PtrDiffTy, nullptr);
SetPropertyNonAtomicCopy.init(&CGM, "objc_setProperty_nonatomic_copy",
- VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy, NULL);
+ VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy, nullptr);
// void objc_setCppObjectAtomic(void *dest, const void *src, void
// *helper);
CxxAtomicObjectSetFn.init(&CGM, "objc_setCppObjectAtomic", VoidTy, PtrTy,
- PtrTy, PtrTy, NULL);
+ PtrTy, PtrTy, nullptr);
// void objc_getCppObjectAtomic(void *dest, const void *src, void
// *helper);
CxxAtomicObjectGetFn.init(&CGM, "objc_getCppObjectAtomic", VoidTy, PtrTy,
- PtrTy, PtrTy, NULL);
+ PtrTy, PtrTy, nullptr);
}
llvm::Constant *GetCppAtomicObjectGetFunction() override {
// The optimised functions were added in version 1.7 of the GNUstep
@@ -834,7 +836,7 @@
if (!ClassSymbol)
ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
llvm::GlobalValue::ExternalLinkage,
- 0, SymbolName);
+ nullptr, SymbolName);
return ClassSymbol;
}
@@ -842,14 +844,14 @@
public:
CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
// IMP objc_msg_lookup(id, SEL);
- MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, NULL);
+ MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, nullptr);
MsgLookupFnSRet.init(&CGM, "objc_msg_lookup_stret", IMPTy, IdTy,
- SelectorTy, NULL);
+ SelectorTy, nullptr);
// IMP objc_msg_lookup_super(struct objc_super*, SEL);
MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
- PtrToObjCSuperTy, SelectorTy, NULL);
+ PtrToObjCSuperTy, SelectorTy, nullptr);
MsgLookupSuperFnSRet.init(&CGM, "objc_msg_lookup_super_stret", IMPTy,
- PtrToObjCSuperTy, SelectorTy, NULL);
+ PtrToObjCSuperTy, SelectorTy, nullptr);
}
};
} // end anonymous namespace
@@ -867,7 +869,8 @@
llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
if (!ClassSymbol) {
ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
- llvm::GlobalValue::ExternalLinkage, 0, symbolName);
+ llvm::GlobalValue::ExternalLinkage,
+ nullptr, symbolName);
}
new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true,
llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
@@ -884,10 +887,11 @@
}
CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
- unsigned protocolClassVersion)
+ unsigned protocolClassVersion)
: CGObjCRuntime(cgm), TheModule(CGM.getModule()),
- VMContext(cgm.getLLVMContext()), ClassPtrAlias(0), MetaClassPtrAlias(0),
- RuntimeVersion(runtimeABIVersion), ProtocolVersion(protocolClassVersion) {
+ VMContext(cgm.getLLVMContext()), ClassPtrAlias(nullptr),
+ MetaClassPtrAlias(nullptr), RuntimeVersion(runtimeABIVersion),
+ ProtocolVersion(protocolClassVersion) {
msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
@@ -937,35 +941,35 @@
}
PtrToIdTy = llvm::PointerType::getUnqual(IdTy);
- ObjCSuperTy = llvm::StructType::get(IdTy, IdTy, NULL);
+ ObjCSuperTy = llvm::StructType::get(IdTy, IdTy, nullptr);
PtrToObjCSuperTy = llvm::PointerType::getUnqual(ObjCSuperTy);
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
// void objc_exception_throw(id);
- ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy, NULL);
- ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy, NULL);
+ ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy, nullptr);
+ ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy, nullptr);
// int objc_sync_enter(id);
- SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy, NULL);
+ SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy, nullptr);
// int objc_sync_exit(id);
- SyncExitFn.init(&CGM, "objc_sync_exit", IntTy, IdTy, NULL);
+ SyncExitFn.init(&CGM, "objc_sync_exit", IntTy, IdTy, nullptr);
// void objc_enumerationMutation (id)
EnumerationMutationFn.init(&CGM, "objc_enumerationMutation", VoidTy,
- IdTy, NULL);
+ IdTy, nullptr);
// id objc_getProperty(id, SEL, ptrdiff_t, BOOL)
GetPropertyFn.init(&CGM, "objc_getProperty", IdTy, IdTy, SelectorTy,
- PtrDiffTy, BoolTy, NULL);
+ PtrDiffTy, BoolTy, nullptr);
// void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, BOOL)
SetPropertyFn.init(&CGM, "objc_setProperty", VoidTy, IdTy, SelectorTy,
- PtrDiffTy, IdTy, BoolTy, BoolTy, NULL);
+ PtrDiffTy, IdTy, BoolTy, BoolTy, nullptr);
// void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL)
GetStructPropertyFn.init(&CGM, "objc_getPropertyStruct", VoidTy, PtrTy, PtrTy,
- PtrDiffTy, BoolTy, BoolTy, NULL);
+ PtrDiffTy, BoolTy, BoolTy, nullptr);
// void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL)
SetStructPropertyFn.init(&CGM, "objc_setPropertyStruct", VoidTy, PtrTy, PtrTy,
- PtrDiffTy, BoolTy, BoolTy, NULL);
+ PtrDiffTy, BoolTy, BoolTy, nullptr);
// IMP type
llvm::Type *IMPArgs[] = { IdTy, SelectorTy };
@@ -990,20 +994,20 @@
// id objc_assign_ivar(id, id, ptrdiff_t);
IvarAssignFn.init(&CGM, "objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy,
- NULL);
+ nullptr);
// id objc_assign_strongCast (id, id*)
StrongCastAssignFn.init(&CGM, "objc_assign_strongCast", IdTy, IdTy,
- PtrToIdTy, NULL);
+ PtrToIdTy, nullptr);
// id objc_assign_global(id, id*);
GlobalAssignFn.init(&CGM, "objc_assign_global", IdTy, IdTy, PtrToIdTy,
- NULL);
+ nullptr);
// id objc_assign_weak(id, id*);
- WeakAssignFn.init(&CGM, "objc_assign_weak", IdTy, IdTy, PtrToIdTy, NULL);
+ WeakAssignFn.init(&CGM, "objc_assign_weak", IdTy, IdTy, PtrToIdTy, nullptr);
// id objc_read_weak(id*);
- WeakReadFn.init(&CGM, "objc_read_weak", IdTy, PtrToIdTy, NULL);
+ WeakReadFn.init(&CGM, "objc_read_weak", IdTy, PtrToIdTy, nullptr);
// void *objc_memmove_collectable(void*, void *, size_t);
MemMoveFn.init(&CGM, "objc_memmove_collectable", PtrTy, PtrTy, PtrTy,
- SizeTy, NULL);
+ SizeTy, nullptr);
}
}
@@ -1042,8 +1046,7 @@
const std::string &TypeEncoding, bool lval) {
SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
- llvm::GlobalAlias *SelValue = 0;
-
+ llvm::GlobalAlias *SelValue = nullptr;
for (SmallVectorImpl<TypedSelector>::iterator i = Types.begin(),
e = Types.end() ; i!=e ; i++) {
@@ -1052,11 +1055,10 @@
break;
}
}
- if (0 == SelValue) {
- SelValue = new llvm::GlobalAlias(SelectorTy,
- llvm::GlobalValue::PrivateLinkage,
- ".objc_selector_"+Sel.getAsString(), NULL,
- &TheModule);
+ if (!SelValue) {
+ SelValue = llvm::GlobalAlias::create(
+ SelectorTy->getElementType(), 0, llvm::GlobalValue::PrivateLinkage,
+ ".objc_selector_" + Sel.getAsString(), &TheModule);
Types.push_back(TypedSelector(TypeEncoding, SelValue));
}
@@ -1089,7 +1091,7 @@
if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
return MakeConstantString("@id");
} else {
- return 0;
+ return nullptr;
}
}
@@ -1118,7 +1120,7 @@
new llvm::GlobalVariable(CGM.getModule(), PtrToInt8Ty,
false,
llvm::GlobalValue::ExternalLinkage,
- 0, "__objc_id_type_info");
+ nullptr, "__objc_id_type_info");
return llvm::ConstantExpr::getBitCast(IDEHType, PtrToInt8Ty);
}
@@ -1145,7 +1147,8 @@
llvm::Constant *Vtable = TheModule.getGlobalVariable(vtableName);
if (!Vtable) {
Vtable = new llvm::GlobalVariable(TheModule, PtrToInt8Ty, true,
- llvm::GlobalValue::ExternalLinkage, 0, vtableName);
+ llvm::GlobalValue::ExternalLinkage,
+ nullptr, vtableName);
}
llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
Vtable = llvm::ConstantExpr::getGetElementPtr(Vtable, Two);
@@ -1159,7 +1162,7 @@
fields.push_back(typeName);
llvm::Constant *TI =
MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
- NULL), fields, "__objc_eh_typeinfo_" + className,
+ nullptr), fields, "__objc_eh_typeinfo_" + className,
llvm::GlobalValue::LinkOnceODRLinkage);
return llvm::ConstantExpr::getBitCast(TI, PtrToInt8Ty);
}
@@ -1185,7 +1188,7 @@
if (!isa)
isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false,
- llvm::GlobalValue::ExternalWeakLinkage, 0, Sym);
+ llvm::GlobalValue::ExternalWeakLinkage, nullptr, Sym);
else if (isa->getType() != PtrToIdTy)
isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy);
@@ -1194,7 +1197,7 @@
Ivars.push_back(MakeConstantString(Str));
Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
llvm::Constant *ObjCStr = MakeGlobal(
- llvm::StructType::get(PtrToIdTy, PtrToInt8Ty, IntTy, NULL),
+ llvm::StructType::get(PtrToIdTy, PtrToInt8Ty, IntTy, nullptr),
Ivars, ".objc_str");
ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
ObjCStrings[Str] = ObjCStr;
@@ -1223,7 +1226,7 @@
CGM.getTypes().ConvertType(ResultType)));
}
if (Sel == ReleaseSel) {
- return RValue::get(0);
+ return RValue::get(nullptr);
}
}
@@ -1238,9 +1241,9 @@
MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
- llvm::Value *ReceiverClass = 0;
+ llvm::Value *ReceiverClass = nullptr;
if (isCategoryImpl) {
- llvm::Constant *classLookupFunction = 0;
+ llvm::Constant *classLookupFunction = nullptr;
if (IsClassMessage) {
classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
IdTy, PtrTy, true), "objc_get_meta_class");
@@ -1258,16 +1261,16 @@
// super_class pointer from either the class or metaclass structure.
if (IsClassMessage) {
if (!MetaClassPtrAlias) {
- MetaClassPtrAlias = new llvm::GlobalAlias(IdTy,
- llvm::GlobalValue::InternalLinkage, ".objc_metaclass_ref" +
- Class->getNameAsString(), NULL, &TheModule);
+ MetaClassPtrAlias = llvm::GlobalAlias::create(
+ IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
+ ".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
}
ReceiverClass = MetaClassPtrAlias;
} else {
if (!ClassPtrAlias) {
- ClassPtrAlias = new llvm::GlobalAlias(IdTy,
- llvm::GlobalValue::InternalLinkage, ".objc_class_ref" +
- Class->getNameAsString(), NULL, &TheModule);
+ ClassPtrAlias = llvm::GlobalAlias::create(
+ IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
+ ".objc_class_ref" + Class->getNameAsString(), &TheModule);
}
ReceiverClass = ClassPtrAlias;
}
@@ -1275,14 +1278,14 @@
// Cast the pointer to a simplified version of the class structure
ReceiverClass = Builder.CreateBitCast(ReceiverClass,
llvm::PointerType::getUnqual(
- llvm::StructType::get(IdTy, IdTy, NULL)));
+ llvm::StructType::get(IdTy, IdTy, nullptr)));
// Get the superclass pointer
ReceiverClass = Builder.CreateStructGEP(ReceiverClass, 1);
// Load the superclass pointer
ReceiverClass = Builder.CreateLoad(ReceiverClass);
// Construct the structure used to look up the IMP
llvm::StructType *ObjCSuperTy = llvm::StructType::get(
- Receiver->getType(), IdTy, NULL);
+ Receiver->getType(), IdTy, nullptr);
llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
@@ -1302,7 +1305,8 @@
llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
llvm::Instruction *call;
- RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, 0, &call);
+ RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, nullptr,
+ &call);
call->setMetadata(msgSendMDKind, node);
return msgRet;
}
@@ -1326,7 +1330,7 @@
CGM.getTypes().ConvertType(ResultType)));
}
if (Sel == ReleaseSel) {
- return RValue::get(0);
+ return RValue::get(nullptr);
}
}
@@ -1344,9 +1348,9 @@
bool isPointerSizedReturn = (ResultType->isAnyPointerType() ||
ResultType->isIntegralOrEnumerationType() || ResultType->isVoidType());
- llvm::BasicBlock *startBB = 0;
- llvm::BasicBlock *messageBB = 0;
- llvm::BasicBlock *continueBB = 0;
+ llvm::BasicBlock *startBB = nullptr;
+ llvm::BasicBlock *messageBB = nullptr;
+ llvm::BasicBlock *continueBB = nullptr;
if (!isPointerSizedReturn) {
startBB = Builder.GetInsertBlock();
@@ -1371,7 +1375,8 @@
llvm::Value *impMD[] = {
llvm::MDString::get(VMContext, Sel.getAsString()),
llvm::MDString::get(VMContext, Class ? Class->getNameAsString() :""),
- llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), Class!=0)
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext),
+ Class!=nullptr)
};
llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
@@ -1414,7 +1419,8 @@
imp = EnforceType(Builder, imp, MSI.MessengerType);
llvm::Instruction *call;
- RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, 0, &call);
+ RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, nullptr,
+ &call);
call->setMetadata(msgSendMDKind, node);
@@ -1470,7 +1476,7 @@
PtrToInt8Ty, // Really a selector, but the runtime creates it us.
PtrToInt8Ty, // Method types
IMPTy, //Method pointer
- NULL);
+ nullptr);
std::vector<llvm::Constant*> Methods;
std::vector<llvm::Constant*> Elements;
for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
@@ -1502,7 +1508,7 @@
NextPtrTy,
IntTy,
ObjCMethodArrayTy,
- NULL);
+ nullptr);
Methods.clear();
Methods.push_back(llvm::ConstantPointerNull::get(
@@ -1526,7 +1532,7 @@
PtrToInt8Ty,
PtrToInt8Ty,
IntTy,
- NULL);
+ nullptr);
std::vector<llvm::Constant*> Ivars;
std::vector<llvm::Constant*> Elements;
for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
@@ -1548,7 +1554,7 @@
// Structure containing array and array count
llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy,
ObjCIvarArrayTy,
- NULL);
+ nullptr);
// Create an instance of the structure
return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
@@ -1598,7 +1604,7 @@
Properties->getType(), // properties
IntPtrTy, // strong_pointers
IntPtrTy, // weak_pointers
- NULL);
+ nullptr);
llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
// Fill in the structure
std::vector<llvm::Constant*> Elements;
@@ -1652,7 +1658,7 @@
llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(
PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
PtrToInt8Ty,
- NULL);
+ nullptr);
std::vector<llvm::Constant*> Methods;
std::vector<llvm::Constant*> Elements;
for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
@@ -1666,7 +1672,7 @@
llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy,
Methods);
llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(
- IntTy, ObjCMethodArrayTy, NULL);
+ IntTy, ObjCMethodArrayTy, nullptr);
Methods.clear();
Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
Methods.push_back(Array);
@@ -1681,11 +1687,11 @@
PtrTy, //Should be a recurisve pointer, but it's always NULL here.
SizeTy,
ProtocolArrayTy,
- NULL);
+ nullptr);
std::vector<llvm::Constant*> Elements;
for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
iter != endIter ; iter++) {
- llvm::Constant *protocol = 0;
+ llvm::Constant *protocol = nullptr;
llvm::StringMap<llvm::Constant*>::iterator value =
ExistingProtocols.find(*iter);
if (value == ExistingProtocols.end()) {
@@ -1731,7 +1737,7 @@
MethodList->getType(),
MethodList->getType(),
MethodList->getType(),
- NULL);
+ nullptr);
std::vector<llvm::Constant*> Elements;
// The isa pointer must be set to a magic number so the runtime knows it's
// the correct layout.
@@ -1812,7 +1818,7 @@
// structures for protocol metadata everywhere.
llvm::StructType *PropertyMetadataTy = llvm::StructType::get(
PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
- PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, NULL);
+ PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, nullptr);
std::vector<llvm::Constant*> Properties;
std::vector<llvm::Constant*> OptionalProperties;
@@ -1821,7 +1827,7 @@
for (auto *property : PD->properties()) {
std::vector<llvm::Constant*> Fields;
- Fields.push_back(MakePropertyEncodingString(property, 0));
+ Fields.push_back(MakePropertyEncodingString(property, nullptr));
PushPropertyAttributes(Fields, property);
if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
@@ -1888,7 +1894,7 @@
OptionalClassMethodList->getType(),
PropertyList->getType(),
OptionalPropertyList->getType(),
- NULL);
+ nullptr);
std::vector<llvm::Constant*> Elements;
// The isa pointer must be set to a magic number so the runtime knows it's
// the correct layout.
@@ -1929,7 +1935,7 @@
PtrTy, //Should be a recurisve pointer, but it's always NULL here.
SizeTy,
ProtocolArrayTy,
- NULL);
+ nullptr);
std::vector<llvm::Constant*> ProtocolElements;
for (llvm::StringMapIterator<llvm::Constant*> iter =
ExistingProtocols.begin(), endIter = ExistingProtocols.end();
@@ -1949,7 +1955,7 @@
ProtocolElements, ".objc_protocol_list"), PtrTy));
Categories.push_back(llvm::ConstantExpr::getBitCast(
MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
- PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
+ PtrTy, PtrTy, PtrTy, nullptr), Elements), PtrTy));
}
/// Libobjc2 uses a bitfield representation where small(ish) bitfields are
@@ -1989,7 +1995,7 @@
llvm::ConstantInt::get(Int32Ty, values.size()),
array };
llvm::Constant *GS = MakeGlobal(llvm::StructType::get(Int32Ty, arrayTy,
- NULL), fields);
+ nullptr), fields);
llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
return ptr;
}
@@ -2041,7 +2047,7 @@
GenerateProtocolList(Protocols), PtrTy));
Categories.push_back(llvm::ConstantExpr::getBitCast(
MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
- PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
+ PtrTy, PtrTy, PtrTy, nullptr), Elements), PtrTy));
}
llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID,
@@ -2052,7 +2058,7 @@
// setter name, setter types, getter name, getter types.
llvm::StructType *PropertyMetadataTy = llvm::StructType::get(
PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
- PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, NULL);
+ PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, nullptr);
std::vector<llvm::Constant*> Properties;
// Add all of the property methods need adding to the method list and to the
@@ -2279,7 +2285,7 @@
// the offset (third field in ivar structure)
llvm::Type *IndexTy = Int32Ty;
llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
- llvm::ConstantInt::get(IndexTy, 1), 0,
+ llvm::ConstantInt::get(IndexTy, 1), nullptr,
llvm::ConstantInt::get(IndexTy, 2) };
unsigned ivarIndex = 0;
@@ -2310,14 +2316,14 @@
llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
//Generate metaclass for class methods
llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
- NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList(
+ NULLPtr, 0x12L, ClassName.c_str(), nullptr, Zeros[0], GenerateIvarList(
empty, empty, empty), ClassMethodList, NULLPtr,
NULLPtr, NULLPtr, ZeroPtr, ZeroPtr, true);
// Generate the class structure
llvm::Constant *ClassStruct =
GenerateClassStructure(MetaClassStruct, SuperClass, 0x11L,
- ClassName.c_str(), 0,
+ ClassName.c_str(), nullptr,
llvm::ConstantInt::get(LongTy, instanceSize), IvarList,
MethodList, GenerateProtocolList(Protocols), IvarOffsetArray,
Properties, StrongIvarBitmap, WeakIvarBitmap);
@@ -2327,13 +2333,13 @@
ClassPtrAlias->replaceAllUsesWith(
llvm::ConstantExpr::getBitCast(ClassStruct, IdTy));
ClassPtrAlias->eraseFromParent();
- ClassPtrAlias = 0;
+ ClassPtrAlias = nullptr;
}
if (MetaClassPtrAlias) {
MetaClassPtrAlias->replaceAllUsesWith(
llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy));
MetaClassPtrAlias->eraseFromParent();
- MetaClassPtrAlias = 0;
+ MetaClassPtrAlias = nullptr;
}
// Add class structure to list to be added to the symtab later
@@ -2346,7 +2352,7 @@
// Only emit an ObjC load function if no Objective-C stuff has been called
if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
ExistingProtocols.empty() && SelectorTable.empty())
- return NULL;
+ return nullptr;
// Add all referenced protocols to a category.
GenerateProtocolHolderCategory();
@@ -2354,8 +2360,8 @@
llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>(
SelectorTy->getElementType());
llvm::Type *SelStructPtrTy = SelectorTy;
- if (SelStructTy == 0) {
- SelStructTy = llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, NULL);
+ if (!SelStructTy) {
+ SelStructTy = llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, nullptr);
SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy);
}
@@ -2376,7 +2382,7 @@
Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
ConstantStrings));
llvm::StructType *StaticsListTy =
- llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, NULL);
+ llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, nullptr);
llvm::Type *StaticsListPtrTy =
llvm::PointerType::getUnqual(StaticsListTy);
Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics");
@@ -2394,7 +2400,7 @@
llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelStructPtrTy,
llvm::Type::getInt16Ty(VMContext),
llvm::Type::getInt16Ty(VMContext),
- ClassListTy, NULL);
+ ClassListTy, nullptr);
Elements.clear();
// Pointer to an array of selectors used in this module.
@@ -2475,7 +2481,7 @@
// constants
llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy,
PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy),
- (RuntimeVersion >= 10) ? IntTy : NULL, NULL);
+ (RuntimeVersion >= 10) ? IntTy : nullptr, nullptr);
Elements.clear();
// Runtime version, used for ABI compatibility checking.
Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
@@ -2556,7 +2562,7 @@
llvm::Constant *TheClass =
TheModule.getGlobalVariable(("_OBJC_CLASS_" + iter->first).c_str(),
true);
- if (0 != TheClass) {
+ if (TheClass) {
TheClass = llvm::ConstantExpr::getBitCast(TheClass, PtrTy);
Builder.CreateCall2(RegisterAlias, TheClass,
MakeConstantString(iter->second));
@@ -2606,7 +2612,7 @@
llvm::Constant *CGObjCGNU::GetOptimizedPropertySetFunction(bool atomic,
bool copy) {
- return 0;
+ return nullptr;
}
llvm::Constant *CGObjCGNU::GetGetStructFunction() {
@@ -2616,10 +2622,10 @@
return SetStructPropertyFn;
}
llvm::Constant *CGObjCGNU::GetCppAtomicObjectGetFunction() {
- return 0;
+ return nullptr;
}
llvm::Constant *CGObjCGNU::GetCppAtomicObjectSetFunction() {
- return 0;
+ return nullptr;
}
llvm::Constant *CGObjCGNU::EnumerationMutationFunction() {
@@ -2767,7 +2773,7 @@
} else {
IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
llvm::Type::getInt32PtrTy(VMContext), false,
- llvm::GlobalValue::ExternalLinkage, 0, Name);
+ llvm::GlobalValue::ExternalLinkage, nullptr, Name);
}
}
return IvarOffsetPointer;
@@ -2797,7 +2803,7 @@
if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
return FindIvarInterface(Context, Super, OIVD);
- return 0;
+ return nullptr;
}
llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 8f5969c..95503cc 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1050,7 +1050,7 @@
llvm::Constant *GenerateConstantString(const StringLiteral *SL) override;
llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
- const ObjCContainerDecl *CD=0) override;
+ const ObjCContainerDecl *CD=nullptr) override;
void GenerateProtocol(const ObjCProtocolDecl *PD) override;
@@ -1564,7 +1564,7 @@
/// value.
struct NullReturnState {
llvm::BasicBlock *NullBB;
- NullReturnState() : NullBB(0) {}
+ NullReturnState() : NullBB(nullptr) {}
/// Perform a null-check of the given receiver.
void init(CodeGenFunction &CGF, llvm::Value *receiver) {
@@ -1593,8 +1593,8 @@
// The continuation block. This will be left null if we don't have an
// IP, which can happen if the method we're calling is marked noreturn.
- llvm::BasicBlock *contBB = 0;
-
+ llvm::BasicBlock *contBB = nullptr;
+
// Finish the call path.
llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
if (callBB) {
@@ -1881,7 +1881,7 @@
NullReturnState nullReturn;
- llvm::Constant *Fn = NULL;
+ llvm::Constant *Fn = nullptr;
if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
if (!IsSuper) nullReturn.init(CGF, Arg0);
Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
@@ -1915,7 +1915,7 @@
Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
- requiresnullCheck ? Method : 0);
+ requiresnullCheck ? Method : nullptr);
}
static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
@@ -2069,8 +2069,8 @@
bool ByrefLayout) {
bool IsUnion = (RD && RD->isUnion());
CharUnits MaxUnionSize = CharUnits::Zero();
- const FieldDecl *MaxField = 0;
- const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
+ const FieldDecl *MaxField = nullptr;
+ const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
CharUnits MaxFieldOffset = CharUnits::Zero();
CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
@@ -2092,8 +2092,8 @@
LastBitfieldOrUnnamedOffset = FieldOffset;
continue;
}
-
- LastFieldBitfieldOrUnnamed = 0;
+
+ LastFieldBitfieldOrUnnamed = nullptr;
QualType FQT = Field->getType();
if (FQT->isRecordType() || FQT->isUnionType()) {
if (FQT->isUnionType())
@@ -2558,7 +2558,7 @@
(void)NameRef;
assert(NameRef[0] == '\01' && (NameRef[1] == 'L' || NameRef[1] == 'l'));
assert(GV->getVisibility() == llvm::GlobalValue::DefaultVisibility);
- assert(GV->getLinkage() == llvm::GlobalValue::PrivateLinkage);
+ assert(GV->hasPrivateLinkage());
}
/*
@@ -2642,7 +2642,7 @@
if (Entry) {
// Already created, update the initializer.
- assert(Entry->getLinkage() == llvm::GlobalValue::PrivateLinkage);
+ assert(Entry->hasPrivateLinkage());
Entry->setInitializer(Init);
} else {
Entry =
@@ -2672,7 +2672,7 @@
Entry =
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
llvm::GlobalValue::PrivateLinkage,
- 0,
+ nullptr,
"\01L_OBJC_PROTOCOL_" + PD->getName());
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
// FIXME: Is this necessary? Why only for protocol?
@@ -2708,8 +2708,8 @@
EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
OptClassMethods),
- EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
- ObjCTypes),
+ EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr,
+ PD, ObjCTypes),
EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
MethodTypesExt, ObjCTypes)
};
@@ -2725,7 +2725,7 @@
// No special section, but goes in llvm.used
return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(),
Init,
- 0, 0, true);
+ nullptr, 0, true);
}
/*
@@ -2860,7 +2860,7 @@
llvm::GlobalVariable *GV =
CreateMetadataVar(Name, Init,
- (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
+ (ObjCABI == 2) ? "__DATA, __objc_const" : nullptr,
(ObjCABI == 2) ? 8 : 4,
true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
@@ -2880,8 +2880,8 @@
GetMethodVarType(MD)
};
if (!Desc[1])
- return 0;
-
+ return nullptr;
+
return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Desc);
}
@@ -3211,7 +3211,8 @@
llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
if (!GV)
GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
- llvm::GlobalValue::PrivateLinkage, 0, Name);
+ llvm::GlobalValue::PrivateLinkage, nullptr,
+ Name);
assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
"Forward metaclass reference has incorrect type.");
@@ -3225,7 +3226,8 @@
if (!GV)
GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
- llvm::GlobalValue::PrivateLinkage, 0, Name);
+ llvm::GlobalValue::PrivateLinkage, nullptr,
+ Name);
assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
"Forward class metadata reference has incorrect type.");
@@ -3345,7 +3347,7 @@
llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
llvm::Function *Fn = GetMethodDefinition(MD);
if (!Fn)
- return 0;
+ return nullptr;
llvm::Constant *Method[] = {
llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
@@ -3416,7 +3418,7 @@
llvm::Function *CGObjCMac::ModuleInitFunction() {
// Abuse this interface function as a place to finalize.
FinishModule();
- return NULL;
+ return nullptr;
}
llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
@@ -3799,7 +3801,7 @@
// @synchronized. We can't avoid a temp here because we need the
// value to be preserved. If the backend ever does liveness
// correctly after setjmp, this will be unnecessary.
- llvm::Value *SyncArgSlot = 0;
+ llvm::Value *SyncArgSlot = nullptr;
if (!isTry) {
llvm::Value *SyncArg =
CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
@@ -3834,7 +3836,7 @@
// A slot containing the exception to rethrow. Only needed when we
// have both a @catch and a @finally.
- llvm::Value *PropagatingExnVar = 0;
+ llvm::Value *PropagatingExnVar = nullptr;
// Push a normal cleanup to leave the try scope.
CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
@@ -3900,10 +3902,10 @@
const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
- bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
+ bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
- llvm::BasicBlock *CatchBlock = 0;
- llvm::BasicBlock *CatchHandler = 0;
+ llvm::BasicBlock *CatchBlock = nullptr;
+ llvm::BasicBlock *CatchHandler = nullptr;
if (HasFinally) {
// Save the currently-propagating exception before
// objc_exception_try_enter clears the exception slot.
@@ -3941,7 +3943,7 @@
const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
- const ObjCObjectPointerType *OPT = 0;
+ const ObjCObjectPointerType *OPT = nullptr;
// catch(...) always matches.
if (!CatchParam) {
@@ -4472,7 +4474,7 @@
if (I != MethodDefinitions.end())
return I->second;
- return NULL;
+ return nullptr;
}
/// GetIvarLayoutName - Returns a unique constant for the given
@@ -4493,8 +4495,8 @@
const llvm::StructLayout *RecLayout =
CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
- BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
- ForStrongLayout, HasUnion);
+ BuildAggrIvarLayout(nullptr, RecLayout, RD, Fields, BytePos, ForStrongLayout,
+ HasUnion);
}
void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
@@ -4506,9 +4508,9 @@
bool IsUnion = (RD && RD->isUnion());
uint64_t MaxUnionIvarSize = 0;
uint64_t MaxSkippedUnionIvarSize = 0;
- const FieldDecl *MaxField = 0;
- const FieldDecl *MaxSkippedField = 0;
- const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
+ const FieldDecl *MaxField = nullptr;
+ const FieldDecl *MaxSkippedField = nullptr;
+ const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
uint64_t MaxFieldOffset = 0;
uint64_t MaxSkippedFieldOffset = 0;
uint64_t LastBitfieldOrUnnamedOffset = 0;
@@ -4543,7 +4545,7 @@
continue;
}
- LastFieldBitfieldOrUnnamed = 0;
+ LastFieldBitfieldOrUnnamed = nullptr;
QualType FQT = Field->getType();
if (FQT->isRecordType() || FQT->isUnionType()) {
if (FQT->isUnionType())
@@ -4834,7 +4836,8 @@
SkipIvars.clear();
IvarsInfo.clear();
- BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
+ BuildAggrIvarLayout(OMD, nullptr, nullptr, RecFields, 0, ForStrongLayout,
+ hasUnion);
if (IvarsInfo.empty())
return llvm::Constant::getNullValue(PtrTy);
// Sort on byte position in case we encounterred a union nested in
@@ -4903,7 +4906,7 @@
bool Extended) {
std::string TypeStr;
if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
- return 0;
+ return nullptr;
llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
@@ -5010,14 +5013,14 @@
CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
: CGObjCCommonMac(cgm),
ObjCTypes(cgm) {
- ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
+ ObjCEmptyCacheVar = ObjCEmptyVtableVar = nullptr;
ObjCABI = 2;
}
/* *** */
ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
- : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
+ : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
{
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
@@ -5031,7 +5034,8 @@
// arm64 targets use "int" ivar offset variables. All others,
// including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
- if (CGM.getTarget().getTriple().getArch() == llvm::Triple::arm64)
+ if (CGM.getTarget().getTriple().getArch() == llvm::Triple::arm64 ||
+ CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
IvarOffsetVarTy = IntTy;
else
IvarOffsetVarTy = LongTy;
@@ -5056,11 +5060,12 @@
Ctx.getTranslationUnitDecl(),
SourceLocation(), SourceLocation(),
&Ctx.Idents.get("_objc_super"));
- RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
- Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit));
- RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
- Ctx.getObjCClassType(), 0, 0, false,
- ICIS_NoInit));
+ RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
+ nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
+ false, ICIS_NoInit));
+ RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
+ nullptr, Ctx.getObjCClassType(), nullptr,
+ nullptr, false, ICIS_NoInit));
RD->completeDefinition();
SuperCTy = Ctx.getTagDeclType(RD);
@@ -5437,11 +5442,12 @@
Ctx.getTranslationUnitDecl(),
SourceLocation(), SourceLocation(),
&Ctx.Idents.get("_message_ref_t"));
- RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
- Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit));
- RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
- Ctx.getObjCSelType(), 0, 0, false,
+ RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
+ nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
ICIS_NoInit));
+ RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
+ nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
+ false, ICIS_NoInit));
RD->completeDefinition();
MessageRefCTy = Ctx.getTagDeclType(RD);
@@ -5479,7 +5485,7 @@
llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
FinishNonFragileABIModule();
- return NULL;
+ return nullptr;
}
void CGObjCNonFragileABIMac::
@@ -5639,7 +5645,7 @@
Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
// FIXME. For 64bit targets add 0 here.
Values[ 3] = (flags & NonFragileABI_Class_Meta)
- ? GetIvarLayoutName(0, ObjCTypes)
+ ? GetIvarLayoutName(nullptr, ObjCTypes)
: BuildIvarLayout(ID, true);
Values[ 4] = GetClassName(ID->getIdentifier());
// const struct _method_list_t * const baseMethods;
@@ -5681,7 +5687,7 @@
if (flags & NonFragileABI_Class_Meta) {
Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
- Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
+ Values[ 8] = GetIvarLayoutName(nullptr, ObjCTypes);
Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
} else {
Values[ 7] = EmitIvarList(ID);
@@ -5745,7 +5751,7 @@
bool
CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
- return OD->getClassMethod(GetNullarySelector("load")) != 0;
+ return OD->getClassMethod(GetNullarySelector("load")) != nullptr;
}
void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
@@ -5772,22 +5778,22 @@
ObjCTypes.CacheTy,
false,
llvm::GlobalValue::ExternalLinkage,
- 0,
+ nullptr,
"_objc_empty_cache");
-
+
// Make this entry NULL for any iOS device target, any iOS simulator target,
// OS X with deployment target 10.9 or later.
const llvm::Triple &Triple = CGM.getTarget().getTriple();
if (Triple.isiOS() || (Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 9)))
// This entry will be null.
- ObjCEmptyVtableVar = 0;
+ ObjCEmptyVtableVar = nullptr;
else
ObjCEmptyVtableVar = new llvm::GlobalVariable(
CGM.getModule(),
ObjCTypes.ImpnfABITy,
false,
llvm::GlobalValue::ExternalLinkage,
- 0,
+ nullptr,
"_objc_empty_vtable");
}
assert(ID->getClassInterface() &&
@@ -5875,7 +5881,7 @@
if (!ID->getClassInterface()->getSuperClass()) {
flags |= NonFragileABI_Class_Root;
- SuperClassGV = 0;
+ SuperClassGV = nullptr;
} else {
// Has a root. Current class is not a root.
std::string RootClassName =
@@ -6042,7 +6048,7 @@
const ObjCMethodDecl *MD) {
llvm::Function *Fn = GetMethodDefinition(MD);
if (!Fn)
- return 0;
+ return nullptr;
llvm::Constant *Method[] = {
llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
@@ -6102,7 +6108,7 @@
if (!IvarOffsetGV)
IvarOffsetGV = new llvm::GlobalVariable(
CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false,
- llvm::GlobalValue::ExternalLinkage, 0, Name);
+ llvm::GlobalValue::ExternalLinkage, nullptr, Name);
return IvarOffsetGV;
}
@@ -6217,7 +6223,8 @@
// contents for protocols which were referenced but never defined.
Entry =
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
- false, llvm::GlobalValue::WeakAnyLinkage, 0,
+ false, llvm::GlobalValue::WeakAnyLinkage,
+ nullptr,
"\01l_OBJC_PROTOCOL_$_" + PD->getName());
Entry->setSection("__DATA,__datacoal_nt,coalesced");
}
@@ -6315,7 +6322,7 @@
"__DATA, __objc_const",
OptClassMethods);
Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
- 0, PD, ObjCTypes);
+ nullptr, PD, ObjCTypes);
uint32_t Size =
CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
@@ -6328,7 +6335,7 @@
if (Entry) {
// Already created, update the initializer.
- assert(Entry->getLinkage() == llvm::GlobalValue::WeakAnyLinkage);
+ assert(Entry->hasWeakAnyLinkage());
Entry->setInitializer(Init);
} else {
Entry =
@@ -6427,8 +6434,8 @@
ObjCTypes.SelectorPtrTy);
Desc[1] = GetMethodVarType(MD);
if (!Desc[1])
- return 0;
-
+ return nullptr;
+
// Protocol methods have no implementation. So, this entry is always NULL.
Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
@@ -6515,7 +6522,7 @@
// Second argument: a pointer to the message ref structure. Leave
// the actual argument value blank for now.
- args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
+ args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
args.insert(args.end(), formalArgs.begin(), formalArgs.end());
@@ -6530,7 +6537,7 @@
// The runtime currently never uses vtable dispatch for anything
// except normal, non-super message-sends.
// FIXME: don't use this for that.
- llvm::Constant *fn = 0;
+ llvm::Constant *fn = nullptr;
std::string messageRefName("\01l_");
if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
if (isSuper) {
@@ -6601,8 +6608,8 @@
callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
- return nullReturn.complete(CGF, result, resultType, formalArgs,
- requiresnullCheck ? method : 0);
+ return nullReturn.complete(CGF, result, resultType, formalArgs,
+ requiresnullCheck ? method : nullptr);
}
/// Generate code for a message send expression in the nonfragile abi.
@@ -6635,7 +6642,7 @@
if (!GV)
GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
- false, L, 0, Name);
+ false, L, nullptr, Name);
assert(GV->getLinkage() == L);
return GV;
@@ -6733,7 +6740,7 @@
std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, true);
(void)ClassGV;
- assert(ClassGV->getLinkage() == llvm::GlobalValue::ExternalWeakLinkage);
+ assert(ClassGV->hasExternalWeakLinkage());
}
return EmitClassRef(CGF, ID);
@@ -6950,7 +6957,7 @@
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
false,
llvm::GlobalValue::ExternalLinkage,
- 0, "OBJC_EHTYPE_id");
+ nullptr, "OBJC_EHTYPE_id");
return IDEHType;
}
@@ -7007,7 +7014,7 @@
return Entry =
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
llvm::GlobalValue::ExternalLinkage,
- 0,
+ nullptr,
("OBJC_EHTYPE_$_" +
ID->getIdentifier()->getName()));
}
@@ -7023,7 +7030,7 @@
VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
false,
llvm::GlobalValue::ExternalLinkage,
- 0, VTableName);
+ nullptr, VTableName);
llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index 8d6c653..1a5db9b 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -65,7 +65,7 @@
uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *OID,
const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, OID, 0, Ivar) /
+ return LookupFieldBitOffset(CGM, OID, nullptr, Ivar) /
CGM.getContext().getCharWidth();
}
@@ -116,7 +116,7 @@
// Note, there is a subtle invariant here: we can only call this routine on
// non-synthesized ivars but we may be called for synthesized ivars. However,
// a synthesized ivar can never be a bit-field, so this is safe.
- uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar);
+ uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, nullptr, Ivar);
uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth();
uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign();
uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext());
@@ -201,7 +201,7 @@
// @catch(...) always matches.
if (!CatchDecl) {
- Handler.TypeInfo = 0; // catch-all
+ Handler.TypeInfo = nullptr; // catch-all
// Don't consider any other catches.
break;
}
@@ -242,7 +242,7 @@
if (endCatchFn) {
// Add a cleanup to leave the catch.
- bool EndCatchMightThrow = (Handler.Variable == 0);
+ bool EndCatchMightThrow = (Handler.Variable == nullptr);
CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
EndCatchMightThrow,
diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index 2a8ae90..fc6bee3 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -156,8 +156,8 @@
Selector Sel,
llvm::Value *Receiver,
const CallArgList &CallArgs,
- const ObjCInterfaceDecl *Class = 0,
- const ObjCMethodDecl *Method = 0) = 0;
+ const ObjCInterfaceDecl *Class = nullptr,
+ const ObjCMethodDecl *Method = nullptr) = 0;
/// Generate an Objective-C message send operation to the super
/// class initiated in a method for Class and with the given Self
@@ -175,7 +175,7 @@
llvm::Value *Self,
bool IsClassMessage,
const CallArgList &CallArgs,
- const ObjCMethodDecl *Method = 0) = 0;
+ const ObjCMethodDecl *Method = nullptr) = 0;
/// Emit the code to return the named protocol as an object, as in a
/// \@protocol expression.
diff --git a/lib/CodeGen/CGOpenCLRuntime.cpp b/lib/CodeGen/CGOpenCLRuntime.cpp
index 6e1a3c9..079ef72 100644
--- a/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -39,7 +39,7 @@
switch (cast<BuiltinType>(T)->getKind()) {
default:
llvm_unreachable("Unexpected opencl builtin type!");
- return 0;
+ return nullptr;
case BuiltinType::OCLImage1d:
return llvm::PointerType::get(llvm::StructType::create(
Ctx, "opencl.image1d_t"), ImgAddrSpc);
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
new file mode 100644
index 0000000..da86e2b
--- /dev/null
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -0,0 +1,177 @@
+//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides a class for OpenMP runtime code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGOpenMPRuntime.h"
+#include "CodeGenFunction.h"
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/raw_ostream.h"
+#include <assert.h>
+
+using namespace clang;
+using namespace CodeGen;
+
+CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
+ : CGM(CGM), DefaultOpenMPPSource(nullptr) {
+ IdentTy = llvm::StructType::create(
+ "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
+ CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
+ CGM.Int8PtrTy /* psource */, NULL);
+ // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
+ llvm::Type *MicroParams[] = { llvm::PointerType::getUnqual(CGM.Int32Ty),
+ llvm::PointerType::getUnqual(CGM.Int32Ty) };
+ Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
+}
+
+llvm::Value *
+CGOpenMPRuntime::GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags) {
+ llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
+ if (!Entry) {
+ if (!DefaultOpenMPPSource) {
+ // Initialize default location for psource field of ident_t structure of
+ // all ident_t objects. Format is ";file;function;line;column;;".
+ // Taken from
+ // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
+ DefaultOpenMPPSource =
+ CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
+ DefaultOpenMPPSource =
+ llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
+ }
+ llvm::GlobalVariable *DefaultOpenMPLocation = cast<llvm::GlobalVariable>(
+ CGM.CreateRuntimeVariable(IdentTy, ".kmpc_default_loc.addr"));
+ DefaultOpenMPLocation->setUnnamedAddr(true);
+ DefaultOpenMPLocation->setConstant(true);
+ DefaultOpenMPLocation->setLinkage(llvm::GlobalValue::PrivateLinkage);
+
+ llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
+ llvm::Constant *Values[] = { Zero,
+ llvm::ConstantInt::get(CGM.Int32Ty, Flags),
+ Zero, Zero, DefaultOpenMPPSource };
+ llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
+ DefaultOpenMPLocation->setInitializer(Init);
+ return DefaultOpenMPLocation;
+ }
+ return Entry;
+}
+
+llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation(
+ CodeGenFunction &CGF, SourceLocation Loc, OpenMPLocationFlags Flags) {
+ // If no debug info is generated - return global default location.
+ if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
+ Loc.isInvalid())
+ return GetOrCreateDefaultOpenMPLocation(Flags);
+
+ assert(CGF.CurFn && "No function in current CodeGenFunction.");
+
+ llvm::Value *LocValue = nullptr;
+ OpenMPLocMapTy::iterator I = OpenMPLocMap.find(CGF.CurFn);
+ if (I != OpenMPLocMap.end()) {
+ LocValue = I->second;
+ } else {
+ // Generate "ident_t .kmpc_loc.addr;"
+ llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr");
+ AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
+ OpenMPLocMap[CGF.CurFn] = AI;
+ LocValue = AI;
+
+ CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
+ CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
+ CGF.Builder.CreateMemCpy(LocValue, GetOrCreateDefaultOpenMPLocation(Flags),
+ llvm::ConstantExpr::getSizeOf(IdentTy),
+ CGM.PointerAlignInBytes);
+ }
+
+ // char **psource = &.kmpc_loc_<flags>.addr.psource;
+ llvm::Value *PSource =
+ CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource);
+
+ SmallString<128> Buffer2;
+ llvm::raw_svector_ostream OS2(Buffer2);
+ // Build debug location
+ PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
+ OS2 << ";" << PLoc.getFilename() << ";";
+ if (const FunctionDecl *FD =
+ dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
+ OS2 << FD->getQualifiedNameAsString();
+ }
+ OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
+ // *psource = ";<File>;<Function>;<Line>;<Column>;;";
+ CGF.Builder.CreateStore(CGF.Builder.CreateGlobalStringPtr(OS2.str()),
+ PSource);
+ return LocValue;
+}
+
+llvm::Value *CGOpenMPRuntime::GetOpenMPGlobalThreadNum(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ assert(CGF.CurFn && "No function in current CodeGenFunction.");
+
+ llvm::Value *GTid = nullptr;
+ OpenMPGtidMapTy::iterator I = OpenMPGtidMap.find(CGF.CurFn);
+ if (I != OpenMPGtidMap.end()) {
+ GTid = I->second;
+ } else {
+ // Generate "int32 .kmpc_global_thread_num.addr;"
+ CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
+ CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
+ llvm::Value *Args[] = { EmitOpenMPUpdateLocation(CGF, Loc) };
+ GTid = CGF.EmitRuntimeCall(
+ CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args);
+ OpenMPGtidMap[CGF.CurFn] = GTid;
+ }
+ return GTid;
+}
+
+void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) {
+ assert(CGF.CurFn && "No function in current CodeGenFunction.");
+ if (OpenMPGtidMap.count(CGF.CurFn))
+ OpenMPGtidMap.erase(CGF.CurFn);
+ if (OpenMPLocMap.count(CGF.CurFn))
+ OpenMPLocMap.erase(CGF.CurFn);
+}
+
+llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
+ return llvm::PointerType::getUnqual(IdentTy);
+}
+
+llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
+ return llvm::PointerType::getUnqual(Kmpc_MicroTy);
+}
+
+llvm::Constant *
+CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
+ llvm::Constant *RTLFn = nullptr;
+ switch (Function) {
+ case OMPRTL__kmpc_fork_call: {
+ // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
+ // microtask, ...);
+ llvm::Type *TypeParams[] = { getIdentTyPointerTy(), CGM.Int32Ty,
+ getKmpc_MicroPointerTy() };
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, true);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
+ break;
+ }
+ case OMPRTL__kmpc_global_thread_num: {
+ // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
+ llvm::Type *TypeParams[] = { getIdentTyPointerTy() };
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
+ break;
+ }
+ }
+ return RTLFn;
+}
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
new file mode 100644
index 0000000..06103cf
--- /dev/null
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -0,0 +1,174 @@
+//===----- CGOpenMPRuntime.h - Interface to OpenMP Runtimes -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides a class for OpenMP runtime code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_OPENMPRUNTIME_H
+#define CLANG_CODEGEN_OPENMPRUNTIME_H
+
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+
+namespace llvm {
+class AllocaInst;
+class CallInst;
+class GlobalVariable;
+class Constant;
+class Function;
+class Module;
+class StructLayout;
+class FunctionType;
+class StructType;
+class Type;
+class Value;
+}
+
+namespace clang {
+
+namespace CodeGen {
+
+class CodeGenFunction;
+class CodeGenModule;
+
+class CGOpenMPRuntime {
+public:
+ /// \brief Values for bit flags used in the ident_t to describe the fields.
+ /// All enumeric elements are named and described in accordance with the code
+ /// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
+ enum OpenMPLocationFlags {
+ /// \brief Use trampoline for internal microtask.
+ OMP_IDENT_IMD = 0x01,
+ /// \brief Use c-style ident structure.
+ OMP_IDENT_KMPC = 0x02,
+ /// \brief Atomic reduction option for kmpc_reduce.
+ OMP_ATOMIC_REDUCE = 0x10,
+ /// \brief Explicit 'barrier' directive.
+ OMP_IDENT_BARRIER_EXPL = 0x20,
+ /// \brief Implicit barrier in code.
+ OMP_IDENT_BARRIER_IMPL = 0x40,
+ /// \brief Implicit barrier in 'for' directive.
+ OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
+ /// \brief Implicit barrier in 'sections' directive.
+ OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
+ /// \brief Implicit barrier in 'single' directive.
+ OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
+ };
+ enum OpenMPRTLFunction {
+ // Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
+ // microtask, ...);
+ OMPRTL__kmpc_fork_call,
+ // Call to kmp_int32 kmpc_global_thread_num(ident_t *loc);
+ OMPRTL__kmpc_global_thread_num
+ };
+
+private:
+ CodeGenModule &CGM;
+ /// \brief Default const ident_t object used for initialization of all other
+ /// ident_t objects.
+ llvm::Constant *DefaultOpenMPPSource;
+ /// \brief Map of flags and corrsponding default locations.
+ typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy;
+ OpenMPDefaultLocMapTy OpenMPDefaultLocMap;
+ llvm::Value *GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags);
+ /// \brief Describes ident structure that describes a source location.
+ /// All descriptions are taken from
+ /// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
+ /// Original structure:
+ /// typedef struct ident {
+ /// kmp_int32 reserved_1; /**< might be used in Fortran;
+ /// see above */
+ /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
+ /// KMP_IDENT_KMPC identifies this union
+ /// member */
+ /// kmp_int32 reserved_2; /**< not really used in Fortran any more;
+ /// see above */
+ ///#if USE_ITT_BUILD
+ /// /* but currently used for storing
+ /// region-specific ITT */
+ /// /* contextual information. */
+ ///#endif /* USE_ITT_BUILD */
+ /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
+ /// C++ */
+ /// char const *psource; /**< String describing the source location.
+ /// The string is composed of semi-colon separated
+ // fields which describe the source file,
+ /// the function and a pair of line numbers that
+ /// delimit the construct.
+ /// */
+ /// } ident_t;
+ enum IdentFieldIndex {
+ /// \brief might be used in Fortran
+ IdentField_Reserved_1,
+ /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
+ IdentField_Flags,
+ /// \brief Not really used in Fortran any more
+ IdentField_Reserved_2,
+ /// \brief Source[4] in Fortran, do not use for C++
+ IdentField_Reserved_3,
+ /// \brief String describing the source location. The string is composed of
+ /// semi-colon separated fields which describe the source file, the function
+ /// and a pair of line numbers that delimit the construct.
+ IdentField_PSource
+ };
+ llvm::StructType *IdentTy;
+ /// \brief The type for a microtask which gets passed to __kmpc_fork_call().
+ /// Original representation is:
+ /// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...);
+ llvm::FunctionType *Kmpc_MicroTy;
+ /// \brief Map of local debug location and functions.
+ typedef llvm::DenseMap<llvm::Function *, llvm::Value *> OpenMPLocMapTy;
+ OpenMPLocMapTy OpenMPLocMap;
+ /// \brief Map of local gtid and functions.
+ typedef llvm::DenseMap<llvm::Function *, llvm::Value *> OpenMPGtidMapTy;
+ OpenMPGtidMapTy OpenMPGtidMap;
+
+public:
+ CGOpenMPRuntime(CodeGenModule &CGM);
+ ~CGOpenMPRuntime() {}
+
+ /// \brief Cleans up references to the objects in finished function.
+ /// \param CGF Reference to finished CodeGenFunction.
+ ///
+ void FunctionFinished(CodeGenFunction &CGF);
+
+ /// \brief Emits object of ident_t type with info for source location.
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param Flags Flags for OpenMP location.
+ ///
+ llvm::Value *
+ EmitOpenMPUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPLocationFlags Flags = OMP_IDENT_KMPC);
+
+ /// \brief Generates global thread number value.
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ ///
+ llvm::Value *GetOpenMPGlobalThreadNum(CodeGenFunction &CGF,
+ SourceLocation Loc);
+
+ /// \brief Returns pointer to ident_t type;
+ llvm::Type *getIdentTyPointerTy();
+
+ /// \brief Returns pointer to kmpc_micro type;
+ llvm::Type *getKmpc_MicroPointerTy();
+
+ /// \brief Returns specified OpenMP runtime function.
+ /// \param Function OpenMP runtime function.
+ /// \return Specified function.
+ llvm::Constant *CreateRuntimeFunction(OpenMPRTLFunction Function);
+};
+}
+}
+
+#endif
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index 7049df7..4ca315c 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -22,7 +22,7 @@
using namespace CodeGen;
namespace {
-class RTTIBuilder {
+class ItaniumRTTIBuilder {
CodeGenModule &CGM; // Per-module state.
llvm::LLVMContext &VMContext;
@@ -62,7 +62,7 @@
void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
public:
- RTTIBuilder(CodeGenModule &CGM) : CGM(CGM),
+ ItaniumRTTIBuilder(CodeGenModule &CGM) : CGM(CGM),
VMContext(CGM.getModule().getContext()) { }
// Pointer type info flags.
@@ -110,7 +110,7 @@
}
llvm::GlobalVariable *
-RTTIBuilder::GetAddrOfTypeName(QualType Ty,
+ItaniumRTTIBuilder::GetAddrOfTypeName(QualType Ty,
llvm::GlobalVariable::LinkageTypes Linkage) {
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
@@ -132,7 +132,8 @@
return GV;
}
-llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
+llvm::Constant *
+ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
// Mangle the RTTI name.
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
@@ -147,7 +148,8 @@
// Create a new global variable.
GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
/*Constant=*/true,
- llvm::GlobalValue::ExternalLinkage, 0, Name);
+ llvm::GlobalValue::ExternalLinkage, nullptr,
+ Name);
}
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
@@ -316,8 +318,8 @@
/// getTypeInfoLinkage - Return the linkage that the type info and type info
/// name constants should have for the given type.
-static llvm::GlobalVariable::LinkageTypes
-getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) {
+llvm::GlobalVariable::LinkageTypes
+CodeGenModule::getTypeInfoLinkage(QualType Ty) {
// Itanium C++ ABI 2.9.5p7:
// In addition, it and all of the intermediate abi::__pointer_type_info
// structs in the chain down to the abi::__class_type_info for the
@@ -338,7 +340,7 @@
case VisibleNoLinkage:
case ExternalLinkage:
- if (!CGM.getLangOpts().RTTI) {
+ if (!getLangOpts().RTTI) {
// RTTI is not enabled, which means that this type info struct is going
// to be used for exception handling. Give it linkonce_odr linkage.
return llvm::GlobalValue::LinkOnceODRLinkage;
@@ -349,7 +351,7 @@
if (RD->hasAttr<WeakAttr>())
return llvm::GlobalValue::WeakODRLinkage;
if (RD->isDynamicClass())
- return CGM.getVTableLinkage(RD);
+ return getVTableLinkage(RD);
}
return llvm::GlobalValue::LinkOnceODRLinkage;
@@ -387,7 +389,7 @@
return true;
}
-void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
+void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
// abi::__class_type_info.
static const char * const ClassTypeInfo =
"_ZTVN10__cxxabiv117__class_type_infoE";
@@ -398,7 +400,7 @@
static const char * const VMIClassTypeInfo =
"_ZTVN10__cxxabiv121__vmi_class_type_infoE";
- const char *VTableName = 0;
+ const char *VTableName = nullptr;
switch (Ty->getTypeClass()) {
#define TYPE(Class, Base)
@@ -508,7 +510,7 @@
Fields.push_back(VTable);
}
-llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
+llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
// We want to operate on the canonical type.
Ty = CGM.getContext().getCanonicalType(Ty);
@@ -537,7 +539,7 @@
if (IsStdLib)
Linkage = llvm::GlobalValue::ExternalLinkage;
else
- Linkage = getTypeInfoLinkage(CGM, Ty);
+ Linkage = CGM.getTypeInfoLinkage(Ty);
// Add the vtable pointer.
BuildVTablePointer(cast<Type>(Ty));
@@ -678,18 +680,17 @@
// Give the type_info object and name the formal visibility of the
// type itself.
- Visibility formalVisibility = Ty->getVisibility();
- llvm::GlobalValue::VisibilityTypes llvmVisibility =
- CodeGenModule::GetLLVMVisibility(formalVisibility);
+ llvm::GlobalValue::VisibilityTypes llvmVisibility;
+ if (llvm::GlobalValue::isLocalLinkage(Linkage))
+ // If the linkage is local, only default visibility makes sense.
+ llvmVisibility = llvm::GlobalValue::DefaultVisibility;
+ else if (RTTIUniqueness == CGCXXABI::RUK_NonUniqueHidden)
+ llvmVisibility = llvm::GlobalValue::HiddenVisibility;
+ else
+ llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
TypeName->setVisibility(llvmVisibility);
GV->setVisibility(llvmVisibility);
- // FIXME: integrate this better into the above when we move to trunk
- if (RTTIUniqueness == CGCXXABI::RUK_NonUniqueHidden) {
- TypeName->setVisibility(llvm::GlobalValue::HiddenVisibility);
- GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- }
-
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
}
@@ -699,18 +700,18 @@
unsigned Flags = 0;
if (Quals.hasConst())
- Flags |= RTTIBuilder::PTI_Const;
+ Flags |= ItaniumRTTIBuilder::PTI_Const;
if (Quals.hasVolatile())
- Flags |= RTTIBuilder::PTI_Volatile;
+ Flags |= ItaniumRTTIBuilder::PTI_Volatile;
if (Quals.hasRestrict())
- Flags |= RTTIBuilder::PTI_Restrict;
+ Flags |= ItaniumRTTIBuilder::PTI_Restrict;
return Flags;
}
/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
/// for the given Objective-C object type.
-void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
+void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
// Drop qualifiers.
const Type *T = OT->getBaseType().getTypePtr();
assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
@@ -728,18 +729,18 @@
QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
// Everything else is single inheritance.
- llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy);
+ llvm::Constant *BaseTypeInfo = ItaniumRTTIBuilder(CGM).BuildTypeInfo(SuperTy);
Fields.push_back(BaseTypeInfo);
}
/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
/// inheritance, according to the Itanium C++ ABI, 2.95p6b.
-void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
+void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
// Itanium C++ ABI 2.9.5p6b:
// It adds to abi::__class_type_info a single member pointing to the
// type_info structure for the base type,
llvm::Constant *BaseTypeInfo =
- RTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
+ ItaniumRTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
Fields.push_back(BaseTypeInfo);
}
@@ -768,20 +769,20 @@
if (!Bases.VirtualBases.insert(BaseDecl)) {
// If this virtual base has been seen before, then the class is diamond
// shaped.
- Flags |= RTTIBuilder::VMI_DiamondShaped;
+ Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
} else {
if (Bases.NonVirtualBases.count(BaseDecl))
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+ Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
}
} else {
// Mark the non-virtual base as seen.
if (!Bases.NonVirtualBases.insert(BaseDecl)) {
// If this non-virtual base has been seen before, then the class has non-
// diamond shaped repeated inheritance.
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+ Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
} else {
if (Bases.VirtualBases.count(BaseDecl))
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+ Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
}
}
@@ -806,7 +807,7 @@
/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
/// classes with bases that do not satisfy the abi::__si_class_type_info
/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
-void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
+void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
llvm::Type *UnsignedIntLTy =
CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
@@ -847,7 +848,7 @@
// };
for (const auto &Base : RD->bases()) {
// The __base_type member points to the RTTI for the base type.
- Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(Base.getType()));
+ Fields.push_back(ItaniumRTTIBuilder(CGM).BuildTypeInfo(Base.getType()));
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
@@ -882,7 +883,7 @@
/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
/// used for pointer types.
-void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
+void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
Qualifiers Quals;
QualType UnqualifiedPointeeTy =
CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
@@ -906,13 +907,14 @@
// __pointee is a pointer to the std::type_info derivation for the
// unqualified type being pointed to.
llvm::Constant *PointeeTypeInfo =
- RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
+ ItaniumRTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
Fields.push_back(PointeeTypeInfo);
}
/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
/// struct, used for member pointer types.
-void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
+void
+ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
QualType PointeeTy = Ty->getPointeeType();
Qualifiers Quals;
@@ -943,14 +945,15 @@
// __pointee is a pointer to the std::type_info derivation for the
// unqualified type being pointed to.
llvm::Constant *PointeeTypeInfo =
- RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
+ ItaniumRTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
Fields.push_back(PointeeTypeInfo);
// Itanium C++ ABI 2.9.5p9:
// __context is a pointer to an abi::__class_type_info corresponding to the
// class type containing the member pointed to
// (e.g., the "A" in "int A::*").
- Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
+ Fields.push_back(
+ ItaniumRTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
}
llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
@@ -965,15 +968,17 @@
LangOpts.ObjCRuntime.isGNUFamily())
return ObjCRuntime->GetEHType(Ty);
- return RTTIBuilder(*this).BuildTypeInfo(Ty);
+ if (getTarget().getCXXABI().isMicrosoft())
+ return getMSTypeDescriptor(Ty);
+ return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
}
void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) {
QualType PointerType = Context.getPointerType(Type);
QualType PointerTypeConst = Context.getPointerType(Type.withConst());
- RTTIBuilder(*this).BuildTypeInfo(Type, true);
- RTTIBuilder(*this).BuildTypeInfo(PointerType, true);
- RTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, true);
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, true);
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
}
void CodeGenModule::EmitFundamentalRTTIDescriptors() {
@@ -984,7 +989,8 @@
Context.UnsignedShortTy, Context.IntTy,
Context.UnsignedIntTy, Context.LongTy,
Context.UnsignedLongTy, Context.LongLongTy,
- Context.UnsignedLongLongTy, Context.FloatTy,
+ Context.UnsignedLongLongTy,
+ Context.HalfTy, Context.FloatTy,
Context.DoubleTy, Context.LongDoubleTy,
Context.Char16Ty, Context.Char32Ty };
for (unsigned i = 0; i < llvm::array_lengthof(FundamentalTypes); ++i)
diff --git a/lib/CodeGen/CGRecordLayout.h b/lib/CodeGen/CGRecordLayout.h
index 0fc7b8a..b45fee5 100644
--- a/lib/CodeGen/CGRecordLayout.h
+++ b/lib/CodeGen/CGRecordLayout.h
@@ -183,6 +183,7 @@
/// \brief Return llvm::StructType element number that corresponds to the
/// field FD.
unsigned getLLVMFieldNo(const FieldDecl *FD) const {
+ FD = FD->getCanonicalDecl();
assert(FieldInfo.count(FD) && "Invalid field for record!");
return FieldInfo.lookup(FD);
}
@@ -201,6 +202,7 @@
/// \brief Return the BitFieldInfo that corresponds to the field FD.
const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const {
+ FD = FD->getCanonicalDecl();
assert(FD->isBitField() && "Invalid call for non-bit-field decl!");
llvm::DenseMap<const FieldDecl *, CGBitFieldInfo>::const_iterator
it = BitFields.find(FD);
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 75b4504..a10d8e7 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -84,7 +84,7 @@
const CXXRecordDecl *RD;
};
MemberInfo(CharUnits Offset, InfoKind Kind, llvm::Type *Data,
- const FieldDecl *FD = 0)
+ const FieldDecl *FD = nullptr)
: Offset(Offset), Kind(Kind), Data(Data), FD(FD) {}
MemberInfo(CharUnits Offset, InfoKind Kind, llvm::Type *Data,
const CXXRecordDecl *RD)
@@ -212,7 +212,7 @@
void CGRecordLowering::setBitFieldInfo(
const FieldDecl *FD, CharUnits StartOffset, llvm::Type *StorageType) {
- CGBitFieldInfo &Info = BitFields[FD];
+ CGBitFieldInfo &Info = BitFields[FD->getCanonicalDecl()];
Info.IsSigned = FD->getType()->isSignedIntegerOrEnumerationType();
Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset));
Info.Size = FD->getBitWidthValue(Context);
@@ -278,7 +278,7 @@
void CGRecordLowering::lowerUnion() {
CharUnits LayoutSize = Layout.getSize();
- llvm::Type *StorageType = 0;
+ llvm::Type *StorageType = nullptr;
// Compute zero-initializable status.
if (!D->field_empty() && !isZeroInitializable(*D->field_begin()))
IsZeroInitializable = IsZeroInitializableAsBase = false;
@@ -297,7 +297,7 @@
FieldType = getByteArrayType(LayoutSize);
setBitFieldInfo(Field, CharUnits::Zero(), FieldType);
}
- Fields[Field] = 0;
+ Fields[Field->getCanonicalDecl()] = 0;
llvm::Type *FieldType = getStorageType(Field);
// Conditionally update our storage type if we've got a new "better" one.
if (!StorageType ||
@@ -373,7 +373,7 @@
// Bitfields get the offset of their storage but come afterward and remain
// there after a stable sort.
Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
- MemberInfo::Field, 0, *Field));
+ MemberInfo::Field, nullptr, *Field));
}
return;
}
@@ -407,17 +407,18 @@
Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
for (; Run != Field; ++Run)
Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
- MemberInfo::Field, 0, *Run));
+ MemberInfo::Field, nullptr, *Run));
Run = FieldEnd;
}
}
void CGRecordLowering::accumulateBases() {
// If we've got a primary virtual base, we need to add it with the bases.
- if (Layout.isPrimaryBaseVirtual())
- Members.push_back(StorageInfo(
- CharUnits::Zero(),
- getStorageType(Layout.getPrimaryBase())));
+ if (Layout.isPrimaryBaseVirtual()) {
+ const CXXRecordDecl *BaseDecl = Layout.getPrimaryBase();
+ Members.push_back(MemberInfo(CharUnits::Zero(), MemberInfo::Base,
+ getStorageType(BaseDecl), BaseDecl));
+ }
// Accumulate the non-virtual bases.
for (const auto &Base : RD->bases()) {
if (Base.isVirtual())
@@ -440,8 +441,25 @@
}
void CGRecordLowering::accumulateVBases() {
- Members.push_back(MemberInfo(Layout.getNonVirtualSize(),
- MemberInfo::Scissor, 0, RD));
+ CharUnits ScissorOffset = Layout.getNonVirtualSize();
+ // In the itanium ABI, it's possible to place a vbase at a dsize that is
+ // smaller than the nvsize. Here we check to see if such a base is placed
+ // before the nvsize and set the scissor offset to that, instead of the
+ // nvsize.
+ if (!useMSABI())
+ for (const auto &Base : RD->vbases()) {
+ const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
+ if (BaseDecl->isEmpty())
+ continue;
+ // If the vbase is a primary virtual base of some base, then it doesn't
+ // get its own storage location but instead lives inside of that base.
+ if (Context.isNearlyEmpty(BaseDecl) && !hasOwnStorage(RD, BaseDecl))
+ continue;
+ ScissorOffset = std::min(ScissorOffset,
+ Layout.getVBaseClassOffset(BaseDecl));
+ }
+ Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor, nullptr,
+ RD));
for (const auto &Base : RD->vbases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (BaseDecl->isEmpty())
@@ -451,7 +469,8 @@
// get its own storage location but instead lives inside of that base.
if (!useMSABI() && Context.isNearlyEmpty(BaseDecl) &&
!hasOwnStorage(RD, BaseDecl)) {
- Members.push_back(MemberInfo(Offset, MemberInfo::VBase, 0, BaseDecl));
+ Members.push_back(MemberInfo(Offset, MemberInfo::VBase, nullptr,
+ BaseDecl));
continue;
}
// If we've got a vtordisp, add it as a storage type.
@@ -570,7 +589,7 @@
FieldTypes.push_back(Member->Data);
if (Member->Kind == MemberInfo::Field) {
if (Member->FD)
- Fields[Member->FD] = FieldTypes.size() - 1;
+ Fields[Member->FD->getCanonicalDecl()] = FieldTypes.size() - 1;
// A field without storage must be a bitfield.
if (!Member->Data)
setBitFieldInfo(Member->FD, Member->Offset, FieldTypes.back());
@@ -627,7 +646,7 @@
Builder.lower(false);
// If we're in C++, compute the base subobject type.
- llvm::StructType *BaseTy = 0;
+ llvm::StructType *BaseTy = nullptr;
if (isa<CXXRecordDecl>(D) && !D->isUnion() && !D->hasAttr<FinalAttr>()) {
BaseTy = Ty;
if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index cba9e6c..573973a 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -76,8 +76,6 @@
case Stmt::SEHExceptStmtClass:
case Stmt::SEHFinallyStmtClass:
case Stmt::MSDependentExistsStmtClass:
- case Stmt::OMPParallelDirectiveClass:
- case Stmt::OMPSimdDirectiveClass:
llvm_unreachable("invalid statement class to emit generically");
case Stmt::NullStmtClass:
case Stmt::CompoundStmtClass:
@@ -174,6 +172,12 @@
case Stmt::SEHTryStmtClass:
EmitSEHTryStmt(cast<SEHTryStmt>(*S));
break;
+ case Stmt::OMPParallelDirectiveClass:
+ EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
+ break;
+ case Stmt::OMPSimdDirectiveClass:
+ EmitOMPSimdDirective(cast<OMPSimdDirective>(*S));
+ break;
}
}
@@ -219,7 +223,7 @@
E = S.body_end()-GetLast; I != E; ++I)
EmitStmt(*I);
- llvm::Value *RetAlloca = 0;
+ llvm::Value *RetAlloca = nullptr;
if (GetLast) {
// We have to special case labels here. They are statements, but when put
// at the end of a statement expression, they yield the value of their
@@ -508,6 +512,8 @@
JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
EmitBlock(LoopHeader.getBlock());
+ LoopStack.push(LoopHeader.getBlock());
+
// Create an exit block for when the condition fails, which will
// also become the break target.
JumpDest LoopExit = getJumpDestInCurrentScope("while.end");
@@ -571,6 +577,8 @@
// Branch to the loop header again.
EmitBranch(LoopHeader.getBlock());
+ LoopStack.pop();
+
// Emit the exit block.
EmitBlock(LoopExit.getBlock(), true);
@@ -591,6 +599,9 @@
// Emit the body of the loop.
llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
+
+ LoopStack.push(LoopBody);
+
EmitBlockWithFallThrough(LoopBody, Cnt);
{
RunCleanupsScope BodyScope(*this);
@@ -621,6 +632,8 @@
Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock(),
PGO.createLoopWeights(S.getCond(), Cnt));
+ LoopStack.pop();
+
// Emit the exit block.
EmitBlock(LoopExit.getBlock());
@@ -652,6 +665,8 @@
llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
+ LoopStack.push(CondBlock);
+
// If the for loop doesn't have an increment we can just use the
// condition as the continue block. Otherwise we'll need to create
// a block for it (in the current scope, i.e. in the scope of the
@@ -722,6 +737,8 @@
if (DI)
DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
+ LoopStack.pop();
+
// Emit the fall-through block.
EmitBlock(LoopExit.getBlock(), true);
}
@@ -747,6 +764,8 @@
llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
EmitBlock(CondBlock);
+ LoopStack.push(CondBlock);
+
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
@@ -796,6 +815,8 @@
if (DI)
DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
+ LoopStack.pop();
+
// Emit the fall-through block.
EmitBlock(LoopExit.getBlock(), true);
}
@@ -848,7 +869,7 @@
// for side effects.
if (RV)
EmitAnyExpr(RV);
- } else if (RV == 0) {
+ } else if (!RV) {
// Do nothing (return value is left uninitialized)
} else if (FnRetTy->isReferenceType()) {
// If this function returns a reference, take the address of the expression
@@ -878,7 +899,7 @@
}
++NumReturnExprs;
- if (RV == 0 || RV->isEvaluatable(getContext()))
+ if (!RV || RV->isEvaluatable(getContext()))
++NumSimpleReturnExprs;
cleanupScope.ForceCleanup();
@@ -982,7 +1003,7 @@
llvm::Value *Cond =
Builder.CreateICmpULE(Diff, Builder.getInt(Range), "inbounds");
- llvm::MDNode *Weights = 0;
+ llvm::MDNode *Weights = nullptr;
if (SwitchWeights) {
uint64_t ThisCount = CaseCnt.getCount();
uint64_t DefaultCount = (*SwitchWeights)[0];
@@ -1066,7 +1087,7 @@
const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
// Otherwise, iteratively add consecutive cases to this switch stmt.
- while (NextCase && NextCase->getRHS() == 0) {
+ while (NextCase && NextCase->getRHS() == nullptr) {
CurCase = NextCase;
llvm::ConstantInt *CaseVal =
Builder.getInt(CurCase->getLHS()->EvaluateKnownConstInt(getContext()));
@@ -1127,7 +1148,7 @@
bool &FoundCase,
SmallVectorImpl<const Stmt*> &ResultStmts) {
// If this is a null statement, just succeed.
- if (S == 0)
+ if (!S)
return Case ? CSFC_Success : CSFC_FallThrough;
// If this is the switchcase (case 4: or default) that we're looking for, then
@@ -1135,7 +1156,7 @@
if (const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
if (S == Case) {
FoundCase = true;
- return CollectStatementsForCase(SC->getSubStmt(), 0, FoundCase,
+ return CollectStatementsForCase(SC->getSubStmt(), nullptr, FoundCase,
ResultStmts);
}
@@ -1146,7 +1167,7 @@
// If we are in the live part of the code and we found our break statement,
// return a success!
- if (Case == 0 && isa<BreakStmt>(S))
+ if (!Case && isa<BreakStmt>(S))
return CSFC_Success;
// If this is a switch statement, then it might contain the SwitchCase, the
@@ -1191,7 +1212,7 @@
// statements in the compound statement as candidates for inclusion.
assert(FoundCase && "Didn't find case but returned fallthrough?");
// We recursively found Case, so we're not looking for it anymore.
- Case = 0;
+ Case = nullptr;
// If we found the case and skipped declarations, we can't do the
// optimization.
@@ -1205,7 +1226,7 @@
// If we have statements in our range, then we know that the statements are
// live and need to be added to the set of statements we're tracking.
for (; I != E; ++I) {
- switch (CollectStatementsForCase(*I, 0, FoundCase, ResultStmts)) {
+ switch (CollectStatementsForCase(*I, nullptr, FoundCase, ResultStmts)) {
case CSFC_Failure: return CSFC_Failure;
case CSFC_FallThrough:
// A fallthrough result means that the statement was simple and just
@@ -1256,7 +1277,7 @@
// First step, find the switch case that is being branched to. We can do this
// efficiently by scanning the SwitchCase list.
const SwitchCase *Case = S.getSwitchCaseList();
- const DefaultStmt *DefaultCase = 0;
+ const DefaultStmt *DefaultCase = nullptr;
for (; Case; Case = Case->getNextSwitchCase()) {
// It's either a default or case. Just remember the default statement in
@@ -1278,10 +1299,10 @@
// If we didn't find a matching case, we use a default if it exists, or we
// elide the whole switch body!
- if (Case == 0) {
+ if (!Case) {
// It is safe to elide the body of the switch if it doesn't contain labels
// etc. If it is safe, return successfully with an empty ResultStmts list.
- if (DefaultCase == 0)
+ if (!DefaultCase)
return !CodeGenFunction::ContainsLabel(&S);
Case = DefaultCase;
}
@@ -1302,13 +1323,6 @@
}
void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
- JumpDest SwitchExit = getJumpDestInCurrentScope("sw.epilog");
-
- RunCleanupsScope ConditionScope(*this);
-
- if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
-
// Handle nested switch statements.
llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
SmallVector<uint64_t, 16> *SavedSwitchWeights = SwitchWeights;
@@ -1319,7 +1333,7 @@
llvm::APSInt ConstantCondValue;
if (ConstantFoldsToSimpleInteger(S.getCond(), ConstantCondValue)) {
SmallVector<const Stmt*, 4> CaseStmts;
- const SwitchCase *Case = 0;
+ const SwitchCase *Case = nullptr;
if (FindCaseStatementsForValue(S, ConstantCondValue, CaseStmts,
getContext(), Case)) {
if (Case) {
@@ -1328,10 +1342,15 @@
}
RunCleanupsScope ExecutedScope(*this);
+ // Emit the condition variable if needed inside the entire cleanup scope
+ // used by this special case for constant folded switches.
+ if (S.getConditionVariable())
+ EmitAutoVarDecl(*S.getConditionVariable());
+
// At this point, we are no longer "within" a switch instance, so
// we can temporarily enforce this to ensure that any embedded case
// statements are not emitted.
- SwitchInsn = 0;
+ SwitchInsn = nullptr;
// Okay, we can dead code eliminate everything except this case. Emit the
// specified series of statements and we're good.
@@ -1348,6 +1367,11 @@
}
}
+ JumpDest SwitchExit = getJumpDestInCurrentScope("sw.epilog");
+
+ RunCleanupsScope ConditionScope(*this);
+ if (S.getConditionVariable())
+ EmitAutoVarDecl(*S.getConditionVariable());
llvm::Value *CondV = EmitScalarExpr(S.getCond());
// Create basic block to hold stuff that comes after switch
@@ -1432,7 +1456,7 @@
static std::string
SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
- SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons=0) {
+ SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons=nullptr) {
std::string Result;
while (*Constraint) {
@@ -1918,6 +1942,12 @@
return F;
}
+llvm::Value *
+CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) {
+ LValue CapStruct = InitCapturedStruct(*this, S);
+ return CapStruct.getAddress();
+}
+
/// Creates the outlined function for a CapturedStmt.
llvm::Function *
CodeGenFunction::GenerateCapturedStmtFunction(const CapturedDecl *CD,
@@ -1944,7 +1974,9 @@
CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
// Generate the function.
- StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getBody()->getLocStart());
+ StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args,
+ CD->getLocation(),
+ CD->getBody()->getLocStart());
// Set the context parameter in CapturedStmtInfo.
llvm::Value *DeclPtr = LocalDeclMap[CD->getContextParam()];
@@ -1960,8 +1992,11 @@
CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal();
}
+ PGO.assignRegionCounters(CD, F);
CapturedStmtInfo->EmitBody(*this, CD->getBody());
FinishFunction(CD->getBodyRBrace());
+ PGO.emitInstrumentationData();
+ PGO.destroyRegionCounters();
return F;
}
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
new file mode 100644
index 0000000..17d8dd1
--- /dev/null
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -0,0 +1,78 @@
+//===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit OpenMP nodes as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGOpenMPRuntime.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtOpenMP.h"
+using namespace clang;
+using namespace CodeGen;
+
+//===----------------------------------------------------------------------===//
+// OpenMP Directive Emission
+//===----------------------------------------------------------------------===//
+
+void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
+ const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ llvm::Value *CapturedStruct = GenerateCapturedStmtArgument(*CS);
+
+ llvm::Value *OutlinedFn;
+ {
+ CodeGenFunction CGF(CGM, true);
+ CGCapturedStmtInfo CGInfo(*CS, CS->getCapturedRegionKind());
+ CGF.CapturedStmtInfo = &CGInfo;
+ OutlinedFn = CGF.GenerateCapturedStmtFunction(
+ CS->getCapturedDecl(), CS->getCapturedRecordDecl(), CS->getLocStart());
+ }
+
+ // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
+ llvm::Value *Args[] = {
+ CGM.getOpenMPRuntime().EmitOpenMPUpdateLocation(*this, S.getLocStart()),
+ Builder.getInt32(1), // Number of arguments after 'microtask' argument
+ // (there is only one additional argument - 'context')
+ Builder.CreateBitCast(OutlinedFn,
+ CGM.getOpenMPRuntime().getKmpc_MicroPointerTy()),
+ EmitCastToVoidPtr(CapturedStruct)
+ };
+ llvm::Constant *RTLFn = CGM.getOpenMPRuntime().CreateRuntimeFunction(
+ CGOpenMPRuntime::OMPRTL__kmpc_fork_call);
+ EmitRuntimeCall(RTLFn, Args);
+}
+
+void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
+ const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ const Stmt *Body = CS->getCapturedStmt();
+ 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;
+ }
+ default:
+ // Not handled yet
+ ;
+ }
+ }
+ EmitStmt(Body);
+}
+
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 0ad765c..d10db5a 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -71,11 +71,11 @@
const ThunkInfo &Thunk) {
// Emit the return adjustment.
bool NullCheckValue = !ResultType->isReferenceType();
-
- llvm::BasicBlock *AdjustNull = 0;
- llvm::BasicBlock *AdjustNotNull = 0;
- llvm::BasicBlock *AdjustEnd = 0;
-
+
+ llvm::BasicBlock *AdjustNull = nullptr;
+ llvm::BasicBlock *AdjustNotNull = nullptr;
+ llvm::BasicBlock *AdjustEnd = nullptr;
+
llvm::Value *ReturnValue = RV.getScalarVal();
if (NullCheckValue) {
@@ -159,7 +159,7 @@
// with "this".
llvm::Value *ThisPtr = &*AI;
llvm::BasicBlock *EntryBB = Fn->begin();
- llvm::Instruction *ThisStore = 0;
+ llvm::Instruction *ThisStore = nullptr;
for (llvm::BasicBlock::iterator I = EntryBB->begin(), E = EntryBB->end();
I != E; I++) {
if (isa<llvm::StoreInst>(I) && I->getOperand(0) == ThisPtr) {
@@ -217,7 +217,7 @@
// Start defining the function.
StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs,
- SourceLocation());
+ MD->getLocation(), SourceLocation());
// Since we didn't pass a GlobalDecl to StartFunction, do this ourselves.
CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
@@ -321,27 +321,30 @@
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(GD);
// FIXME: re-use FnInfo in this computation.
- llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
-
+ llvm::Constant *C = CGM.GetAddrOfThunk(GD, Thunk);
+ llvm::GlobalValue *Entry;
+
// Strip off a bitcast if we got one back.
- if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
+ if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(C)) {
assert(CE->getOpcode() == llvm::Instruction::BitCast);
- Entry = CE->getOperand(0);
+ Entry = cast<llvm::GlobalValue>(CE->getOperand(0));
+ } else {
+ Entry = cast<llvm::GlobalValue>(C);
}
-
+
// There's already a declaration with the same name, check if it has the same
// type or if we need to replace it.
- if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() !=
+ if (Entry->getType()->getElementType() !=
CGM.getTypes().GetFunctionTypeForVTable(GD)) {
- llvm::GlobalValue *OldThunkFn = cast<llvm::GlobalValue>(Entry);
-
+ llvm::GlobalValue *OldThunkFn = Entry;
+
// If the types mismatch then we have to rewrite the definition.
assert(OldThunkFn->isDeclaration() &&
"Shouldn't replace non-declaration");
// Remove the name from the old thunk function and get a new thunk.
OldThunkFn->setName(StringRef());
- Entry = CGM.GetAddrOfThunk(GD, Thunk);
+ Entry = cast<llvm::GlobalValue>(CGM.GetAddrOfThunk(GD, Thunk));
// If needed, replace the old thunk with a bitcast.
if (!OldThunkFn->use_empty()) {
@@ -443,13 +446,13 @@
llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(ClassType);
unsigned NextVTableThunkIndex = 0;
-
- llvm::Constant *PureVirtualFn = 0, *DeletedVirtualFn = 0;
+
+ llvm::Constant *PureVirtualFn = nullptr, *DeletedVirtualFn = nullptr;
for (unsigned I = 0; I != NumComponents; ++I) {
VTableComponent Component = Components[I];
- llvm::Constant *Init = 0;
+ llvm::Constant *Init = nullptr;
switch (Component.getKind()) {
case VTableComponent::CK_VCallOffset:
@@ -614,7 +617,7 @@
if (const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD)) {
// If this class has a key function, use that to determine the
// linkage of the vtable.
- const FunctionDecl *def = 0;
+ const FunctionDecl *def = nullptr;
if (keyFunction->hasBody(def))
keyFunction = cast<CXXMethodDecl>(def);
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index da2a034..956f324 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -110,7 +110,8 @@
Simple, // This is a normal l-value, use getAddress().
VectorElt, // This is a vector element l-value (V[i]), use getVector*
BitField, // This is a bitfield l-value, use getBitfield*.
- ExtVectorElt // This is an extended vector subset, use getExtVectorComp
+ ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
+ GlobalReg // This is a register l-value, use getGlobalReg()
} LVType;
llvm::Value *V;
@@ -168,7 +169,7 @@
private:
void Initialize(QualType Type, Qualifiers Quals,
CharUnits Alignment,
- llvm::MDNode *TBAAInfo = 0) {
+ llvm::MDNode *TBAAInfo = nullptr) {
this->Type = Type;
this->Quals = Quals;
this->Alignment = Alignment.getQuantity();
@@ -179,7 +180,7 @@
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
this->ImpreciseLifetime = false;
this->ThreadLocalRef = false;
- this->BaseIvarExp = 0;
+ this->BaseIvarExp = nullptr;
// Initialize fields for TBAA.
this->TBAABaseType = Type;
@@ -192,6 +193,7 @@
bool isVectorElt() const { return LVType == VectorElt; }
bool isBitField() const { return LVType == BitField; }
bool isExtVectorElt() const { return LVType == ExtVectorElt; }
+ bool isGlobalReg() const { return LVType == GlobalReg; }
bool isVolatileQualified() const { return Quals.hasVolatile(); }
bool isRestrictQualified() const { return Quals.hasRestrict(); }
@@ -286,9 +288,12 @@
return *BitFieldInfo;
}
+ // global register lvalue
+ llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; }
+
static LValue MakeAddr(llvm::Value *address, QualType type,
CharUnits alignment, ASTContext &Context,
- llvm::MDNode *TBAAInfo = 0) {
+ llvm::MDNode *TBAAInfo = nullptr) {
Qualifiers qs = type.getQualifiers();
qs.setObjCGCAttr(Context.getObjCGCAttrKind(type));
@@ -336,6 +341,16 @@
return R;
}
+ static LValue MakeGlobalReg(llvm::Value *Reg,
+ QualType type,
+ CharUnits Alignment) {
+ LValue R;
+ R.LVType = GlobalReg;
+ R.V = Reg;
+ R.Initialize(type, type.getQualifiers(), Alignment);
+ return R;
+ }
+
RValue asAggregateRValue() const {
// FIMXE: Alignment
return RValue::getAggregate(getAddress(), isVolatileQualified());
@@ -390,7 +405,7 @@
/// ignored - Returns an aggregate value slot indicating that the
/// aggregate value is being ignored.
static AggValueSlot ignored() {
- return forAddr(0, CharUnits(), Qualifiers(), IsNotDestructed,
+ return forAddr(nullptr, CharUnits(), Qualifiers(), IsNotDestructed,
DoesNotNeedGCBarriers, IsNotAliased);
}
@@ -460,7 +475,7 @@
}
bool isIgnored() const {
- return Addr == 0;
+ return Addr == nullptr;
}
CharUnits getAlignment() const {
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 12cb1ab..4b7d51b 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -9,6 +9,7 @@
Linker
MC
ObjCARCOpts
+ ProfileData
ScalarOpts
Support
Target
@@ -37,14 +38,17 @@
CGExprComplex.cpp
CGExprConstant.cpp
CGExprScalar.cpp
+ CGLoopInfo.cpp
CGObjC.cpp
CGObjCGNU.cpp
CGObjCMac.cpp
CGObjCRuntime.cpp
CGOpenCLRuntime.cpp
+ CGOpenMPRuntime.cpp
CGRTTI.cpp
CGRecordLayoutBuilder.cpp
CGStmt.cpp
+ CGStmtOpenMP.cpp
CGVTT.cpp
CGVTables.cpp
CodeGenABITypes.cpp
@@ -56,6 +60,7 @@
CodeGenTypes.cpp
ItaniumCXXABI.cpp
MicrosoftCXXABI.cpp
+ MicrosoftRTTI.cpp
ModuleBuilder.cpp
TargetInfo.cpp
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 573f8e9..2fe9842 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -11,6 +11,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -20,6 +21,7 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
@@ -103,6 +105,19 @@
return true;
}
+ void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
+ PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ Context->getSourceManager(),
+ "LLVM IR generation of inline method");
+ if (llvm::TimePassesIsEnabled)
+ LLVMIRGeneration.startTimer();
+
+ Gen->HandleInlineMethodDefinition(D);
+
+ if (llvm::TimePassesIsEnabled)
+ LLVMIRGeneration.stopTimer();
+ }
+
void HandleTranslationUnit(ASTContext &C) override {
{
PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
@@ -220,6 +235,11 @@
/// \return True if the diagnostic has been successfully reported, false
/// otherwise.
bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
+ /// \brief Specialized handler for the optimization diagnostic.
+ /// Note that this handler only accepts remarks and it always handles
+ /// them.
+ void
+ OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationRemark &D);
};
void BackendConsumer::anchor() {}
@@ -243,7 +263,7 @@
llvm::MemoryBuffer *CBuf =
llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(),
LBuf->getBufferIdentifier());
- FileID FID = CSM.createFileIDForMemBuffer(CBuf);
+ FileID FID = CSM.createFileID(CBuf);
// Translate the offset into the file.
unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
@@ -374,6 +394,51 @@
return true;
}
+void BackendConsumer::OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemark &D) {
+ // We only support remarks.
+ assert(D.getSeverity() == llvm::DS_Remark);
+
+ // Optimization remarks are active only if -Rpass=regexp is given and the
+ // regular expression pattern in 'regexp' matches the name of the pass
+ // name in \p D.
+ if (CodeGenOpts.OptimizationRemarkPattern &&
+ CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) {
+ SourceManager &SourceMgr = Context->getSourceManager();
+ FileManager &FileMgr = SourceMgr.getFileManager();
+ StringRef Filename;
+ unsigned Line, Column;
+ D.getLocation(&Filename, &Line, &Column);
+ SourceLocation Loc;
+ const FileEntry *FE = FileMgr.getFile(Filename);
+ if (FE && Line > 0) {
+ // If -gcolumn-info was not used, Column will be 0. This upsets the
+ // source manager, so if Column is not set, set it to 1.
+ if (Column == 0)
+ Column = 1;
+ Loc = SourceMgr.translateFileLineCol(FE, Line, Column);
+ }
+ Diags.Report(Loc, diag::remark_fe_backend_optimization_remark)
+ << AddFlagValue(D.getPassName()) << D.getMsg().str();
+
+ if (Line == 0)
+ // If we could not extract a source location for the diagnostic,
+ // inform the user how they can get source locations back.
+ //
+ // FIXME: We should really be generating !srcloc annotations when
+ // -Rpass is used. !srcloc annotations need to be emitted in
+ // approximately the same spots as !dbg nodes.
+ Diags.Report(diag::note_fe_backend_optimization_remark_missing_loc);
+ else if (Loc.isInvalid())
+ // If we were not able to translate the file:line:col information
+ // back to a SourceLocation, at least emit a note stating that
+ // we could not translate this location. This can happen in the
+ // case of #line directives.
+ Diags.Report(diag::note_fe_backend_optimization_remark_invalid_loc)
+ << Filename << Line << Column;
+ }
+}
+
/// \brief This function is invoked when the backend needs
/// to report something to the user.
void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
@@ -391,6 +456,11 @@
return;
ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
break;
+ case llvm::DK_OptimizationRemark:
+ // Optimization remarks are always handled completely by this
+ // handler. There is no generic way of emitting them.
+ OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemark>(DI));
+ return;
default:
// Plugin IDs are not bound to any value as they are set dynamically.
ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
@@ -410,7 +480,7 @@
#undef ComputeDiagID
CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
- : Act(_Act), LinkModule(0),
+ : Act(_Act), LinkModule(nullptr),
VMContext(_VMContext ? _VMContext : new LLVMContext),
OwnsVMContext(!_VMContext) {}
@@ -453,7 +523,7 @@
case Backend_EmitBC:
return CI.createDefaultOutputFile(true, InFile, "bc");
case Backend_EmitNothing:
- return 0;
+ return nullptr;
case Backend_EmitMCNull:
case Backend_EmitObj:
return CI.createDefaultOutputFile(true, InFile, "o");
@@ -467,7 +537,7 @@
BackendAction BA = static_cast<BackendAction>(Act);
std::unique_ptr<raw_ostream> OS(GetOutputStream(CI, InFile, BA));
if (BA != Backend_EmitNothing && !OS)
- return 0;
+ return nullptr;
llvm::Module *LinkModuleToUse = LinkModule;
@@ -482,7 +552,7 @@
if (!BCBuf) {
CI.getDiagnostics().Report(diag::err_cannot_open_file)
<< LinkBCFile << ErrorStr;
- return 0;
+ return nullptr;
}
ErrorOr<llvm::Module *> ModuleOrErr =
@@ -490,14 +560,17 @@
if (error_code EC = ModuleOrErr.getError()) {
CI.getDiagnostics().Report(diag::err_cannot_open_file)
<< LinkBCFile << EC.message();
- return 0;
+ return nullptr;
}
LinkModuleToUse = ModuleOrErr.get();
}
+ StringRef MainFileName = getCompilerInstance().getCodeGenOpts().MainFileName;
+ if (MainFileName.empty())
+ MainFileName = InFile;
BEConsumer = new BackendConsumer(BA, CI.getDiagnostics(), CI.getCodeGenOpts(),
CI.getTargetOpts(), CI.getLangOpts(),
- CI.getFrontendOpts().ShowTimers, InFile,
+ CI.getFrontendOpts().ShowTimers, MainFileName,
LinkModuleToUse, OS.release(), *VMContext);
return BEConsumer;
}
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 806540a..7de619e 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -15,6 +15,7 @@
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
+#include "CGOpenMPRuntime.h"
#include "CodeGenModule.h"
#include "CodeGenPGO.h"
#include "TargetInfo.h"
@@ -34,23 +35,26 @@
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
: CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
- Builder(cgm.getModule().getContext()), CapturedStmtInfo(0),
+ Builder(cgm.getModule().getContext(), llvm::ConstantFolder(),
+ CGBuilderInserterTy(this)), CapturedStmtInfo(nullptr),
SanitizePerformTypeCheck(CGM.getSanOpts().Null |
CGM.getSanOpts().Alignment |
CGM.getSanOpts().ObjectSize |
CGM.getSanOpts().Vptr),
- SanOpts(&CGM.getSanOpts()), AutoreleaseResult(false), BlockInfo(0),
- BlockPointer(0), LambdaThisCaptureField(0), NormalCleanupDest(0),
- NextCleanupDestIndex(1), FirstBlockInfo(0), EHResumeBlock(0),
- ExceptionSlot(0), EHSelectorSlot(0), DebugInfo(CGM.getModuleDebugInfo()),
- DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(0),
- PGO(cgm), SwitchInsn(0), SwitchWeights(0),
- CaseRangeBlock(0), UnreachableBlock(0), NumReturnExprs(0),
- NumSimpleReturnExprs(0), CXXABIThisDecl(0), CXXABIThisValue(0),
- CXXThisValue(0), CXXDefaultInitExprThis(0),
- CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),
- OutermostConditional(0), CurLexicalScope(0), TerminateLandingPad(0),
- TerminateHandler(0), TrapBB(0) {
+ SanOpts(&CGM.getSanOpts()), AutoreleaseResult(false), BlockInfo(nullptr),
+ BlockPointer(nullptr), LambdaThisCaptureField(nullptr),
+ NormalCleanupDest(nullptr), NextCleanupDestIndex(1),
+ FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr),
+ EHSelectorSlot(nullptr), DebugInfo(CGM.getModuleDebugInfo()),
+ DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr),
+ PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr),
+ CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0),
+ NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr),
+ CXXABIThisValue(nullptr), CXXThisValue(nullptr),
+ CXXDefaultInitExprThis(nullptr), CXXStructorImplicitParamDecl(nullptr),
+ CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr),
+ CurLexicalScope(nullptr), TerminateLandingPad(nullptr),
+ TerminateHandler(nullptr), TrapBB(nullptr) {
if (!suppressNewContext)
CGM.getCXXABI().getMangleContext().startNewFunction();
@@ -72,6 +76,10 @@
// something.
if (FirstBlockInfo)
destroyBlockInfos(FirstBlockInfo);
+
+ if (getLangOpts().OpenMP) {
+ CGM.getOpenMPRuntime().FunctionFinished(*this);
+ }
}
@@ -256,7 +264,7 @@
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
llvm::Instruction *Ptr = AllocaInsertPt;
- AllocaInsertPt = 0;
+ AllocaInsertPt = nullptr;
Ptr->eraseFromParent();
// If someone took the address of a label but never did an indirect goto, we
@@ -339,6 +347,8 @@
// Each MDNode is a list in the form of "key", N number of values which is
// the same number of values as their are kernel arguments.
+ const PrintingPolicy &Policy = ASTCtx.getPrintingPolicy();
+
// MDNode for the kernel argument address space qualifiers.
SmallVector<llvm::Value*, 8> addressQuals;
addressQuals.push_back(llvm::MDString::get(Context, "kernel_arg_addr_space"));
@@ -372,7 +382,8 @@
pointeeTy.getAddressSpace())));
// Get argument type name.
- std::string typeName = pointeeTy.getUnqualifiedType().getAsString() + "*";
+ std::string typeName =
+ pointeeTy.getUnqualifiedType().getAsString(Policy) + "*";
// Turn "unsigned type" to "utype"
std::string::size_type pos = typeName.find("unsigned");
@@ -398,7 +409,7 @@
addressQuals.push_back(Builder.getInt32(AddrSpc));
// Get argument type name.
- std::string typeName = ty.getUnqualifiedType().getAsString();
+ std::string typeName = ty.getUnqualifiedType().getAsString(Policy);
// Turn "unsigned type" to "utype"
std::string::size_type pos = typeName.find("unsigned");
@@ -495,17 +506,34 @@
OpenCLKernelMetadata->addOperand(kernelMDNode);
}
+/// Determine whether the function F ends with a return stmt.
+static bool endsWithReturn(const Decl* F) {
+ const Stmt *Body = nullptr;
+ if (auto *FD = dyn_cast_or_null<FunctionDecl>(F))
+ Body = FD->getBody();
+ else if (auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(F))
+ Body = OMD->getBody();
+
+ if (auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
+ auto LastStmt = CS->body_rbegin();
+ if (LastStmt != CS->body_rend())
+ return isa<ReturnStmt>(*LastStmt);
+ }
+ return false;
+}
+
void CodeGenFunction::StartFunction(GlobalDecl GD,
QualType RetTy,
llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
const FunctionArgList &Args,
+ SourceLocation Loc,
SourceLocation StartLoc) {
const Decl *D = GD.getDecl();
DidCallStackSave = false;
CurCodeDecl = D;
- CurFuncDecl = (D ? D->getNonClosureContext() : 0);
+ CurFuncDecl = (D ? D->getNonClosureContext() : nullptr);
FnRetTy = RetTy;
CurFn = Fn;
CurFnInfo = &FnInfo;
@@ -577,9 +605,7 @@
QualType FnType =
getContext().getFunctionType(RetTy, ArgTypes,
FunctionProtoType::ExtProtoInfo());
-
- DI->setLocation(StartLoc);
- DI->EmitFunctionStart(GD, FnType, CurFn, Builder);
+ DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, Builder);
}
if (ShouldInstrumentFunction())
@@ -590,12 +616,19 @@
if (RetTy->isVoidType()) {
// Void type; nothing to return.
- ReturnValue = 0;
+ ReturnValue = nullptr;
+
+ // Count the implicit return.
+ if (!endsWithReturn(D))
+ ++NumReturnExprs;
} else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
!hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
// Indirect aggregate return; emit returned value directly into sret slot.
// This reduces code size, and affects correctness in C++.
- ReturnValue = CurFn->arg_begin();
+ auto AI = CurFn->arg_begin();
+ if (CurFnInfo->getReturnInfo().isSRetAfterThis())
+ ++AI;
+ ReturnValue = AI;
} else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca &&
!hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
// Load the sret pointer from the argument struct and return into that.
@@ -682,7 +715,7 @@
/// this just calls EmitBlock().
void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
RegionCounter &Cnt) {
- llvm::BasicBlock *SkipCountBB = 0;
+ llvm::BasicBlock *SkipCountBB = nullptr;
if (HaveInsertPoint() && CGM.getCodeGenOpts().ProfileInstrGenerate) {
// When instrumenting for profiling, the fallthrough to certain
// statements needs to skip over the instrumentation code so that we
@@ -733,7 +766,7 @@
// Check if we should generate debug info for this function.
if (FD->hasAttr<NoDebugAttr>())
- DebugInfo = NULL; // disable debug info indefinitely for this function
+ DebugInfo = nullptr; // disable debug info indefinitely for this function
FunctionArgList Args;
QualType ResTy = FD->getReturnType();
@@ -756,8 +789,24 @@
if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
CurEHLocation = BodyRange.getEnd();
+ // Use the location of the start of the function to determine where
+ // the function definition is located. By default use the location
+ // of the declaration as the location for the subprogram. A function
+ // may lack a declaration in the source code if it is created by code
+ // gen. (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk).
+ SourceLocation Loc;
+ if (FD) {
+ Loc = FD->getLocation();
+
+ // If this is a function specialization then use the pattern body
+ // as the location for the function.
+ if (const FunctionDecl *SpecDecl = FD->getTemplateInstantiationPattern())
+ if (SpecDecl->hasBody(SpecDecl))
+ Loc = SpecDecl->getLocation();
+ }
+
// Emit the standard function prologue.
- StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin());
+ StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
// Generate the body of the function.
PGO.assignRegionCounters(GD.getDecl(), CurFn);
@@ -830,7 +879,7 @@
/// that we can just remove the code.
bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) {
// Null statement, not a label!
- if (S == 0) return false;
+ if (!S) return false;
// If this is a label, we have to emit the code, consider something like:
// if (0) { ... foo: bar(); } goto foo;
@@ -862,7 +911,7 @@
/// inside of it, this is fine.
bool CodeGenFunction::containsBreak(const Stmt *S) {
// Null statement, not a label!
- if (S == 0) return false;
+ if (!S) return false;
// If this is a switch or loop that defines its own break scope, then we can
// include it and anything inside of it.
@@ -1188,7 +1237,7 @@
}
} else {
SizeVal = CGM.getSize(Size);
- vla = 0;
+ vla = nullptr;
}
// If the type contains a pointer to data member we can't memset it to zero.
@@ -1225,7 +1274,7 @@
llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) {
// Make sure that there is a block for the indirect goto.
- if (IndirectBranch == 0)
+ if (!IndirectBranch)
GetIndirectGotoBlock();
llvm::BasicBlock *BB = getJumpDestForLabel(L).getBlock();
@@ -1259,7 +1308,7 @@
// If it's a VLA, we have to load the stored size. Note that
// this is the size of the VLA in bytes, not its size in elements.
- llvm::Value *numVLAElements = 0;
+ llvm::Value *numVLAElements = nullptr;
if (isa<VariableArrayType>(arrayType)) {
numVLAElements = getVLASize(cast<VariableArrayType>(arrayType)).first;
@@ -1352,7 +1401,7 @@
std::pair<llvm::Value*, QualType>
CodeGenFunction::getVLASize(const VariableArrayType *type) {
// The number of elements so far; always size_t.
- llvm::Value *numElements = 0;
+ llvm::Value *numElements = nullptr;
QualType elementType;
do {
@@ -1596,3 +1645,30 @@
}
CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }
+
+void CodeGenFunction::InsertHelper(llvm::Instruction *I,
+ const llvm::Twine &Name,
+ llvm::BasicBlock *BB,
+ llvm::BasicBlock::iterator InsertPt) const {
+ LoopStack.InsertHelper(I);
+}
+
+template <bool PreserveNames>
+void CGBuilderInserter<PreserveNames>::InsertHelper(
+ llvm::Instruction *I, const llvm::Twine &Name, llvm::BasicBlock *BB,
+ llvm::BasicBlock::iterator InsertPt) const {
+ llvm::IRBuilderDefaultInserter<PreserveNames>::InsertHelper(I, Name, BB,
+ InsertPt);
+ if (CGF)
+ CGF->InsertHelper(I, Name, BB, InsertPt);
+}
+
+#ifdef NDEBUG
+#define PreserveNames false
+#else
+#define PreserveNames true
+#endif
+template void CGBuilderInserter<PreserveNames>::InsertHelper(
+ llvm::Instruction *I, const llvm::Twine &Name, llvm::BasicBlock *BB,
+ llvm::BasicBlock::iterator InsertPt) const;
+#undef PreserveNames
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 5b0653a..750bec8 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -16,6 +16,7 @@
#include "CGBuilder.h"
#include "CGDebugInfo.h"
+#include "CGLoopInfo.h"
#include "CGValue.h"
#include "CodeGenModule.h"
#include "CodeGenPGO.h"
@@ -35,51 +36,51 @@
#include "llvm/Support/Debug.h"
namespace llvm {
- class BasicBlock;
- class LLVMContext;
- class MDNode;
- class Module;
- class SwitchInst;
- class Twine;
- class Value;
- class CallSite;
+class BasicBlock;
+class LLVMContext;
+class MDNode;
+class Module;
+class SwitchInst;
+class Twine;
+class Value;
+class CallSite;
}
namespace clang {
- class ASTContext;
- class BlockDecl;
- class CXXDestructorDecl;
- class CXXForRangeStmt;
- class CXXTryStmt;
- class Decl;
- class LabelDecl;
- class EnumConstantDecl;
- class FunctionDecl;
- class FunctionProtoType;
- class LabelStmt;
- class ObjCContainerDecl;
- class ObjCInterfaceDecl;
- class ObjCIvarDecl;
- class ObjCMethodDecl;
- class ObjCImplementationDecl;
- class ObjCPropertyImplDecl;
- class TargetInfo;
- class TargetCodeGenInfo;
- class VarDecl;
- class ObjCForCollectionStmt;
- class ObjCAtTryStmt;
- class ObjCAtThrowStmt;
- class ObjCAtSynchronizedStmt;
- class ObjCAutoreleasePoolStmt;
+class ASTContext;
+class BlockDecl;
+class CXXDestructorDecl;
+class CXXForRangeStmt;
+class CXXTryStmt;
+class Decl;
+class LabelDecl;
+class EnumConstantDecl;
+class FunctionDecl;
+class FunctionProtoType;
+class LabelStmt;
+class ObjCContainerDecl;
+class ObjCInterfaceDecl;
+class ObjCIvarDecl;
+class ObjCMethodDecl;
+class ObjCImplementationDecl;
+class ObjCPropertyImplDecl;
+class TargetInfo;
+class TargetCodeGenInfo;
+class VarDecl;
+class ObjCForCollectionStmt;
+class ObjCAtTryStmt;
+class ObjCAtThrowStmt;
+class ObjCAtSynchronizedStmt;
+class ObjCAutoreleasePoolStmt;
namespace CodeGen {
- class CodeGenTypes;
- class CGFunctionInfo;
- class CGRecordLayout;
- class CGBlockInfo;
- class CGCXXABI;
- class BlockFlags;
- class BlockFieldFlags;
+class CodeGenTypes;
+class CGFunctionInfo;
+class CGRecordLayout;
+class CGBlockInfo;
+class CGCXXABI;
+class BlockFlags;
+class BlockFieldFlags;
/// The kind of evaluation to perform on values of a particular
/// type. Basically, is the code in CGExprScalar, CGExprComplex, or
@@ -103,13 +104,13 @@
/// A jump destination is an abstract label, branching to which may
/// require a jump out through normal cleanups.
struct JumpDest {
- JumpDest() : Block(0), ScopeDepth(), Index(0) {}
+ JumpDest() : Block(nullptr), ScopeDepth(), Index(0) {}
JumpDest(llvm::BasicBlock *Block,
EHScopeStack::stable_iterator Depth,
unsigned Index)
: Block(Block), ScopeDepth(Depth), Index(Index) {}
- bool isValid() const { return Block != 0; }
+ bool isValid() const { return Block != nullptr; }
llvm::BasicBlock *getBlock() const { return Block; }
EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; }
unsigned getDestIndex() const { return Index; }
@@ -129,8 +130,15 @@
const TargetInfo &Target;
typedef std::pair<llvm::Value *, llvm::Value *> ComplexPairTy;
+ LoopInfoStack LoopStack;
CGBuilderTy Builder;
+ /// \brief CGBuilder insert helper. This function is called after an
+ /// instruction is created using Builder.
+ void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
+ llvm::BasicBlock *BB,
+ llvm::BasicBlock::iterator InsertPt) const;
+
/// CurFuncDecl - Holds the Decl for the current outermost
/// non-closure context.
const Decl *CurFuncDecl;
@@ -163,7 +171,7 @@
public:
explicit CGCapturedStmtInfo(const CapturedStmt &S,
CapturedRegionKind K = CR_Default)
- : Kind(K), ThisValue(0), CXXThisFieldDecl(0) {
+ : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) {
RecordDecl::field_iterator Field =
S.getCapturedRecordDecl()->field_begin();
@@ -190,11 +198,13 @@
return CaptureFields.lookup(VD);
}
- bool isCXXThisExprCaptured() const { return CXXThisFieldDecl != 0; }
+ bool isCXXThisExprCaptured() const { return CXXThisFieldDecl != nullptr; }
FieldDecl *getThisFieldDecl() const { return CXXThisFieldDecl; }
/// \brief Emit the captured statement body.
virtual void EmitBody(CodeGenFunction &CGF, Stmt *S) {
+ RegionCounter Cnt = CGF.getPGORegionCounter(S);
+ Cnt.beginRegion(CGF.Builder);
CGF.EmitStmt(S);
}
@@ -609,9 +619,9 @@
}
void end(CodeGenFunction &CGF) {
- assert(CGF.OutermostConditional != 0);
+ assert(CGF.OutermostConditional != nullptr);
if (CGF.OutermostConditional == this)
- CGF.OutermostConditional = 0;
+ CGF.OutermostConditional = nullptr;
}
/// Returns a block which will be executed prior to each
@@ -623,7 +633,7 @@
/// isInConditionalBranch - Return true if we're currently emitting
/// one branch or the other of a conditional expression.
- bool isInConditionalBranch() const { return OutermostConditional != 0; }
+ bool isInConditionalBranch() const { return OutermostConditional != nullptr; }
void setBeforeOutermostConditional(llvm::Value *value, llvm::Value *addr) {
assert(isInConditionalBranch());
@@ -644,7 +654,7 @@
public:
StmtExprEvaluation(CodeGenFunction &CGF)
: CGF(CGF), SavedOutermostConditional(CGF.OutermostConditional) {
- CGF.OutermostConditional = 0;
+ CGF.OutermostConditional = nullptr;
}
~StmtExprEvaluation() {
@@ -661,7 +671,7 @@
friend class CodeGenFunction;
public:
- PeepholeProtection() : Inst(0) {}
+ PeepholeProtection() : Inst(nullptr) {}
};
/// A non-RAII class containing all the information about a bound
@@ -679,7 +689,7 @@
bool boundLValue)
: OpaqueValue(ov), BoundLValue(boundLValue) {}
public:
- OpaqueValueMappingData() : OpaqueValue(0) {}
+ OpaqueValueMappingData() : OpaqueValue(nullptr) {}
static bool shouldBindAsLValue(const Expr *expr) {
// gl-values should be bound as l-values for obvious reasons.
@@ -724,8 +734,8 @@
return data;
}
- bool isValid() const { return OpaqueValue != 0; }
- void clear() { OpaqueValue = 0; }
+ bool isValid() const { return OpaqueValue != nullptr; }
+ void clear() { OpaqueValue = nullptr; }
void unbind(CodeGenFunction &CGF) {
assert(OpaqueValue && "no data to unbind!");
@@ -968,7 +978,7 @@
ASTContext &getContext() const { return CGM.getContext(); }
CGDebugInfo *getDebugInfo() {
if (DisableDebugInfo)
- return NULL;
+ return nullptr;
return DebugInfo;
}
void disableDebugInfo() { DisableDebugInfo = true; }
@@ -1001,7 +1011,7 @@
}
llvm::BasicBlock *getInvokeDest() {
- if (!EHStack.requiresLandingPad()) return 0;
+ if (!EHStack.requiresLandingPad()) return nullptr;
return getInvokeDestImpl();
}
@@ -1140,12 +1150,16 @@
void GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo);
+ /// \brief Emit code for the start of a function.
+ /// \param Loc The location to be associated with the function.
+ /// \param StartLoc The location of the function body.
void StartFunction(GlobalDecl GD,
QualType RetTy,
llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
const FunctionArgList &Args,
- SourceLocation StartLoc);
+ SourceLocation Loc = SourceLocation(),
+ SourceLocation StartLoc = SourceLocation());
void EmitConstructorBody(FunctionArgList &Args);
void EmitDestructorBody(FunctionArgList &Args);
@@ -1285,8 +1299,8 @@
/// createBasicBlock - Create an LLVM basic block.
llvm::BasicBlock *createBasicBlock(const Twine &name = "",
- llvm::Function *parent = 0,
- llvm::BasicBlock *before = 0) {
+ llvm::Function *parent = nullptr,
+ llvm::BasicBlock *before = nullptr) {
#ifdef NDEBUG
return llvm::BasicBlock::Create(getLLVMContext(), "", parent, before);
#else
@@ -1330,7 +1344,7 @@
/// HaveInsertPoint - True if an insertion point is defined. If not, this
/// indicates that the current code being emitted is unreachable.
bool HaveInsertPoint() const {
- return Builder.GetInsertBlock() != 0;
+ return Builder.GetInsertBlock() != nullptr;
}
/// EnsureInsertPoint - Ensure that an insertion point is defined so that
@@ -1741,19 +1755,21 @@
llvm::Value *SizeForLifetimeMarkers;
struct Invalid {};
- AutoVarEmission(Invalid) : Variable(0) {}
+ AutoVarEmission(Invalid) : Variable(nullptr) {}
AutoVarEmission(const VarDecl &variable)
- : Variable(&variable), Address(0), NRVOFlag(0),
+ : Variable(&variable), Address(nullptr), NRVOFlag(nullptr),
IsByRef(false), IsConstantAggregate(false),
- SizeForLifetimeMarkers(0) {}
+ SizeForLifetimeMarkers(nullptr) {}
- bool wasEmittedAsGlobal() const { return Address == 0; }
+ bool wasEmittedAsGlobal() const { return Address == nullptr; }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
- bool useLifetimeMarkers() const { return SizeForLifetimeMarkers != 0; }
+ bool useLifetimeMarkers() const {
+ return SizeForLifetimeMarkers != nullptr;
+ }
llvm::Value *getSizeForLifetimeMarkers() const {
assert(useLifetimeMarkers());
return SizeForLifetimeMarkers;
@@ -1872,6 +1888,10 @@
llvm::Function *GenerateCapturedStmtFunction(const CapturedDecl *CD,
const RecordDecl *RD,
SourceLocation Loc);
+ llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S);
+
+ void EmitOMPParallelDirective(const OMPParallelDirective &S);
+ void EmitOMPSimdDirective(const OMPSimdDirective &S);
//===--------------------------------------------------------------------===//
// LValue Expression Emission
@@ -1938,7 +1958,7 @@
llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
unsigned Alignment, QualType Ty,
SourceLocation Loc,
- llvm::MDNode *TBAAInfo = 0,
+ llvm::MDNode *TBAAInfo = nullptr,
QualType TBAABaseTy = QualType(),
uint64_t TBAAOffset = 0);
@@ -1953,7 +1973,7 @@
/// the LLVM value representation.
void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
bool Volatile, unsigned Alignment, QualType Ty,
- llvm::MDNode *TBAAInfo = 0, bool isInit = false,
+ llvm::MDNode *TBAAInfo = nullptr, bool isInit = false,
QualType TBAABaseTy = QualType(),
uint64_t TBAAOffset = 0);
@@ -1970,12 +1990,14 @@
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc);
RValue EmitLoadOfExtVectorElementLValue(LValue V);
RValue EmitLoadOfBitfieldLValue(LValue LV);
+ RValue EmitLoadOfGlobalRegLValue(LValue LV);
/// EmitStoreThroughLValue - Store the specified rvalue into the specified
/// lvalue, where both are guaranteed to the have the same type, and that type
/// is 'Ty'.
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false);
void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst);
+ void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst);
/// EmitStoreThroughBitfieldLValue - Store Src into Dst with same constraints
/// as EmitStoreThroughLValue.
@@ -1984,7 +2006,7 @@
/// bit-field contents after the store, appropriate for use as the result of
/// an assignment to the bit-field.
void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
- llvm::Value **Result=0);
+ llvm::Value **Result=nullptr);
/// Emit an l-value for an assignment (simple or compound) of complex type.
LValue EmitComplexAssignmentLValue(const BinaryOperator *E);
@@ -2000,6 +2022,7 @@
// Note: only available for agg return types
LValue EmitVAArgExprLValue(const VAArgExpr *E);
LValue EmitDeclRefLValue(const DeclRefExpr *E);
+ LValue EmitReadRegister(const VarDecl *VD);
LValue EmitStringLiteralLValue(const StringLiteral *E);
LValue EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E);
LValue EmitPredefinedLValue(const PredefinedExpr *E);
@@ -2031,7 +2054,9 @@
return ConstantEmission(C, false);
}
- LLVM_EXPLICIT operator bool() const { return ValueAndIsReference.getOpaqueValue() != 0; }
+ LLVM_EXPLICIT operator bool() const {
+ return ValueAndIsReference.getOpaqueValue() != nullptr;
+ }
bool isReference() const { return ValueAndIsReference.getInt(); }
LValue getReferenceLValue(CodeGenFunction &CGF, Expr *refExpr) const {
@@ -2094,15 +2119,15 @@
llvm::Value *Callee,
ReturnValueSlot ReturnValue,
const CallArgList &Args,
- const Decl *TargetDecl = 0,
- llvm::Instruction **callOrInvoke = 0);
+ const Decl *TargetDecl = nullptr,
+ llvm::Instruction **callOrInvoke = nullptr);
RValue EmitCall(QualType FnType, llvm::Value *Callee,
SourceLocation CallLoc,
ReturnValueSlot ReturnValue,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
- const Decl *TargetDecl = 0);
+ const Decl *TargetDecl = nullptr);
RValue EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue = ReturnValueSlot());
@@ -2176,8 +2201,6 @@
const llvm::CmpInst::Predicate Fp,
const llvm::CmpInst::Predicate Ip,
const llvm::Twine &Name = "");
- llvm::Value *EmitAArch64CompareBuiltinExpr(llvm::Value *Op, llvm::Type *Ty);
- llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitCommonNeonBuiltinExpr(unsigned BuiltinID,
@@ -2187,7 +2210,7 @@
unsigned Modifier,
const CallExpr *E,
SmallVectorImpl<llvm::Value *> &Ops,
- llvm::Value *Align = 0);
+ llvm::Value *Align = nullptr);
llvm::Function *LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
unsigned Modifier, llvm::Type *ArgTy,
const CallExpr *E);
@@ -2203,14 +2226,14 @@
llvm::Value *EmitConcatVectors(llvm::Value *Lo, llvm::Value *Hi,
llvm::Type *ArgTy);
llvm::Value *EmitExtractHigh(llvm::Value *In, llvm::Type *ResTy);
- // Helper functions for EmitARM64BuiltinExpr.
+ // Helper functions for EmitAArch64BuiltinExpr.
llvm::Value *vectorWrapScalar8(llvm::Value *Op);
llvm::Value *vectorWrapScalar16(llvm::Value *Op);
llvm::Value *emitVectorWrappedScalar8Intrinsic(
unsigned Int, SmallVectorImpl<llvm::Value *> &Ops, const char *Name);
llvm::Value *emitVectorWrappedScalar16Intrinsic(
unsigned Int, SmallVectorImpl<llvm::Value *> &Ops, const char *Name);
- llvm::Value *EmitARM64BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitNeon64Call(llvm::Function *F,
llvm::SmallVectorImpl<llvm::Value *> &O,
const char *name);
@@ -2385,7 +2408,7 @@
/// variables.
void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Constant *> Decls,
- llvm::GlobalVariable *Guard = 0);
+ llvm::GlobalVariable *Guard = nullptr);
/// GenerateCXXGlobalDtorsFunc - Generates code for destroying global
/// variables.
@@ -2413,7 +2436,7 @@
void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest);
- RValue EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest = 0);
+ RValue EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest = nullptr);
//===--------------------------------------------------------------------===//
// Annotations Emission
@@ -2559,7 +2582,7 @@
ForceColumnInfo);
} else {
// T::param_type_iterator might not have a default ctor.
- const QualType *NoIter = 0;
+ const QualType *NoIter = nullptr;
EmitCallArgs(Args, /*AllowExtraArguments=*/true, NoIter, NoIter, ArgBeg,
ArgEnd, ForceColumnInfo);
}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index c26f769..c55e231 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -18,6 +18,7 @@
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
+#include "CGOpenMPRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenPGO.h"
#include "CodeGenTBAA.h"
@@ -47,6 +48,7 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
@@ -75,15 +77,17 @@
DiagnosticsEngine &diags)
: Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M),
Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()),
- ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(0),
- TheTargetCodeGenInfo(0), Types(*this), VTables(*this), ObjCRuntime(0),
- OpenCLRuntime(0), CUDARuntime(0), DebugInfo(0), ARCData(0),
- NoObjCARCExceptionsMetadata(0), RRData(0), PGOData(0),
- CFConstantStringClassRef(0),
- ConstantStringClassRef(0), NSConstantStringType(0),
- NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockObjectAssign(0),
- BlockObjectDispose(0), BlockDescriptorType(0), GenericBlockLiteralType(0),
- LifetimeStartFn(0), LifetimeEndFn(0),
+ ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(nullptr),
+ TheTargetCodeGenInfo(nullptr), Types(*this), VTables(*this),
+ ObjCRuntime(nullptr), OpenCLRuntime(nullptr), OpenMPRuntime(nullptr),
+ CUDARuntime(nullptr), DebugInfo(nullptr), ARCData(nullptr),
+ NoObjCARCExceptionsMetadata(nullptr), RRData(nullptr), PGOReader(nullptr),
+ CFConstantStringClassRef(nullptr), ConstantStringClassRef(nullptr),
+ NSConstantStringType(nullptr), NSConcreteGlobalBlock(nullptr),
+ NSConcreteStackBlock(nullptr), BlockObjectAssign(nullptr),
+ BlockObjectDispose(nullptr), BlockDescriptorType(nullptr),
+ GenericBlockLiteralType(nullptr), LifetimeStartFn(nullptr),
+ LifetimeEndFn(nullptr),
SanitizerBlacklist(
llvm::SpecialCaseList::createOrDie(CGO.SanitizerBlacklistFile)),
SanOpts(SanitizerBlacklist->isIn(M) ? SanitizerOptions::Disabled
@@ -112,6 +116,8 @@
createObjCRuntime();
if (LangOpts.OpenCL)
createOpenCLRuntime();
+ if (LangOpts.OpenMP)
+ createOpenMPRuntime();
if (LangOpts.CUDA)
createCUDARuntime();
@@ -134,13 +140,20 @@
ARCData = new ARCEntrypoints();
RRData = new RREntrypoints();
- if (!CodeGenOpts.InstrProfileInput.empty())
- PGOData = new PGOProfileData(*this, CodeGenOpts.InstrProfileInput);
+ if (!CodeGenOpts.InstrProfileInput.empty()) {
+ if (llvm::error_code EC = llvm::IndexedInstrProfReader::create(
+ CodeGenOpts.InstrProfileInput, PGOReader)) {
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "Could not read profile: %0");
+ getDiags().Report(DiagID) << EC.message();
+ }
+ }
}
CodeGenModule::~CodeGenModule() {
delete ObjCRuntime;
delete OpenCLRuntime;
+ delete OpenMPRuntime;
delete CUDARuntime;
delete TheTargetCodeGenInfo;
delete TBAA;
@@ -172,6 +185,10 @@
OpenCLRuntime = new CGOpenCLRuntime(*this);
}
+void CodeGenModule::createOpenMPRuntime() {
+ OpenMPRuntime = new CGOpenMPRuntime(*this);
+}
+
void CodeGenModule::createCUDARuntime() {
CUDARuntime = CreateNVCUDARuntime(*this);
}
@@ -185,13 +202,13 @@
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (!Entry)
continue;
- llvm::Function *OldF = cast<llvm::Function>(Entry);
- llvm::Function *NewF = dyn_cast<llvm::Function>(Replacement);
+ auto *OldF = cast<llvm::Function>(Entry);
+ auto *NewF = dyn_cast<llvm::Function>(Replacement);
if (!NewF) {
- if (llvm::GlobalAlias *Alias = dyn_cast<llvm::GlobalAlias>(Replacement)) {
- NewF = dyn_cast<llvm::Function>(Alias->getAliasedGlobal());
+ if (auto *Alias = dyn_cast<llvm::GlobalAlias>(Replacement)) {
+ NewF = dyn_cast<llvm::Function>(Alias->getAliasee());
} else {
- llvm::ConstantExpr *CE = cast<llvm::ConstantExpr>(Replacement);
+ auto *CE = cast<llvm::ConstantExpr>(Replacement);
assert(CE->getOpcode() == llvm::Instruction::BitCast ||
CE->getOpcode() == llvm::Instruction::GetElementPtr);
NewF = dyn_cast<llvm::Function>(CE->getOperand(0));
@@ -213,46 +230,27 @@
// that we have to do this in CodeGen, but we only construct mangled names
// and aliases during codegen.
bool Error = false;
+ DiagnosticsEngine &Diags = getDiags();
for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
E = Aliases.end(); I != E; ++I) {
const GlobalDecl &GD = *I;
- const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+ const auto *D = cast<ValueDecl>(GD.getDecl());
const AliasAttr *AA = D->getAttr<AliasAttr>();
StringRef MangledName = getMangledName(GD);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
- llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry);
- llvm::GlobalValue *GV = Alias->getAliasedGlobal();
- if (!GV) {
+ auto *Alias = cast<llvm::GlobalAlias>(Entry);
+ llvm::GlobalValue *GV = Alias->getAliasee();
+ if (GV->isDeclaration()) {
Error = true;
- getDiags().Report(AA->getLocation(), diag::err_cyclic_alias);
- } else if (GV->isDeclaration()) {
- Error = true;
- getDiags().Report(AA->getLocation(), diag::err_alias_to_undefined);
+ Diags.Report(AA->getLocation(), diag::err_alias_to_undefined);
}
- // We have to handle alias to weak aliases in here. LLVM itself disallows
- // this since the object semantics would not match the IL one. For
- // compatibility with gcc we implement it by just pointing the alias
- // to its aliasee's aliasee. We also warn, since the user is probably
- // expecting the link to be weak.
- llvm::Constant *Aliasee = Alias->getAliasee();
- llvm::GlobalValue *AliaseeGV;
- if (auto CE = dyn_cast<llvm::ConstantExpr>(Aliasee)) {
- assert((CE->getOpcode() == llvm::Instruction::BitCast ||
- CE->getOpcode() == llvm::Instruction::AddrSpaceCast) &&
- "Unsupported aliasee");
- AliaseeGV = cast<llvm::GlobalValue>(CE->getOperand(0));
- } else {
- AliaseeGV = cast<llvm::GlobalValue>(Aliasee);
- }
- if (auto GA = dyn_cast<llvm::GlobalAlias>(AliaseeGV)) {
- if (GA->mayBeOverridden()) {
- getDiags().Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
- << GA->getAliasedGlobal()->getName() << GA->getName();
- Aliasee = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
- GA->getAliasee(), Alias->getType());
- Alias->setAliasee(Aliasee);
- }
+ llvm::GlobalObject *Aliasee = Alias->getAliasee();
+ if (const SectionAttr *SA = D->getAttr<SectionAttr>()) {
+ StringRef AliasSection = SA->getName();
+ if (AliasSection != Aliasee->getSection())
+ Diags.Report(SA->getLocation(), diag::warn_alias_with_section)
+ << AliasSection;
}
}
if (!Error)
@@ -263,7 +261,7 @@
const GlobalDecl &GD = *I;
StringRef MangledName = getMangledName(GD);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
- llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry);
+ auto *Alias = cast<llvm::GlobalAlias>(Entry);
Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType()));
Alias->eraseFromParent();
}
@@ -283,6 +281,12 @@
if (ObjCRuntime)
if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction())
AddGlobalCtor(ObjCInitFunction);
+ if (getCodeGenOpts().ProfileInstrGenerate)
+ if (llvm::Function *PGOInit = CodeGenPGO::emitInitialization(*this))
+ AddGlobalCtor(PGOInit, 0);
+ if (PGOReader && PGOStats.isOutOfDate())
+ getDiags().Report(diag::warn_profile_data_out_of_date)
+ << PGOStats.Visited << PGOStats.Missing << PGOStats.Mismatched;
EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitGlobalAnnotations();
@@ -299,12 +303,10 @@
getModule().addModuleFlag(llvm::Module::Warning, "Dwarf Version",
CodeGenOpts.DwarfVersion);
if (DebugInfo)
- // We support a single version in the linked module: error out when
- // modules do not have the same version. We are going to implement dropping
- // debug info when the version number is not up-to-date. Once that is
- // done, the bitcode linker is not going to see modules with different
- // version numbers.
- getModule().addModuleFlag(llvm::Module::Error, "Debug Info Version",
+ // We support a single version in the linked module. The LLVM
+ // parser will drop debug info with a different version number
+ // (and warn about it, too).
+ getModule().addModuleFlag(llvm::Module::Warning, "Debug Info Version",
llvm::DEBUG_METADATA_VERSION);
SimplifyPersonality();
@@ -328,25 +330,25 @@
llvm::MDNode *CodeGenModule::getTBAAInfo(QualType QTy) {
if (!TBAA)
- return 0;
+ return nullptr;
return TBAA->getTBAAInfo(QTy);
}
llvm::MDNode *CodeGenModule::getTBAAInfoForVTablePtr() {
if (!TBAA)
- return 0;
+ return nullptr;
return TBAA->getTBAAInfoForVTablePtr();
}
llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) {
if (!TBAA)
- return 0;
+ return nullptr;
return TBAA->getTBAAStructInfo(QTy);
}
llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) {
if (!TBAA)
- return 0;
+ return nullptr;
return TBAA->getTBAAStructTypeInfo(QTy);
}
@@ -354,7 +356,7 @@
llvm::MDNode *AccessN,
uint64_t O) {
if (!TBAA)
- return 0;
+ return nullptr;
return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O);
}
@@ -453,7 +455,7 @@
}
StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
- const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
+ const auto *ND = cast<NamedDecl>(GD.getDecl());
StringRef &Str = MangledDeclNames[GD.getCanonicalDecl()];
if (!Str.empty())
@@ -469,9 +471,9 @@
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
- if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND))
+ if (const auto *D = dyn_cast<CXXConstructorDecl>(ND))
getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out);
- else if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND))
+ else if (const auto *D = dyn_cast<CXXDestructorDecl>(ND))
getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out);
else
getCXXABI().getMangleContext().mangleName(ND, Out);
@@ -492,12 +494,12 @@
MangleContext &MangleCtx = getCXXABI().getMangleContext();
const Decl *D = GD.getDecl();
llvm::raw_svector_ostream Out(Buffer.getBuffer());
- if (D == 0)
+ if (!D)
MangleCtx.mangleGlobalBlock(BD,
dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out);
- else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
+ else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out);
- else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D))
+ else if (const auto *DD = dyn_cast<CXXDestructorDecl>(D))
MangleCtx.mangleDtorBlock(DD, GD.getDtorType(), BD, Out);
else
MangleCtx.mangleBlock(cast<DeclContext>(D), BD, Out);
@@ -509,16 +511,17 @@
/// AddGlobalCtor - Add a function to the list that will be called before
/// main() runs.
-void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor, int Priority) {
+void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority,
+ llvm::Constant *AssociatedData) {
// FIXME: Type coercion of void()* types.
- GlobalCtors.push_back(std::make_pair(Ctor, Priority));
+ GlobalCtors.push_back(Structor(Priority, Ctor, AssociatedData));
}
/// AddGlobalDtor - Add a function to the list that will be called
/// when the module is unloaded.
-void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) {
+void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority) {
// FIXME: Type coercion of void()* types.
- GlobalDtors.push_back(std::make_pair(Dtor, Priority));
+ GlobalDtors.push_back(Structor(Priority, Dtor, 0));
}
void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
@@ -526,16 +529,19 @@
llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false);
llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy);
- // Get the type of a ctor entry, { i32, void ()* }.
- llvm::StructType *CtorStructTy =
- llvm::StructType::get(Int32Ty, llvm::PointerType::getUnqual(CtorFTy), NULL);
+ // Get the type of a ctor entry, { i32, void ()*, i8* }.
+ llvm::StructType *CtorStructTy = llvm::StructType::get(
+ Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy, NULL);
// Construct the constructor and destructor arrays.
SmallVector<llvm::Constant*, 8> Ctors;
for (CtorList::const_iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
llvm::Constant *S[] = {
- llvm::ConstantInt::get(Int32Ty, I->second, false),
- llvm::ConstantExpr::getBitCast(I->first, CtorPFTy)
+ llvm::ConstantInt::get(Int32Ty, I->Priority, false),
+ llvm::ConstantExpr::getBitCast(I->Initializer, CtorPFTy),
+ (I->AssociatedData
+ ? llvm::ConstantExpr::getBitCast(I->AssociatedData, VoidPtrTy)
+ : llvm::Constant::getNullValue(VoidPtrTy))
};
Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S));
}
@@ -551,69 +557,25 @@
llvm::GlobalValue::LinkageTypes
CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
- const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
+ const auto *D = cast<FunctionDecl>(GD.getDecl());
GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
- if (Linkage == GVA_Internal)
- return llvm::Function::InternalLinkage;
-
- if (D->hasAttr<DLLExportAttr>())
- return llvm::Function::ExternalLinkage;
-
- if (D->hasAttr<WeakAttr>())
- return llvm::Function::WeakAnyLinkage;
-
- // In C99 mode, 'inline' functions are guaranteed to have a strong
- // definition somewhere else, so we can use available_externally linkage.
- if (Linkage == GVA_C99Inline)
- return llvm::Function::AvailableExternallyLinkage;
-
- // Note that Apple's kernel linker doesn't support symbol
- // coalescing, so we need to avoid linkonce and weak linkages there.
- // Normally, this means we just map to internal, but for explicit
- // instantiations we'll map to external.
-
- // In C++, the compiler has to emit a definition in every translation unit
- // that references the function. We should use linkonce_odr because
- // a) if all references in this translation unit are optimized away, we
- // don't need to codegen it. b) if the function persists, it needs to be
- // merged with other definitions. c) C++ has the ODR, so we know the
- // definition is dependable.
- if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
- return !Context.getLangOpts().AppleKext
- ? llvm::Function::LinkOnceODRLinkage
- : llvm::Function::InternalLinkage;
-
- // An explicit instantiation of a template has weak linkage, since
- // explicit instantiations can occur in multiple translation units
- // and must all be equivalent. However, we are not allowed to
- // throw away these explicit instantiations.
- if (Linkage == GVA_StrongODR)
- return !Context.getLangOpts().AppleKext
- ? llvm::Function::WeakODRLinkage
- : llvm::Function::ExternalLinkage;
-
- // Destructor variants in the Microsoft C++ ABI are always linkonce_odr thunks
- // emitted on an as-needed basis.
if (isa<CXXDestructorDecl>(D) &&
getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
- GD.getDtorType()))
- return llvm::Function::LinkOnceODRLinkage;
+ GD.getDtorType())) {
+ // Destructor variants in the Microsoft C++ ABI are always internal or
+ // linkonce_odr thunks emitted on an as-needed basis.
+ return Linkage == GVA_Internal ? llvm::GlobalValue::InternalLinkage
+ : llvm::GlobalValue::LinkOnceODRLinkage;
+ }
- // Otherwise, we have strong external linkage.
- assert(Linkage == GVA_StrongExternal);
- return llvm::Function::ExternalLinkage;
+ return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false);
}
-
-/// SetFunctionDefinitionAttributes - Set attributes for a global.
-///
-/// FIXME: This is currently only done for aliases and functions, but not for
-/// variables (these details are set in EmitGlobalVarDefinition for variables).
-void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
- llvm::GlobalValue *GV) {
- SetCommonAttributes(D, GV);
+void CodeGenModule::setFunctionDefinitionAttributes(const FunctionDecl *D,
+ llvm::Function *F) {
+ setNonAliasAttributes(D, F);
}
void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
@@ -717,7 +679,7 @@
if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D))
F->setUnnamedAddr(true);
- else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D))
+ else if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
if (MD->isVirtual())
F->setUnnamedAddr(true);
@@ -732,20 +694,23 @@
void CodeGenModule::SetCommonAttributes(const Decl *D,
llvm::GlobalValue *GV) {
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (const auto *ND = dyn_cast<NamedDecl>(D))
setGlobalVisibility(GV, ND);
else
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
if (D->hasAttr<UsedAttr>())
addUsedGlobal(GV);
+}
+
+void CodeGenModule::setNonAliasAttributes(const Decl *D,
+ llvm::GlobalObject *GO) {
+ SetCommonAttributes(D, GO);
if (const SectionAttr *SA = D->getAttr<SectionAttr>())
- GV->setSection(SA->getName());
+ GO->setSection(SA->getName());
- // Alias cannot have attributes. Filter them here.
- if (!isa<llvm::GlobalAlias>(GV))
- getTargetCodeGenInfo().SetTargetAttributes(D, GV, *this);
+ getTargetCodeGenInfo().SetTargetAttributes(D, GO, *this);
}
void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
@@ -756,7 +721,32 @@
F->setLinkage(llvm::Function::InternalLinkage);
- SetCommonAttributes(D, F);
+ setNonAliasAttributes(D, F);
+}
+
+static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
+ const NamedDecl *ND) {
+ // Set linkage and visibility in case we never see a definition.
+ LinkageInfo LV = ND->getLinkageAndVisibility();
+ if (LV.getLinkage() != ExternalLinkage) {
+ // Don't set internal linkage on declarations.
+ } else {
+ if (ND->hasAttr<DLLImportAttr>()) {
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ } else if (ND->hasAttr<DLLExportAttr>()) {
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ } else if (ND->hasAttr<WeakAttr>() || ND->isWeakImported()) {
+ // "extern_weak" is overloaded in LLVM; we probably should have
+ // separate linkage types for this.
+ GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+ }
+
+ // Set visibility on a declaration only if it's explicit.
+ if (LV.isVisibilityExplicit())
+ GV->setVisibility(CodeGenModule::GetLLVMVisibility(LV.getVisibility()));
+ }
}
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD,
@@ -770,7 +760,7 @@
return;
}
- const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+ const auto *FD = cast<FunctionDecl>(GD.getDecl());
if (!IsIncompleteFunction)
SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);
@@ -791,22 +781,12 @@
// Only a few attributes are set on declarations; these may later be
// overridden by a definition.
- if (FD->hasAttr<DLLImportAttr>()) {
- F->setLinkage(llvm::Function::ExternalLinkage);
- F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- } else if (FD->hasAttr<WeakAttr>() ||
- FD->isWeakImported()) {
- // "extern_weak" is overloaded in LLVM; we probably should have
- // separate linkage types for this.
- F->setLinkage(llvm::Function::ExternalWeakLinkage);
- } else {
- F->setLinkage(llvm::Function::ExternalLinkage);
- if (FD->hasAttr<DLLExportAttr>())
- F->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ setLinkageAndVisibilityForGV(F, FD);
- LinkageInfo LV = FD->getLinkageAndVisibility();
- if (LV.getLinkage() == ExternalLinkage && LV.isVisibilityExplicit()) {
- F->setVisibility(GetLLVMVisibility(LV.getVisibility()));
+ if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(FD)) {
+ if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) {
+ // Don't dllexport/import destructor thunks.
+ F->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
}
}
@@ -851,11 +831,9 @@
return;
llvm::ArrayType *ATy = llvm::ArrayType::get(CGM.Int8PtrTy, UsedArray.size());
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), ATy, false,
- llvm::GlobalValue::AppendingLinkage,
- llvm::ConstantArray::get(ATy, UsedArray),
- Name);
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), ATy, false, llvm::GlobalValue::AppendingLinkage,
+ llvm::ConstantArray::get(ATy, UsedArray), Name);
GV->setSection("llvm.metadata");
}
@@ -1036,9 +1014,9 @@
// Create a new global variable for the ConstantStruct in the Module.
llvm::Constant *Array = llvm::ConstantArray::get(llvm::ArrayType::get(
Annotations[0]->getType(), Annotations.size()), Annotations);
- llvm::GlobalValue *gv = new llvm::GlobalVariable(getModule(),
- Array->getType(), false, llvm::GlobalValue::AppendingLinkage, Array,
- "llvm.global.annotations");
+ auto *gv = new llvm::GlobalVariable(getModule(), Array->getType(), false,
+ llvm::GlobalValue::AppendingLinkage,
+ Array, "llvm.global.annotations");
gv->setSection(AnnotationSection);
}
@@ -1049,8 +1027,9 @@
// Not found yet, create a new global.
llvm::Constant *s = llvm::ConstantDataArray::getString(getLLVMContext(), Str);
- llvm::GlobalValue *gv = new llvm::GlobalVariable(getModule(), s->getType(),
- true, llvm::GlobalValue::PrivateLinkage, s, ".str");
+ auto *gv =
+ new llvm::GlobalVariable(getModule(), s->getType(), true,
+ llvm::GlobalValue::PrivateLinkage, s, ".str");
gv->setSection(AnnotationSection);
gv->setUnnamedAddr(true);
AStr = gv;
@@ -1122,7 +1101,7 @@
llvm::Constant *Init = EmitUuidofInitializer(Uuid, E->getType());
assert(Init && "failed to initialize as constant");
- llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ auto *GV = new llvm::GlobalVariable(
getModule(), Init->getType(),
/*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
return GV;
@@ -1148,9 +1127,10 @@
/*ForVTable=*/false);
else
Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
- llvm::PointerType::getUnqual(DeclTy), 0);
+ llvm::PointerType::getUnqual(DeclTy),
+ nullptr);
- llvm::GlobalValue* F = cast<llvm::GlobalValue>(Aliasee);
+ auto *F = cast<llvm::GlobalValue>(Aliasee);
F->setLinkage(llvm::Function::ExternalWeakLinkage);
WeakRefReferences.insert(F);
@@ -1158,7 +1138,7 @@
}
void CodeGenModule::EmitGlobal(GlobalDecl GD) {
- const ValueDecl *Global = cast<ValueDecl>(GD.getDecl());
+ const auto *Global = cast<ValueDecl>(GD.getDecl());
// Weak references don't produce any output by themselves.
if (Global->hasAttr<WeakRefAttr>())
@@ -1187,7 +1167,7 @@
}
// Ignore declarations, they will be emitted on their first use.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
// Forward declarations are emitted lazily on first use.
if (!FD->doesThisDeclarationHaveABody()) {
if (!FD->doesDeclarationForceExternallyVisibleDefinition())
@@ -1204,7 +1184,7 @@
return;
}
} else {
- const VarDecl *VD = cast<VarDecl>(Global);
+ const auto *VD = cast<VarDecl>(Global);
assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
if (VD->isThisDeclarationADefinition() != VarDecl::Definition)
@@ -1224,7 +1204,7 @@
if (getLangOpts().CPlusPlus && isa<VarDecl>(Global) &&
cast<VarDecl>(Global)->hasInit()) {
DelayedCXXInitPosition[Global] = CXXGlobalInits.size();
- CXXGlobalInits.push_back(0);
+ CXXGlobalInits.push_back(nullptr);
}
// If the value has already been used, add it directly to the
@@ -1299,7 +1279,7 @@
CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
return true;
- const FunctionDecl *F = cast<FunctionDecl>(GD.getDecl());
+ const auto *F = cast<FunctionDecl>(GD.getDecl());
if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr<AlwaysInlineAttr>())
return false;
// PR9614. Avoid cases where the source code is lying to us. An available
@@ -1321,14 +1301,13 @@
if (CGDebugInfo *DI = getModuleDebugInfo())
if (getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
- const PointerType *ThisPtr =
- cast<PointerType>(D->getThisType(getContext()));
+ const auto *ThisPtr = cast<PointerType>(D->getThisType(getContext()));
DI->getOrCreateRecordType(ThisPtr->getPointeeType(), D->getLocation());
}
}
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
- const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+ const auto *D = cast<ValueDecl>(GD.getDecl());
PrettyStackTraceDecl CrashInfo(const_cast<ValueDecl *>(D), D->getLocation(),
Context.getSourceManager(),
@@ -1340,13 +1319,13 @@
if (!shouldEmitFunction(GD))
return;
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
CompleteDIClassType(Method);
// Make sure to emit the definition(s) before we emit the thunks.
// This is necessary for the generation of certain thunks.
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Method))
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(Method))
EmitCXXConstructor(CD, GD.getCtorType());
- else if (const CXXDestructorDecl *DD =dyn_cast<CXXDestructorDecl>(Method))
+ else if (const auto *DD = dyn_cast<CXXDestructorDecl>(Method))
EmitCXXDestructor(DD, GD.getDtorType());
else
EmitGlobalFunctionDefinition(GD, GV);
@@ -1359,8 +1338,8 @@
return EmitGlobalFunctionDefinition(GD, GV);
}
-
- if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+
+ if (const auto *VD = dyn_cast<VarDecl>(D))
return EmitGlobalVarDefinition(VD);
llvm_unreachable("Invalid argument to EmitGlobalDefinition()");
@@ -1465,7 +1444,7 @@
// in a vtable, unless it's already marked as used.
} else if (getLangOpts().CPlusPlus && D) {
// Look for a declaration that's lexically in a record.
- const FunctionDecl *FD = cast<FunctionDecl>(D);
+ const auto *FD = cast<FunctionDecl>(D);
FD = FD->getMostRecentDecl();
do {
if (isa<CXXRecordDecl>(FD->getLexicalDeclContext())) {
@@ -1484,6 +1463,8 @@
}
}
+ getTargetCodeGenInfo().emitTargetMD(D, F, *this);
+
// Make sure the result is of the requested type.
if (!IsIncompleteFunction) {
assert(F->getType()->getElementType() == Ty);
@@ -1518,7 +1499,7 @@
llvm::Constant *C =
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
/*DontDefer=*/false, ExtraAttrs);
- if (llvm::Function *F = dyn_cast<llvm::Function>(C))
+ if (auto *F = dyn_cast<llvm::Function>(C))
if (F->empty())
F->setCallingConv(getRuntimeCC());
return C;
@@ -1544,6 +1525,18 @@
return true;
}
+static bool isVarDeclInlineInitializedStaticDataMember(const VarDecl *VD) {
+ if (!VD->isStaticDataMember())
+ return false;
+ const VarDecl *InitDecl;
+ const Expr *InitExpr = VD->getAnyInitializer(InitDecl);
+ if (!InitExpr)
+ return false;
+ if (InitDecl->isThisDeclarationADefinition())
+ return false;
+ return true;
+}
+
/// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module,
/// create and return an llvm GlobalVariable with the specified type. If there
/// is something in the module with the specified name, return it potentially
@@ -1554,8 +1547,7 @@
llvm::Constant *
CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
llvm::PointerType *Ty,
- const VarDecl *D,
- bool UnnamedAddr) {
+ const VarDecl *D) {
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
@@ -1564,9 +1556,6 @@
Entry->setLinkage(llvm::Function::ExternalLinkage);
}
- if (UnnamedAddr)
- Entry->setUnnamedAddr(true);
-
if (Entry->getType() == Ty)
return Entry;
@@ -1578,11 +1567,10 @@
}
unsigned AddrSpace = GetGlobalVarAddressSpace(D, Ty->getAddressSpace());
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(getModule(), Ty->getElementType(), false,
- llvm::GlobalValue::ExternalLinkage,
- 0, MangledName, 0,
- llvm::GlobalVariable::NotThreadLocal, AddrSpace);
+ auto *GV = new llvm::GlobalVariable(
+ getModule(), Ty->getElementType(), false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, MangledName, nullptr,
+ llvm::GlobalVariable::NotThreadLocal, AddrSpace);
// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
@@ -1601,21 +1589,7 @@
// handling.
GV->setConstant(isTypeConstant(D->getType(), false));
- // Set linkage and visibility in case we never see a definition.
- LinkageInfo LV = D->getLinkageAndVisibility();
- if (LV.getLinkage() != ExternalLinkage) {
- // Don't set internal linkage on declarations.
- } else {
- if (D->hasAttr<DLLImportAttr>()) {
- GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- } else if (D->hasAttr<WeakAttr>() || D->isWeakImported())
- GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
-
- // Set visibility on a declaration only if it's explicit.
- if (LV.isVisibilityExplicit())
- GV->setVisibility(GetLLVMVisibility(LV.getVisibility()));
- }
+ setLinkageAndVisibilityForGV(GV, D);
if (D->getTLSKind()) {
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
@@ -1626,19 +1600,21 @@
// If required by the ABI, treat declarations of static data members with
// inline initializers as definitions.
if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
- D->isStaticDataMember() && D->hasInit() &&
- !D->isThisDeclarationADefinition())
+ isVarDeclInlineInitializedStaticDataMember(D))
EmitGlobalVarDefinition(D);
+
+ // Handle XCore specific ABI requirements.
+ if (getTarget().getTriple().getArch() == llvm::Triple::xcore &&
+ D->getLanguageLinkage() == CLanguageLinkage &&
+ D->getType().isConstant(Context) &&
+ isExternallyVisible(D->getLinkageAndVisibility().getLinkage()))
+ GV->setSection(".cp.rodata");
}
if (AddrSpace != Ty->getAddressSpace())
return llvm::ConstantExpr::getAddrSpaceCast(GV, Ty);
- if (getTarget().getTriple().getArch() == llvm::Triple::xcore &&
- D->getLanguageLinkage() == CLanguageLinkage &&
- D->getType().isConstant(Context) &&
- isExternallyVisible(D->getLinkageAndVisibility().getLinkage()))
- GV->setSection(".cp.rodata");
+ getTargetCodeGenInfo().emitTargetMD(D, GV, *this);
return GV;
}
@@ -1649,9 +1625,8 @@
llvm::Type *Ty,
llvm::GlobalValue::LinkageTypes Linkage) {
llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name);
- llvm::GlobalVariable *OldGV = 0;
+ llvm::GlobalVariable *OldGV = nullptr;
-
if (GV) {
// Check if the variable has the right type.
if (GV->getType()->getElementType() == Ty)
@@ -1665,8 +1640,8 @@
// Create a new variable.
GV = new llvm::GlobalVariable(getModule(), Ty, /*isConstant=*/true,
- Linkage, 0, Name);
-
+ Linkage, nullptr, Name);
+
if (OldGV) {
// Replace occurrences of the old variable if needed.
GV->takeName(OldGV);
@@ -1691,7 +1666,7 @@
llvm::Type *Ty) {
assert(D->hasGlobalStorage() && "Not a global variable");
QualType ASTTy = D->getType();
- if (Ty == 0)
+ if (!Ty)
Ty = getTypes().ConvertTypeForMem(ASTTy);
llvm::PointerType *PTy =
@@ -1706,8 +1681,7 @@
llvm::Constant *
CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name) {
- return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0,
- true);
+ return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr);
}
void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
@@ -1777,11 +1751,11 @@
// If we have multiple internal linkage entities with the same name
// in extern "C" regions, none of them gets that name.
if (!R.second)
- R.first->second = 0;
+ R.first->second = nullptr;
}
void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
- llvm::Constant *Init = 0;
+ llvm::Constant *Init = nullptr;
QualType ASTTy = D->getType();
CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
bool NeedsGlobalCtor = false;
@@ -1831,7 +1805,7 @@
llvm::Constant *Entry = GetAddrOfGlobalVar(D, InitType);
// Strip off a bitcast if we got one back.
- if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
+ if (auto *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
assert(CE->getOpcode() == llvm::Instruction::BitCast ||
CE->getOpcode() == llvm::Instruction::AddrSpaceCast ||
// All zero index gep.
@@ -1840,7 +1814,7 @@
}
// Entry is now either a Function or GlobalVariable.
- llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Entry);
+ auto *GV = dyn_cast<llvm::GlobalVariable>(Entry);
// We have a definition after a declaration with the wrong type.
// We must make a new GlobalVariable* and update everything that used OldGV
@@ -1851,7 +1825,7 @@
// "extern int x[];") and then a definition of a different type (e.g.
// "int x[10];"). This also happens when an initializer has a different type
// from the type of the global (this happens with unions).
- if (GV == 0 ||
+ if (!GV ||
GV->getType()->getElementType() != InitType ||
GV->getType()->getAddressSpace() !=
GetGlobalVarAddressSpace(D, getContext().getTargetAddressSpace(ASTTy))) {
@@ -1885,26 +1859,19 @@
GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
// Set the llvm linkage type as appropriate.
- llvm::GlobalValue::LinkageTypes Linkage =
- GetLLVMLinkageVarDefinition(D, GV->isConstant());
+ llvm::GlobalValue::LinkageTypes Linkage =
+ getLLVMLinkageVarDefinition(D, GV->isConstant());
GV->setLinkage(Linkage);
if (D->hasAttr<DLLImportAttr>())
GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
else if (D->hasAttr<DLLExportAttr>())
GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
- // If required by the ABI, give definitions of static data members with inline
- // initializers linkonce_odr linkage.
- if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
- D->isStaticDataMember() && InitExpr &&
- !InitDecl->isThisDeclarationADefinition())
- GV->setLinkage(llvm::GlobalVariable::LinkOnceODRLinkage);
-
if (Linkage == llvm::GlobalVariable::CommonLinkage)
// common vars aren't constant even if declared const.
GV->setConstant(false);
- SetCommonAttributes(D, GV);
+ setNonAliasAttributes(D, GV);
// Emit the initializer function if necessary.
if (NeedsGlobalCtor || NeedsGlobalDtor)
@@ -1928,46 +1895,105 @@
DI->EmitGlobalVariable(GV, D);
}
-llvm::GlobalValue::LinkageTypes
-CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
- GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
+static bool isVarDeclStrongDefinition(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>())
+ return true;
+
+ // C11 6.9.2/2:
+ // A declaration of an identifier for an object that has file scope without
+ // an initializer, and without a storage-class specifier or with the
+ // storage-class specifier static, constitutes a tentative definition.
+ if (D->getInit() || D->hasExternalStorage())
+ return true;
+
+ // A variable cannot be both common and exist in a section.
+ if (D->hasAttr<SectionAttr>())
+ return true;
+
+ // Thread local vars aren't considered common linkage.
+ if (D->getTLSKind())
+ return true;
+
+ // Tentative definitions marked with WeakImportAttr are true definitions.
+ if (D->hasAttr<WeakImportAttr>())
+ return true;
+
+ return false;
+}
+
+llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator(
+ const DeclaratorDecl *D, GVALinkage Linkage, bool IsConstantVariable) {
if (Linkage == GVA_Internal)
return llvm::Function::InternalLinkage;
- else if (D->hasAttr<DLLImportAttr>())
- return llvm::Function::ExternalLinkage;
- else if (D->hasAttr<DLLExportAttr>())
- return llvm::Function::ExternalLinkage;
- else if (D->hasAttr<SelectAnyAttr>()) {
- // selectany symbols are externally visible, so use weak instead of
- // linkonce. MSVC optimizes away references to const selectany globals, so
- // all definitions should be the same and ODR linkage should be used.
- // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
- return llvm::GlobalVariable::WeakODRLinkage;
- } else if (D->hasAttr<WeakAttr>()) {
- if (isConstant)
+
+ if (D->hasAttr<WeakAttr>()) {
+ if (IsConstantVariable)
return llvm::GlobalVariable::WeakODRLinkage;
else
return llvm::GlobalVariable::WeakAnyLinkage;
- } else if (Linkage == GVA_TemplateInstantiation || Linkage == GVA_StrongODR)
- return llvm::GlobalVariable::WeakODRLinkage;
- else if (!getLangOpts().CPlusPlus &&
- ((!CodeGenOpts.NoCommon && !D->hasAttr<NoCommonAttr>()) ||
- D->hasAttr<CommonAttr>()) &&
- !D->hasExternalStorage() && !D->getInit() &&
- !D->hasAttr<SectionAttr>() && !D->getTLSKind() &&
- !D->hasAttr<WeakImportAttr>()) {
- // Thread local vars aren't considered common linkage.
+ }
+
+ // We are guaranteed to have a strong definition somewhere else,
+ // so we can use available_externally linkage.
+ if (Linkage == GVA_AvailableExternally)
+ return llvm::Function::AvailableExternallyLinkage;
+
+ // Note that Apple's kernel linker doesn't support symbol
+ // coalescing, so we need to avoid linkonce and weak linkages there.
+ // Normally, this means we just map to internal, but for explicit
+ // instantiations we'll map to external.
+
+ // In C++, the compiler has to emit a definition in every translation unit
+ // that references the function. We should use linkonce_odr because
+ // a) if all references in this translation unit are optimized away, we
+ // don't need to codegen it. b) if the function persists, it needs to be
+ // merged with other definitions. c) C++ has the ODR, so we know the
+ // definition is dependable.
+ if (Linkage == GVA_DiscardableODR)
+ return !Context.getLangOpts().AppleKext ? llvm::Function::LinkOnceODRLinkage
+ : llvm::Function::InternalLinkage;
+
+ // An explicit instantiation of a template has weak linkage, since
+ // explicit instantiations can occur in multiple translation units
+ // and must all be equivalent. However, we are not allowed to
+ // throw away these explicit instantiations.
+ if (Linkage == GVA_StrongODR)
+ return !Context.getLangOpts().AppleKext ? llvm::Function::WeakODRLinkage
+ : llvm::Function::ExternalLinkage;
+
+ // If required by the ABI, give definitions of static data members with inline
+ // initializers at least linkonce_odr linkage.
+ if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
+ isa<VarDecl>(D) &&
+ isVarDeclInlineInitializedStaticDataMember(cast<VarDecl>(D)))
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+
+ // C++ doesn't have tentative definitions and thus cannot have common
+ // linkage.
+ if (!getLangOpts().CPlusPlus && isa<VarDecl>(D) &&
+ !isVarDeclStrongDefinition(cast<VarDecl>(D), CodeGenOpts.NoCommon))
return llvm::GlobalVariable::CommonLinkage;
- } else if (D->getTLSKind() == VarDecl::TLS_Dynamic &&
- getTarget().getTriple().isMacOSX())
- // On Darwin, the backing variable for a C++11 thread_local variable always
- // has internal linkage; all accesses should just be calls to the
- // Itanium-specified entry point, which has the normal linkage of the
- // variable.
- return llvm::GlobalValue::InternalLinkage;
+
+ // selectany symbols are externally visible, so use weak instead of
+ // linkonce. MSVC optimizes away references to const selectany globals, so
+ // all definitions should be the same and ODR linkage should be used.
+ // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
+ if (D->hasAttr<SelectAnyAttr>())
+ return llvm::GlobalVariable::WeakODRLinkage;
+
+ // Otherwise, we have strong external linkage.
+ assert(Linkage == GVA_StrongExternal);
return llvm::GlobalVariable::ExternalLinkage;
}
+llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageVarDefinition(
+ const VarDecl *VD, bool IsConstant) {
+ GVALinkage Linkage = getContext().GetGVALinkageForVariable(VD);
+ return getLLVMLinkageForDeclarator(VD, Linkage, IsConstant);
+}
+
/// Replace the uses of a function that was declared with a non-proto type.
/// We want to silently drop extra arguments from call sites
static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
@@ -1985,7 +2011,7 @@
// Recognize and replace uses of bitcasts. Most calls to
// unprototyped functions will use bitcasts.
- if (llvm::ConstantExpr *bitcast = dyn_cast<llvm::ConstantExpr>(user)) {
+ if (auto *bitcast = dyn_cast<llvm::ConstantExpr>(user)) {
if (bitcast->getOpcode() == llvm::Instruction::BitCast)
replaceUsesOfNonProtoConstant(bitcast, newFn);
continue;
@@ -2049,8 +2075,7 @@
newCall = llvm::CallInst::Create(newFn, newArgs, "",
callSite.getInstruction());
} else {
- llvm::InvokeInst *oldInvoke =
- cast<llvm::InvokeInst>(callSite.getInstruction());
+ auto *oldInvoke = cast<llvm::InvokeInst>(callSite.getInstruction());
newCall = llvm::InvokeInst::Create(newFn,
oldInvoke->getNormalDest(),
oldInvoke->getUnwindDest(),
@@ -2105,34 +2130,34 @@
void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
llvm::GlobalValue *GV) {
- const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
+ const auto *D = cast<FunctionDecl>(GD.getDecl());
// Compute the function info and LLVM type.
const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
// Get or create the prototype for the function.
- llvm::Constant *Entry =
- GV ? GV
- : GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true);
+ if (!GV) {
+ llvm::Constant *C =
+ GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true);
- // Strip off a bitcast if we got one back.
- if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
- assert(CE->getOpcode() == llvm::Instruction::BitCast);
- Entry = CE->getOperand(0);
+ // Strip off a bitcast if we got one back.
+ if (auto *CE = dyn_cast<llvm::ConstantExpr>(C)) {
+ assert(CE->getOpcode() == llvm::Instruction::BitCast);
+ GV = cast<llvm::GlobalValue>(CE->getOperand(0));
+ } else {
+ GV = cast<llvm::GlobalValue>(C);
+ }
}
- if (!cast<llvm::GlobalValue>(Entry)->isDeclaration()) {
+ if (!GV->isDeclaration()) {
getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name);
return;
}
- if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() != Ty) {
- llvm::GlobalValue *OldFn = cast<llvm::GlobalValue>(Entry);
-
+ if (GV->getType()->getElementType() != Ty) {
// If the types mismatch then we have to rewrite the definition.
- assert(OldFn->isDeclaration() &&
- "Shouldn't replace non-declaration");
+ assert(GV->isDeclaration() && "Shouldn't replace non-declaration");
// F is the Function* for the one with the wrong type, we must make a new
// Function* and update everything that used F (a declaration) with the new
@@ -2142,8 +2167,8 @@
// (e.g. "int f()") and then a definition of a different type
// (e.g. "int f(int x)"). Move the old function aside so that it
// doesn't interfere with GetAddrOfFunction.
- OldFn->setName(StringRef());
- llvm::Function *NewFn = cast<llvm::Function>(GetAddrOfFunction(GD, Ty));
+ GV->setName(StringRef());
+ auto *NewFn = cast<llvm::Function>(GetAddrOfFunction(GD, Ty));
// This might be an implementation of a function without a
// prototype, in which case, try to do special replacement of
@@ -2152,39 +2177,39 @@
// so as to make a direct call, which makes the inliner happier
// and suppresses a number of optimizer warnings (!) about
// dropping arguments.
- if (!OldFn->use_empty()) {
- ReplaceUsesOfNonProtoTypeWithRealFunction(OldFn, NewFn);
- OldFn->removeDeadConstantUsers();
+ if (!GV->use_empty()) {
+ ReplaceUsesOfNonProtoTypeWithRealFunction(GV, NewFn);
+ GV->removeDeadConstantUsers();
}
// Replace uses of F with the Function we will endow with a body.
- if (!Entry->use_empty()) {
+ if (!GV->use_empty()) {
llvm::Constant *NewPtrForOldDecl =
- llvm::ConstantExpr::getBitCast(NewFn, Entry->getType());
- Entry->replaceAllUsesWith(NewPtrForOldDecl);
+ llvm::ConstantExpr::getBitCast(NewFn, GV->getType());
+ GV->replaceAllUsesWith(NewPtrForOldDecl);
}
// Ok, delete the old function now, which is dead.
- OldFn->eraseFromParent();
+ GV->eraseFromParent();
- Entry = NewFn;
+ GV = NewFn;
}
// We need to set linkage and visibility on the function before
// generating code for it because various parts of IR generation
// want to propagate this information down (e.g. to local static
// declarations).
- llvm::Function *Fn = cast<llvm::Function>(Entry);
+ auto *Fn = cast<llvm::Function>(GV);
setFunctionLinkage(GD, Fn);
- // FIXME: this is redundant with part of SetFunctionDefinitionAttributes
+ // FIXME: this is redundant with part of setFunctionDefinitionAttributes
setGlobalVisibility(Fn, D);
MaybeHandleStaticInExternC(D, Fn);
CodeGenFunction(*this).GenerateCode(D, Fn, FI);
- SetFunctionDefinitionAttributes(D, Fn);
+ setFunctionDefinitionAttributes(D, Fn);
SetLLVMFunctionAttributesForDefinition(D, Fn);
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
@@ -2193,14 +2218,33 @@
AddGlobalDtor(Fn, DA->getPriority());
if (D->hasAttr<AnnotateAttr>())
AddGlobalAnnotations(D, Fn);
+}
- llvm::Function *PGOInit = CodeGenPGO::emitInitialization(*this);
- if (PGOInit)
- AddGlobalCtor(PGOInit, 0);
+static llvm::GlobalObject &getGlobalObjectInExpr(DiagnosticsEngine &Diags,
+ const AliasAttr *AA,
+ llvm::Constant *C) {
+ if (auto *GO = dyn_cast<llvm::GlobalObject>(C))
+ return *GO;
+
+ auto *GA = dyn_cast<llvm::GlobalAlias>(C);
+ if (GA) {
+ if (GA->mayBeOverridden()) {
+ Diags.Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
+ << GA->getAliasee()->getName() << GA->getName();
+ }
+
+ return *GA->getAliasee();
+ }
+
+ auto *CE = cast<llvm::ConstantExpr>(C);
+ assert(CE->getOpcode() == llvm::Instruction::BitCast ||
+ CE->getOpcode() == llvm::Instruction::GetElementPtr ||
+ CE->getOpcode() == llvm::Instruction::AddrSpaceCast);
+ return *cast<llvm::GlobalObject>(CE->getOperand(0));
}
void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
- const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+ const auto *D = cast<ValueDecl>(GD.getDecl());
const AliasAttr *AA = D->getAttr<AliasAttr>();
assert(AA && "Not an alias?");
@@ -2224,15 +2268,21 @@
/*ForVTable=*/false);
else
Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
- llvm::PointerType::getUnqual(DeclTy), 0);
+ llvm::PointerType::getUnqual(DeclTy),
+ nullptr);
// Create the new alias itself, but don't set a name yet.
- llvm::GlobalValue *GA =
- new llvm::GlobalAlias(Aliasee->getType(),
- llvm::Function::ExternalLinkage,
- "", Aliasee, &getModule());
+ auto *GA = llvm::GlobalAlias::create(
+ cast<llvm::PointerType>(Aliasee->getType())->getElementType(), 0,
+ llvm::Function::ExternalLinkage, "",
+ &getGlobalObjectInExpr(Diags, AA, Aliasee));
if (Entry) {
+ if (GA->getAliasee() == Entry) {
+ Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
+ return;
+ }
+
assert(Entry->isDeclaration());
// If there is a declaration in the module, then we had an extern followed
@@ -2255,7 +2305,7 @@
// specialization of the attributes which may be set on a global
// variable/function.
if (D->hasAttr<DLLExportAttr>()) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// The dllexport attribute is ignored for undefined symbols.
if (FD->hasBody())
GA->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
@@ -2353,8 +2403,7 @@
QualType CFTy = getContext().getCFConstantStringType();
- llvm::StructType *STy =
- cast<llvm::StructType>(getTypes().ConvertType(CFTy));
+ auto *STy = cast<llvm::StructType>(getTypes().ConvertType(CFTy));
llvm::Constant *Fields[4];
@@ -2367,7 +2416,7 @@
llvm::ConstantInt::get(Ty, 0x07C8);
// String pointer.
- llvm::Constant *C = 0;
+ llvm::Constant *C = nullptr;
if (isUTF16) {
ArrayRef<uint16_t> Arr =
llvm::makeArrayRef<uint16_t>(reinterpret_cast<uint16_t*>(
@@ -2380,7 +2429,7 @@
// Note: -fwritable-strings doesn't make the backing store strings of
// CFStrings writable. (See <rdar://problem/10657500>)
- llvm::GlobalVariable *GV =
+ auto *GV =
new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/true,
llvm::GlobalValue::PrivateLinkage, C, ".str");
GV->setUnnamedAddr(true);
@@ -2479,9 +2528,9 @@
for (unsigned i = 0; i < 3; ++i) {
FieldDecl *Field = FieldDecl::Create(Context, D,
SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
+ SourceLocation(), nullptr,
+ FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit);
Field->setAccess(AS_public);
@@ -2506,10 +2555,9 @@
bool isConstant;
Linkage = llvm::GlobalValue::PrivateLinkage;
isConstant = !LangOpts.WritableStrings;
-
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C,
- ".str");
+
+ auto *GV = new llvm::GlobalVariable(getModule(), C->getType(), isConstant,
+ Linkage, C, ".str");
GV->setUnnamedAddr(true);
// Don't enforce the target's minimum global alignment, since the only use
// of the string is via this class initializer.
@@ -2555,9 +2603,9 @@
FieldDecl *Field = FieldDecl::Create(Context,
D,
SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
+ SourceLocation(), nullptr,
+ FieldTypes[i], /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit);
Field->setAccess(AS_public);
@@ -2585,9 +2633,8 @@
Str.resize(CAT->getSize().getZExtValue());
return llvm::ConstantDataArray::getString(VMContext, Str, false);
}
-
- llvm::ArrayType *AType =
- cast<llvm::ArrayType>(getTypes().ConvertType(E->getType()));
+
+ auto *AType = cast<llvm::ArrayType>(getTypes().ConvertType(E->getType()));
llvm::Type *ElemTy = AType->getElementType();
unsigned NumElements = AType->getNumElements();
@@ -2656,7 +2703,7 @@
LT = llvm::GlobalValue::LinkOnceODRLinkage;
GlobalVariableName = MangledNameBuffer;
} else {
- LT = llvm::GlobalValue::PrivateLinkage;;
+ LT = llvm::GlobalValue::PrivateLinkage;
GlobalVariableName = ".str";
}
@@ -2708,9 +2755,9 @@
AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
// Create a global variable for this string
- llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ auto *GV = new llvm::GlobalVariable(
CGM.getModule(), C->getType(), constant,
- llvm::GlobalValue::PrivateLinkage, C, GlobalName, 0,
+ llvm::GlobalValue::PrivateLinkage, C, GlobalName, nullptr,
llvm::GlobalVariable::NotThreadLocal, AddrSpace);
GV->setAlignment(Alignment);
GV->setUnnamedAddr(true);
@@ -2771,7 +2818,7 @@
const MaterializeTemporaryExpr *E, const Expr *Init) {
assert((E->getStorageDuration() == SD_Static ||
E->getStorageDuration() == SD_Thread) && "not a global temporary");
- const VarDecl *VD = cast<VarDecl>(E->getExtendingDecl());
+ const auto *VD = cast<VarDecl>(E->getExtendingDecl());
// If we're not materializing a subobject of the temporary, keep the
// cv-qualifiers from the type of the MaterializeTemporaryExpr.
@@ -2788,10 +2835,11 @@
// we also need to make the temporaries externally-visible).
SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
- getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out);
+ getCXXABI().getMangleContext().mangleReferenceTemporary(
+ VD, E->getManglingNumber(), Out);
Out.flush();
- APValue *Value = 0;
+ APValue *Value = nullptr;
if (E->getStorageDuration() == SD_Static) {
// We might have a cached constant initializer for this temporary. Note
// that this might have a different value from the value computed by
@@ -2799,7 +2847,7 @@
// modifies the temporary.
Value = getContext().getMaterializedTemporaryValue(E, false);
if (Value && Value->isUninit())
- Value = 0;
+ Value = nullptr;
}
// Try evaluating it now, it might have a constant initializer.
@@ -2808,12 +2856,12 @@
!EvalResult.hasSideEffects())
Value = &EvalResult.Val;
- llvm::Constant *InitialValue = 0;
+ llvm::Constant *InitialValue = nullptr;
bool Constant = false;
llvm::Type *Type;
if (Value) {
// The temporary has a constant initializer, use it.
- InitialValue = EmitConstantValue(*Value, MaterializedType, 0);
+ InitialValue = EmitConstantValue(*Value, MaterializedType, nullptr);
Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value);
Type = InitialValue->getType();
} else {
@@ -2823,10 +2871,19 @@
}
// Create a global variable for this lifetime-extended temporary.
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(getModule(), Type, Constant,
- llvm::GlobalValue::PrivateLinkage,
- InitialValue, Name.c_str());
+ llvm::GlobalValue::LinkageTypes Linkage =
+ getLLVMLinkageVarDefinition(VD, Constant);
+ // There is no need for this temporary to have global linkage if the global
+ // variable has external linkage.
+ if (Linkage == llvm::GlobalVariable::ExternalLinkage)
+ Linkage = llvm::GlobalVariable::PrivateLinkage;
+ unsigned AddrSpace = GetGlobalVarAddressSpace(
+ VD, getContext().getTargetAddressSpace(MaterializedType));
+ auto *GV = new llvm::GlobalVariable(
+ getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(),
+ /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal,
+ AddrSpace);
+ setGlobalVisibility(GV, VD);
GV->setAlignment(
getContext().getTypeAlignInChars(MaterializedType).getQuantity());
if (VD->getTLSKind())
@@ -2879,7 +2936,7 @@
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
ObjCMethodDecl *DTORMethod =
ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(),
- cxxSelector, getContext().VoidTy, 0, D,
+ cxxSelector, getContext().VoidTy, nullptr, D,
/*isInstance=*/true, /*isVariadic=*/false,
/*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true,
/*isDefined=*/false, ObjCMethodDecl::Required);
@@ -2900,8 +2957,8 @@
D->getLocation(),
D->getLocation(),
cxxSelector,
- getContext().getObjCIdType(), 0,
- D, /*isInstance=*/true,
+ getContext().getObjCIdType(),
+ nullptr, D, /*isInstance=*/true,
/*isVariadic=*/false,
/*isPropertyAccessor=*/true,
/*isImplicitlyDeclared=*/true,
@@ -3025,7 +3082,7 @@
break;
case Decl::ObjCProtocol: {
- ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(D);
+ auto *Proto = cast<ObjCProtocolDecl>(D);
if (Proto->isThisDeclarationADefinition())
ObjCRuntime->GenerateProtocol(Proto);
break;
@@ -3038,7 +3095,7 @@
break;
case Decl::ObjCImplementation: {
- ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
+ auto *OMD = cast<ObjCImplementationDecl>(D);
EmitObjCPropertyImplementations(OMD);
EmitObjCIvarInitializations(OMD);
ObjCRuntime->GenerateClass(OMD);
@@ -3050,7 +3107,7 @@
break;
}
case Decl::ObjCMethod: {
- ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D);
+ auto *OMD = cast<ObjCMethodDecl>(D);
// If this is not a prototype, emit the body.
if (OMD->getBody())
CodeGenFunction(*this).GenerateObjCMethod(OMD);
@@ -3065,7 +3122,7 @@
break;
case Decl::FileScopeAsm: {
- FileScopeAsmDecl *AD = cast<FileScopeAsmDecl>(D);
+ auto *AD = cast<FileScopeAsmDecl>(D);
StringRef AsmString = AD->getAsmString()->getString();
const std::string &S = getModule().getModuleInlineAsm();
@@ -3079,7 +3136,7 @@
}
case Decl::Import: {
- ImportDecl *Import = cast<ImportDecl>(D);
+ auto *Import = cast<ImportDecl>(D);
// Ignore import declarations that come from imported modules.
if (clang::Module *Owner = Import->getOwningModule()) {
@@ -3093,8 +3150,7 @@
}
case Decl::ClassTemplateSpecialization: {
- const ClassTemplateSpecializationDecl *Spec =
- cast<ClassTemplateSpecializationDecl>(D);
+ const auto *Spec = cast<ClassTemplateSpecializationDecl>(D);
if (DebugInfo &&
Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition)
DebugInfo->completeTemplateDefinition(*Spec);
@@ -3144,8 +3200,8 @@
IdentifierInfo *Name = I->first;
llvm::GlobalValue *Val = I->second;
if (Val && !getModule().getNamedValue(Name->getName()))
- addUsedGlobal(new llvm::GlobalAlias(Val->getType(), Val->getLinkage(),
- Name->getName(), Val, &getModule()));
+ addUsedGlobal(llvm::GlobalAlias::create(Name->getName(),
+ cast<llvm::GlobalObject>(Val)));
}
}
@@ -3157,7 +3213,7 @@
/// with an llvm::GlobalValue, we create a global named metadata
/// with the name 'clang.global.decl.ptrs'.
void CodeGenModule::EmitDeclMetadata() {
- llvm::NamedMDNode *GlobalMetadata = 0;
+ llvm::NamedMDNode *GlobalMetadata = nullptr;
// StaticLocalDeclMap
for (llvm::DenseMap<GlobalDecl,StringRef>::iterator
@@ -3178,17 +3234,17 @@
// Find the unique metadata ID for this name.
unsigned DeclPtrKind = Context.getMDKindID("clang.decl.ptr");
- llvm::NamedMDNode *GlobalMetadata = 0;
+ llvm::NamedMDNode *GlobalMetadata = nullptr;
for (llvm::DenseMap<const Decl*, llvm::Value*>::iterator
I = LocalDeclMap.begin(), E = LocalDeclMap.end(); I != E; ++I) {
const Decl *D = I->first;
llvm::Value *Addr = I->second;
- if (llvm::AllocaInst *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
+ if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D);
Alloca->setMetadata(DeclPtrKind, llvm::MDNode::get(Context, DAddr));
- } else if (llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(Addr)) {
+ } else if (auto *GV = dyn_cast<llvm::GlobalValue>(Addr)) {
GlobalDecl GD = GlobalDecl(cast<VarDecl>(D));
EmitGlobalDeclMetadata(CGM, GlobalMetadata, GD, GV);
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 0d13bdc..c54f6de 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -34,124 +34,122 @@
#include "llvm/Transforms/Utils/SpecialCaseList.h"
namespace llvm {
- class Module;
- class Constant;
- class ConstantInt;
- class Function;
- class GlobalValue;
- class DataLayout;
- class FunctionType;
- class LLVMContext;
+class Module;
+class Constant;
+class ConstantInt;
+class Function;
+class GlobalValue;
+class DataLayout;
+class FunctionType;
+class LLVMContext;
+class IndexedInstrProfReader;
}
namespace clang {
- class TargetCodeGenInfo;
- class ASTContext;
- class AtomicType;
- class FunctionDecl;
- class IdentifierInfo;
- class ObjCMethodDecl;
- class ObjCImplementationDecl;
- class ObjCCategoryImplDecl;
- class ObjCProtocolDecl;
- class ObjCEncodeExpr;
- class BlockExpr;
- class CharUnits;
- class Decl;
- class Expr;
- class Stmt;
- class InitListExpr;
- class StringLiteral;
- class NamedDecl;
- class ValueDecl;
- class VarDecl;
- class LangOptions;
- class CodeGenOptions;
- class DiagnosticsEngine;
- class AnnotateAttr;
- class CXXDestructorDecl;
- class MangleBuffer;
- class Module;
+class TargetCodeGenInfo;
+class ASTContext;
+class AtomicType;
+class FunctionDecl;
+class IdentifierInfo;
+class ObjCMethodDecl;
+class ObjCImplementationDecl;
+class ObjCCategoryImplDecl;
+class ObjCProtocolDecl;
+class ObjCEncodeExpr;
+class BlockExpr;
+class CharUnits;
+class Decl;
+class Expr;
+class Stmt;
+class InitListExpr;
+class StringLiteral;
+class NamedDecl;
+class ValueDecl;
+class VarDecl;
+class LangOptions;
+class CodeGenOptions;
+class DiagnosticsEngine;
+class AnnotateAttr;
+class CXXDestructorDecl;
+class MangleBuffer;
+class Module;
namespace CodeGen {
- class CallArgList;
- class CodeGenFunction;
- class CodeGenTBAA;
- class CGCXXABI;
- class CGDebugInfo;
- class CGObjCRuntime;
- class CGOpenCLRuntime;
- class CGCUDARuntime;
- class BlockFieldFlags;
- class FunctionArgList;
- class PGOProfileData;
+class CallArgList;
+class CodeGenFunction;
+class CodeGenTBAA;
+class CGCXXABI;
+class CGDebugInfo;
+class CGObjCRuntime;
+class CGOpenCLRuntime;
+class CGOpenMPRuntime;
+class CGCUDARuntime;
+class BlockFieldFlags;
+class FunctionArgList;
- struct OrderGlobalInits {
- unsigned int priority;
- unsigned int lex_order;
- OrderGlobalInits(unsigned int p, unsigned int l)
+struct OrderGlobalInits {
+ unsigned int priority;
+ unsigned int lex_order;
+ OrderGlobalInits(unsigned int p, unsigned int l)
: priority(p), lex_order(l) {}
-
- bool operator==(const OrderGlobalInits &RHS) const {
- return priority == RHS.priority &&
- lex_order == RHS.lex_order;
- }
-
- bool operator<(const OrderGlobalInits &RHS) const {
- return std::tie(priority, lex_order) <
- std::tie(RHS.priority, RHS.lex_order);
- }
+
+ bool operator==(const OrderGlobalInits &RHS) const {
+ return priority == RHS.priority && lex_order == RHS.lex_order;
+ }
+
+ bool operator<(const OrderGlobalInits &RHS) const {
+ return std::tie(priority, lex_order) <
+ std::tie(RHS.priority, RHS.lex_order);
+ }
+};
+
+struct CodeGenTypeCache {
+ /// void
+ llvm::Type *VoidTy;
+
+ /// i8, i16, i32, and i64
+ llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty;
+ /// float, double
+ llvm::Type *FloatTy, *DoubleTy;
+
+ /// int
+ llvm::IntegerType *IntTy;
+
+ /// intptr_t, size_t, and ptrdiff_t, which we assume are the same size.
+ union {
+ llvm::IntegerType *IntPtrTy;
+ llvm::IntegerType *SizeTy;
+ llvm::IntegerType *PtrDiffTy;
};
- struct CodeGenTypeCache {
- /// void
- llvm::Type *VoidTy;
-
- /// i8, i16, i32, and i64
- llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty;
- /// float, double
- llvm::Type *FloatTy, *DoubleTy;
-
- /// int
- llvm::IntegerType *IntTy;
-
- /// intptr_t, size_t, and ptrdiff_t, which we assume are the same size.
- union {
- llvm::IntegerType *IntPtrTy;
- llvm::IntegerType *SizeTy;
- llvm::IntegerType *PtrDiffTy;
- };
-
- /// void* in address space 0
- union {
- llvm::PointerType *VoidPtrTy;
- llvm::PointerType *Int8PtrTy;
- };
-
- /// void** in address space 0
- union {
- llvm::PointerType *VoidPtrPtrTy;
- llvm::PointerType *Int8PtrPtrTy;
- };
-
- /// The width of a pointer into the generic address space.
- unsigned char PointerWidthInBits;
-
- /// The size and alignment of a pointer into the generic address
- /// space.
- union {
- unsigned char PointerAlignInBytes;
- unsigned char PointerSizeInBytes;
- unsigned char SizeSizeInBytes; // sizeof(size_t)
- };
-
- llvm::CallingConv::ID RuntimeCC;
- llvm::CallingConv::ID getRuntimeCC() const {
- return RuntimeCC;
- }
+ /// void* in address space 0
+ union {
+ llvm::PointerType *VoidPtrTy;
+ llvm::PointerType *Int8PtrTy;
};
+ /// void** in address space 0
+ union {
+ llvm::PointerType *VoidPtrPtrTy;
+ llvm::PointerType *Int8PtrPtrTy;
+ };
+
+ /// The width of a pointer into the generic address space.
+ unsigned char PointerWidthInBits;
+
+ /// The size and alignment of a pointer into the generic address
+ /// space.
+ union {
+ unsigned char PointerAlignInBytes;
+ unsigned char PointerSizeInBytes;
+ unsigned char SizeSizeInBytes; // sizeof(size_t)
+ };
+
+ llvm::CallingConv::ID RuntimeCC;
+ llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
+};
+
struct RREntrypoints {
RREntrypoints() { memset(this, 0, sizeof(*this)); }
/// void objc_autoreleasePoolPop(void*);
@@ -220,13 +218,33 @@
llvm::Constant *clang_arc_use;
};
-/// CodeGenModule - This class organizes the cross-function state that is used
-/// while generating LLVM code.
+/// This class records statistics on instrumentation based profiling.
+struct InstrProfStats {
+ InstrProfStats() : Visited(0), Missing(0), Mismatched(0) {}
+ bool isOutOfDate() { return Missing || Mismatched; }
+ uint32_t Visited;
+ uint32_t Missing;
+ uint32_t Mismatched;
+};
+
+/// This class organizes the cross-function state that is used while generating
+/// LLVM code.
class CodeGenModule : public CodeGenTypeCache {
CodeGenModule(const CodeGenModule &) LLVM_DELETED_FUNCTION;
void operator=(const CodeGenModule &) LLVM_DELETED_FUNCTION;
- typedef std::vector<std::pair<llvm::Constant*, int> > CtorList;
+ struct Structor {
+ Structor() : Priority(0), Initializer(nullptr), AssociatedData(nullptr) {}
+ Structor(int Priority, llvm::Constant *Initializer,
+ llvm::Constant *AssociatedData)
+ : Priority(Priority), Initializer(Initializer),
+ AssociatedData(AssociatedData) {}
+ int Priority;
+ llvm::Constant *Initializer;
+ llvm::Constant *AssociatedData;
+ };
+
+ typedef std::vector<Structor> CtorList;
ASTContext &Context;
const LangOptions &LangOpts;
@@ -247,32 +265,33 @@
// if TheTargetCodeGenInfo is NULL
CodeGenTypes Types;
- /// VTables - Holds information about C++ vtables.
+ /// Holds information about C++ vtables.
CodeGenVTables VTables;
CGObjCRuntime* ObjCRuntime;
CGOpenCLRuntime* OpenCLRuntime;
+ CGOpenMPRuntime* OpenMPRuntime;
CGCUDARuntime* CUDARuntime;
CGDebugInfo* DebugInfo;
ARCEntrypoints *ARCData;
llvm::MDNode *NoObjCARCExceptionsMetadata;
RREntrypoints *RRData;
- PGOProfileData *PGOData;
+ std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
+ InstrProfStats PGOStats;
- // WeakRefReferences - A set of references that have only been seen via
- // a weakref so far. This is used to remove the weak of the reference if we
- // ever see a direct reference or a definition.
+ // A set of references that have only been seen via a weakref so far. This is
+ // used to remove the weak of the reference if we ever see a direct reference
+ // or a definition.
llvm::SmallPtrSet<llvm::GlobalValue*, 10> WeakRefReferences;
- /// DeferredDecls - This contains all the decls which have definitions but
- /// which are deferred for emission and therefore should only be output if
- /// they are actually used. If a decl is in this, then it is known to have
- /// not been referenced yet.
+ /// This contains all the decls which have definitions but/ which are deferred
+ /// for emission and therefore should only be output if they are actually
+ /// used. If a decl is in this, then it is known to have not been referenced
+ /// yet.
llvm::StringMap<GlobalDecl> DeferredDecls;
- /// DeferredDeclsToEmit - This is a list of deferred decls which we have seen
- /// that *are* actually referenced. These get code generated when the module
- /// is done.
+ /// This is a list of deferred decls which we have seen that *are* actually
+ /// referenced. These get code generated when the module is done.
struct DeferredGlobal {
DeferredGlobal(llvm::GlobalValue *GV, GlobalDecl GD) : GV(GV), GD(GD) {}
llvm::AssertingVH<llvm::GlobalValue> GV;
@@ -290,25 +309,24 @@
typedef llvm::StringMap<llvm::TrackingVH<llvm::Constant> > ReplacementsTy;
ReplacementsTy Replacements;
- /// DeferredVTables - A queue of (optional) vtables to consider emitting.
+ /// A queue of (optional) vtables to consider emitting.
std::vector<const CXXRecordDecl*> DeferredVTables;
- /// LLVMUsed - List of global values which are required to be
- /// present in the object file; bitcast to i8*. This is used for
- /// forcing visibility of symbols which may otherwise be optimized
- /// out.
+ /// List of global values which are required to be present in the object file;
+ /// bitcast to i8*. This is used for forcing visibility of symbols which may
+ /// otherwise be optimized out.
std::vector<llvm::WeakVH> LLVMUsed;
std::vector<llvm::WeakVH> LLVMCompilerUsed;
- /// GlobalCtors - Store the list of global constructors and their respective
- /// priorities to be emitted when the translation unit is complete.
+ /// Store the list of global constructors and their respective priorities to
+ /// be emitted when the translation unit is complete.
CtorList GlobalCtors;
- /// GlobalDtors - Store the list of global destructors and their respective
- /// priorities to be emitted when the translation unit is complete.
+ /// Store the list of global destructors and their respective priorities to be
+ /// emitted when the translation unit is complete.
CtorList GlobalDtors;
- /// MangledDeclNames - A map of canonical GlobalDecls to their mangled names.
+ /// A map of canonical GlobalDecls to their mangled names.
llvm::DenseMap<GlobalDecl, StringRef> MangledDeclNames;
llvm::BumpPtrAllocator MangledNamesAllocator;
@@ -347,8 +365,7 @@
/// before any thread_local variable in this TU is odr-used.
std::vector<llvm::Constant*> CXXThreadLocalInits;
- /// CXXGlobalInits - Global variables with initializers that need to run
- /// before main.
+ /// Global variables with initializers that need to run before main.
std::vector<llvm::Constant*> CXXGlobalInits;
/// When a C++ decl with an initializer is deferred, null is
@@ -366,12 +383,11 @@
}
};
- /// - Global variables with initializers whose order of initialization
- /// is set by init_priority attribute.
+ /// Global variables with initializers whose order of initialization is set by
+ /// init_priority attribute.
SmallVector<GlobalInitData, 8> PrioritizedCXXGlobalInits;
- /// CXXGlobalDtors - Global destructor functions and arguments that need to
- /// run on termination.
+ /// Global destructor functions and arguments that need to run on termination.
std::vector<std::pair<llvm::WeakVH,llvm::Constant*> > CXXGlobalDtors;
/// \brief The complete set of modules that has been imported.
@@ -383,12 +399,12 @@
/// @name Cache for Objective-C runtime types
/// @{
- /// CFConstantStringClassRef - Cached reference to the class for constant
- /// strings. This value has type int * but is actually an Obj-C class pointer.
+ /// Cached reference to the class for constant strings. This value has type
+ /// int * but is actually an Obj-C class pointer.
llvm::WeakVH CFConstantStringClassRef;
- /// ConstantStringClassRef - Cached reference to the class for constant
- /// strings. This value has type int * but is actually an Obj-C class pointer.
+ /// Cached reference to the class for constant strings. This value has type
+ /// int * but is actually an Obj-C class pointer.
llvm::WeakVH ConstantStringClassRef;
/// \brief The LLVM type corresponding to NSConstantString.
@@ -404,6 +420,7 @@
void createObjCRuntime();
void createOpenCLRuntime();
+ void createOpenMPRuntime();
void createCUDARuntime();
bool isTriviallyRecursive(const FunctionDecl *F);
@@ -447,45 +464,48 @@
void clear();
- /// Release - Finalize LLVM code generation.
+ /// Finalize LLVM code generation.
void Release();
- /// getObjCRuntime() - Return a reference to the configured
- /// Objective-C runtime.
+ /// Return a reference to the configured Objective-C runtime.
CGObjCRuntime &getObjCRuntime() {
if (!ObjCRuntime) createObjCRuntime();
return *ObjCRuntime;
}
- /// hasObjCRuntime() - Return true iff an Objective-C runtime has
- /// been configured.
+ /// Return true iff an Objective-C runtime has been configured.
bool hasObjCRuntime() { return !!ObjCRuntime; }
- /// getOpenCLRuntime() - Return a reference to the configured OpenCL runtime.
+ /// Return a reference to the configured OpenCL runtime.
CGOpenCLRuntime &getOpenCLRuntime() {
- assert(OpenCLRuntime != 0);
+ assert(OpenCLRuntime != nullptr);
return *OpenCLRuntime;
}
- /// getCUDARuntime() - Return a reference to the configured CUDA runtime.
+ /// Return a reference to the configured OpenMP runtime.
+ CGOpenMPRuntime &getOpenMPRuntime() {
+ assert(OpenMPRuntime != nullptr);
+ return *OpenMPRuntime;
+ }
+
+ /// Return a reference to the configured CUDA runtime.
CGCUDARuntime &getCUDARuntime() {
- assert(CUDARuntime != 0);
+ assert(CUDARuntime != nullptr);
return *CUDARuntime;
}
ARCEntrypoints &getARCEntrypoints() const {
- assert(getLangOpts().ObjCAutoRefCount && ARCData != 0);
+ assert(getLangOpts().ObjCAutoRefCount && ARCData != nullptr);
return *ARCData;
}
RREntrypoints &getRREntrypoints() const {
- assert(RRData != 0);
+ assert(RRData != nullptr);
return *RRData;
}
- PGOProfileData *getPGOData() const {
- return PGOData;
- }
+ InstrProfStats &getPGOStats() { return PGOStats; }
+ llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); }
llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
return StaticLocalDeclMap[D];
@@ -519,10 +539,10 @@
AtomicGetterHelperFnMap[Ty] = Fn;
}
- llvm::Constant *getTypeDescriptor(QualType Ty) {
+ llvm::Constant *getTypeDescriptorFromMap(QualType Ty) {
return TypeDescriptorMap[Ty];
}
- void setTypeDescriptor(QualType Ty, llvm::Constant *C) {
+ void setTypeDescriptorInMap(QualType Ty, llvm::Constant *C) {
TypeDescriptorMap[Ty] = C;
}
@@ -545,8 +565,8 @@
const TargetInfo &getTarget() const { return Target; }
CGCXXABI &getCXXABI() const { return *ABI; }
llvm::LLVMContext &getLLVMContext() { return VMContext; }
-
- bool shouldUseTBAA() const { return TBAA != 0; }
+
+ bool shouldUseTBAA() const { return TBAA != nullptr; }
const TargetCodeGenInfo &getTargetCodeGenInfo();
@@ -584,15 +604,14 @@
llvm::MDNode *TBAAInfo,
bool ConvertTypeToTag = true);
- /// getSize - Emit the given number of characters as a value of type size_t.
+ /// Emit the given number of characters as a value of type size_t.
llvm::ConstantInt *getSize(CharUnits numChars);
- /// setGlobalVisibility - Set the visibility for the given LLVM
- /// GlobalValue.
+ /// Set the visibility for the given LLVM GlobalValue.
void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
- /// setTLSMode - Set the TLS mode for the given LLVM GlobalVariable
- /// for the thread-local variable declaration D.
+ /// Set the TLS mode for the given LLVM GlobalVariable for the thread-local
+ /// variable declaration D.
void setTLSMode(llvm::GlobalVariable *GV, const VarDecl &D) const;
static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V) {
@@ -617,50 +636,47 @@
return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl()));
}
- /// CreateOrReplaceCXXRuntimeVariable - Will return a global variable of the
- /// given type. If a variable with a different type already exists then a new
- /// variable with the right type will be created and all uses of the old
- /// variable will be replaced with a bitcast to the new variable.
+ /// Will return a global variable of the given type. If a variable with a
+ /// different type already exists then a new variable with the right type
+ /// will be created and all uses of the old variable will be replaced with a
+ /// bitcast to the new variable.
llvm::GlobalVariable *
CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty,
llvm::GlobalValue::LinkageTypes Linkage);
- /// GetGlobalVarAddressSpace - Return the address space of the underlying
- /// global variable for D, as determined by its declaration. Normally this
- /// is the same as the address space of D's type, but in CUDA, address spaces
- /// are associated with declarations, not types.
+ /// Return the address space of the underlying global variable for D, as
+ /// determined by its declaration. Normally this is the same as the address
+ /// space of D's type, but in CUDA, address spaces are associated with
+ /// declarations, not types.
unsigned GetGlobalVarAddressSpace(const VarDecl *D, unsigned AddrSpace);
- /// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
- /// given global variable. If Ty is non-null and if the global doesn't exist,
- /// then it will be greated with the specified type instead of whatever the
- /// normal requested type would be.
+ /// Return the llvm::Constant for the address of the given global variable.
+ /// If Ty is non-null and if the global doesn't exist, then it will be greated
+ /// with the specified type instead of whatever the normal requested type
+ /// would be.
llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D,
- llvm::Type *Ty = 0);
+ llvm::Type *Ty = nullptr);
-
- /// GetAddrOfFunction - Return the address of the given function. If Ty is
- /// non-null, then this function will use the specified type if it has to
- /// create it.
+ /// Return the address of the given function. If Ty is non-null, then this
+ /// function will use the specified type if it has to create it.
llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = 0,
bool ForVTable = false,
bool DontDefer = false);
- /// GetAddrOfRTTIDescriptor - Get the address of the RTTI descriptor
- /// for the given type.
+ /// Get the address of the RTTI descriptor for the given type.
llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
- /// GetAddrOfUuidDescriptor - Get the address of a uuid descriptor .
+ /// Get the address of a uuid descriptor .
llvm::Constant *GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);
- /// GetAddrOfThunk - Get the address of the thunk for the given global decl.
+ /// Get the address of the thunk for the given global decl.
llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkInfo &Thunk);
- /// GetWeakRefReference - Get a reference to the target of VD.
+ /// Get a reference to the target of VD.
llvm::Constant *GetWeakRefReference(const ValueDecl *VD);
- /// GetNonVirtualBaseClassOffset - Returns the offset from a derived class to
- /// a class. Returns null if the offset is 0.
+ /// Returns the offset from a derived class to a class. Returns null if the
+ /// offset is 0.
llvm::Constant *
GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
CastExpr::path_const_iterator PathBegin,
@@ -696,67 +712,66 @@
llvm::FoldingSet<ByrefHelpers> ByrefHelpersCache;
- /// getUniqueBlockCount - Fetches the global unique block count.
+ /// Fetches the global unique block count.
int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; }
- /// getBlockDescriptorType - Fetches the type of a generic block
- /// descriptor.
+ /// Fetches the type of a generic block descriptor.
llvm::Type *getBlockDescriptorType();
- /// getGenericBlockLiteralType - The type of a generic block literal.
+ /// The type of a generic block literal.
llvm::Type *getGenericBlockLiteralType();
- /// GetAddrOfGlobalBlock - Gets the address of a block which
- /// requires no captures.
+ /// \brief Gets or a creats a Microsoft TypeDescriptor.
+ llvm::Constant *getMSTypeDescriptor(QualType Ty);
+ /// \brief Gets or a creats a Microsoft CompleteObjectLocator.
+ llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,
+ const VPtrInfo *Info);
+
+ /// Gets the address of a block which requires no captures.
llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
- /// GetAddrOfConstantCFString - Return a pointer to a constant CFString object
- /// for the given string.
+ /// Return a pointer to a constant CFString object for the given string.
llvm::Constant *GetAddrOfConstantCFString(const StringLiteral *Literal);
-
- /// GetAddrOfConstantString - Return a pointer to a constant NSString object
- /// for the given string. Or a user defined String object as defined via
+
+ /// 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);
- /// GetConstantArrayFromStringLiteral - Return a constant array for the given
- /// string.
+ /// Return a constant array for the given string.
llvm::Constant *GetConstantArrayFromStringLiteral(const StringLiteral *E);
- /// GetAddrOfConstantStringFromLiteral - Return a pointer to a constant array
- /// for the given string literal.
+ /// Return a pointer to a constant array for the given string literal.
llvm::Constant *GetAddrOfConstantStringFromLiteral(const StringLiteral *S);
- /// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
- /// array for the given ObjCEncodeExpr node.
+ /// Return a pointer to a constant array for the given ObjCEncodeExpr node.
llvm::Constant *GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *);
- /// GetAddrOfConstantString - Returns a pointer to a character array
- /// containing the literal. This contents are exactly that of the given
- /// string, i.e. it will not be null terminated automatically; see
- /// GetAddrOfConstantCString. Note that whether the result is actually a
- /// pointer to an LLVM constant depends on Feature.WriteableStrings.
+ /// Returns a pointer to a character array containing the literal. This
+ /// contents are exactly that of the given string, i.e. it will not be null
+ /// terminated automatically; see GetAddrOfConstantCString. Note that whether
+ /// the result is actually a pointer to an LLVM constant depends on
+ /// Feature.WriteableStrings.
///
/// The result has pointer to array type.
///
/// \param GlobalName If provided, the name to use for the global
/// (if one is created).
llvm::Constant *GetAddrOfConstantString(StringRef Str,
- const char *GlobalName=0,
+ const char *GlobalName=nullptr,
unsigned Alignment=0);
- /// GetAddrOfConstantCString - Returns a pointer to a character array
- /// containing the literal and a terminating '\0' character. The result has
- /// pointer to array type.
+ /// Returns a pointer to a character array containing the literal and a
+ /// terminating '\0' character. The result has pointer to array type.
///
/// \param GlobalName If provided, the name to use for the global (if one is
/// created).
llvm::Constant *GetAddrOfConstantCString(const std::string &str,
- const char *GlobalName=0,
+ const char *GlobalName=nullptr,
unsigned Alignment=0);
- /// GetAddrOfConstantCompoundLiteral - Returns a pointer to a constant global
- /// variable for the given file-scope compound literal expression.
+ /// Returns a pointer to a constant global variable for the given file-scope
+ /// compound literal expression.
llvm::Constant *GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr*E);
/// \brief Returns a pointer to a global variable representing a temporary
@@ -768,33 +783,31 @@
/// Objective-C fast enumeration loop (for..in).
QualType getObjCFastEnumerationStateType();
- /// GetAddrOfCXXConstructor - Return the address of the constructor of the
- /// given type.
- llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor,
- CXXCtorType ctorType,
- const CGFunctionInfo *fnInfo = 0,
- bool DontDefer = false);
+ /// Return the address of the constructor of the given type.
+ llvm::GlobalValue *
+ GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, CXXCtorType ctorType,
+ const CGFunctionInfo *fnInfo = nullptr,
+ bool DontDefer = false);
- /// GetAddrOfCXXDestructor - Return the address of the constructor of the
- /// given type.
- llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
- CXXDtorType dtorType,
- const CGFunctionInfo *fnInfo = 0,
- llvm::FunctionType *fnType = 0,
- bool DontDefer = false);
+ /// Return the address of the constructor of the given type.
+ llvm::GlobalValue *
+ GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
+ CXXDtorType dtorType,
+ const CGFunctionInfo *fnInfo = nullptr,
+ llvm::FunctionType *fnType = nullptr,
+ bool DontDefer = false);
- /// getBuiltinLibFunction - Given a builtin id for a function like
- /// "__builtin_fabsf", return a Function* for "fabsf".
+ /// Given a builtin id for a function like "__builtin_fabsf", return a
+ /// Function* for "fabsf".
llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD,
unsigned BuiltinID);
llvm::Function *getIntrinsic(unsigned IID, ArrayRef<llvm::Type*> Tys = None);
- /// EmitTopLevelDecl - Emit code for a single top level declaration.
+ /// Emit code for a single top level declaration.
void EmitTopLevelDecl(Decl *D);
- /// HandleCXXStaticMemberVarInstantiation - Tell the consumer that this
- // variable has been instantiated.
+ /// Tell the consumer that this variable has been instantiated.
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
/// \brief If the declaration has internal linkage but is inside an
@@ -809,20 +822,17 @@
/// Add a global to a list to be added to the llvm.compiler.used metadata.
void addCompilerUsedGlobal(llvm::GlobalValue *GV);
- /// AddCXXDtorEntry - Add a destructor and object to add to the C++ global
- /// destructor function.
+ /// Add a destructor and object to add to the C++ global destructor function.
void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) {
CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
}
- /// CreateRuntimeFunction - Create a new runtime function with the specified
- /// type and name.
+ /// Create a new runtime function with the specified type and name.
llvm::Constant *CreateRuntimeFunction(llvm::FunctionType *Ty,
StringRef Name,
llvm::AttributeSet ExtraAttrs =
llvm::AttributeSet());
- /// CreateRuntimeVariable - Create a new runtime global variable with the
- /// specified type and name.
+ /// Create a new runtime global variable with the specified type and name.
llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name);
@@ -839,89 +849,80 @@
llvm::Constant *getLLVMLifetimeStartFn();
llvm::Constant *getLLVMLifetimeEndFn();
- // UpdateCompleteType - Make sure that this type is translated.
+ // Make sure that this type is translated.
void UpdateCompletedType(const TagDecl *TD);
llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
- /// EmitConstantInit - Try to emit the initializer for the given declaration
- /// as a constant; returns 0 if the expression cannot be emitted as a
- /// constant.
- llvm::Constant *EmitConstantInit(const VarDecl &D, CodeGenFunction *CGF = 0);
+ /// Try to emit the initializer for the given declaration as a constant;
+ /// returns 0 if the expression cannot be emitted as a constant.
+ llvm::Constant *EmitConstantInit(const VarDecl &D,
+ CodeGenFunction *CGF = nullptr);
- /// EmitConstantExpr - Try to emit the given expression as a
- /// constant; returns 0 if the expression cannot be emitted as a
- /// constant.
+ /// Try to emit the given expression as a constant; returns 0 if the
+ /// expression cannot be emitted as a constant.
llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
- CodeGenFunction *CGF = 0);
+ CodeGenFunction *CGF = nullptr);
- /// EmitConstantValue - Emit the given constant value as a constant, in the
- /// type's scalar representation.
+ /// Emit the given constant value as a constant, in the type's scalar
+ /// representation.
llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType,
- CodeGenFunction *CGF = 0);
+ CodeGenFunction *CGF = nullptr);
- /// EmitConstantValueForMemory - Emit the given constant value as a constant,
- /// in the type's memory representation.
+ /// Emit the given constant value as a constant, in the type's memory
+ /// representation.
llvm::Constant *EmitConstantValueForMemory(const APValue &Value,
QualType DestType,
- CodeGenFunction *CGF = 0);
+ CodeGenFunction *CGF = nullptr);
- /// EmitNullConstant - Return the result of value-initializing the given
- /// type, i.e. a null expression of the given type. This is usually,
- /// but not always, an LLVM null constant.
+ /// Return the result of value-initializing the given type, i.e. a null
+ /// expression of the given type. This is usually, but not always, an LLVM
+ /// null constant.
llvm::Constant *EmitNullConstant(QualType T);
- /// EmitNullConstantForBase - Return a null constant appropriate for
- /// zero-initializing a base class with the given type. This is usually,
- /// but not always, an LLVM null constant.
+ /// Return a null constant appropriate for zero-initializing a base class with
+ /// the given type. This is usually, but not always, an LLVM null constant.
llvm::Constant *EmitNullConstantForBase(const CXXRecordDecl *Record);
- /// Error - Emit a general error that something can't be done.
+ /// Emit a general error that something can't be done.
void Error(SourceLocation loc, StringRef error);
- /// ErrorUnsupported - Print out an error that codegen doesn't support the
- /// specified stmt yet.
+ /// Print out an error that codegen doesn't support the specified stmt yet.
void ErrorUnsupported(const Stmt *S, const char *Type);
- /// ErrorUnsupported - Print out an error that codegen doesn't support the
- /// specified decl yet.
+ /// Print out an error that codegen doesn't support the specified decl yet.
void ErrorUnsupported(const Decl *D, const char *Type);
- /// SetInternalFunctionAttributes - Set the attributes on the LLVM
- /// function for the given decl and function info. This applies
- /// attributes necessary for handling the ABI as well as user
- /// specified attributes like section.
+ /// Set the attributes on the LLVM function for the given decl and function
+ /// info. This applies attributes necessary for handling the ABI as well as
+ /// user specified attributes like section.
void SetInternalFunctionAttributes(const Decl *D, llvm::Function *F,
const CGFunctionInfo &FI);
- /// SetLLVMFunctionAttributes - Set the LLVM function attributes
- /// (sext, zext, etc).
+ /// Set the LLVM function attributes (sext, zext, etc).
void SetLLVMFunctionAttributes(const Decl *D,
const CGFunctionInfo &Info,
llvm::Function *F);
- /// SetLLVMFunctionAttributesForDefinition - Set the LLVM function attributes
- /// which only apply to a function definintion.
+ /// Set the LLVM function attributes which only apply to a function
+ /// definintion.
void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F);
- /// ReturnTypeUsesSRet - Return true iff the given type uses 'sret' when used
- /// as a return type.
+ /// Return true iff the given type uses 'sret' when used as a return type.
bool ReturnTypeUsesSRet(const CGFunctionInfo &FI);
- /// ReturnSlotInterferesWithArgs - Return true iff the given type uses an
- /// argument slot when 'sret' is used as a return type.
+ /// Return true iff the given type uses an argument slot when 'sret' is used
+ /// as a return type.
bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI);
- /// ReturnTypeUsesFPRet - Return true iff the given type uses 'fpret' when
- /// used as a return type.
+ /// Return true iff the given type uses 'fpret' when used as a return type.
bool ReturnTypeUsesFPRet(QualType ResultType);
- /// ReturnTypeUsesFP2Ret - Return true iff the given type uses 'fp2ret' when
- /// used as a return type.
+ /// Return true iff the given type uses 'fp2ret' when used as a return type.
bool ReturnTypeUsesFP2Ret(QualType ResultType);
- /// ConstructAttributeList - Get the LLVM attributes and calling convention to
- /// use for a particular function type.
+ /// Get the LLVM attributes and calling convention to use for a particular
+ /// function type.
///
/// \param Info - The function type information.
/// \param TargetDecl - The decl these attributes are being constructed
@@ -943,8 +944,7 @@
void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);
- /// EmitFundamentalRTTIDescriptors - Emit the RTTI descriptors for the
- /// builtin types.
+ /// Emit the RTTI descriptors for the builtin types.
void EmitFundamentalRTTIDescriptors();
/// \brief Appends Opts to the "Linker Options" metadata value.
@@ -958,23 +958,29 @@
llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD);
- void setFunctionLinkage(GlobalDecl GD, llvm::GlobalValue *V) {
- V->setLinkage(getFunctionLinkage(GD));
+ void setFunctionLinkage(GlobalDecl GD, llvm::Function *F) {
+ F->setLinkage(getFunctionLinkage(GD));
}
- /// getVTableLinkage - Return the appropriate linkage for the vtable, VTT,
- /// and type information of the given class.
+ /// \brief Returns the appropriate linkage for the TypeInfo struct for a type.
+ llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty);
+
+ /// Return the appropriate linkage for the vtable, VTT, and type information
+ /// of the given class.
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD);
- /// GetTargetTypeStoreSize - Return the store size, in character units, of
- /// the given LLVM type.
+ /// Return the store size, in character units, of the given LLVM type.
CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const;
- /// GetLLVMLinkageVarDefinition - Returns LLVM linkage for a global
- /// variable.
- llvm::GlobalValue::LinkageTypes
- GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant);
-
+ /// Returns LLVM linkage for a declarator.
+ llvm::GlobalValue::LinkageTypes
+ getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage,
+ bool IsConstantVariable);
+
+ /// Returns LLVM linkage for a declarator.
+ llvm::GlobalValue::LinkageTypes
+ getLLVMLinkageVarDefinition(const VarDecl *VD, bool IsConstant);
+
/// Emit all the global annotations.
void EmitGlobalAnnotations();
@@ -987,8 +993,8 @@
/// Emit the annotation line number.
llvm::Constant *EmitAnnotationLineNo(SourceLocation L);
- /// EmitAnnotateAttr - Generate the llvm::ConstantStruct which contains the
- /// annotation information for a given GlobalValue. The annotation struct is
+ /// Generate the llvm::ConstantStruct which contains the annotation
+ /// information for a given GlobalValue. The annotation struct is
/// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the
/// GlobalValue being annotated. The second field is the constant string
/// created from the AnnotateAttr's annotation. The third field is a constant
@@ -1012,8 +1018,8 @@
DeferredVTables.push_back(RD);
}
- /// EmitGlobal - Emit code for a singal global function or var decl. Forward
- /// declarations are emitted lazily.
+ /// Emit code for a singal global function or var decl. Forward declarations
+ /// are emitted lazily.
void EmitGlobal(GlobalDecl D);
private:
@@ -1026,27 +1032,26 @@
llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName,
llvm::PointerType *PTy,
- const VarDecl *D,
- bool UnnamedAddr = false);
+ const VarDecl *D);
- /// SetCommonAttributes - Set attributes which are common to any
- /// form of a global definition (alias, Objective-C method,
- /// function, global variable).
+ /// Set attributes which are common to any form of a global definition (alias,
+ /// Objective-C method, function, global variable).
///
/// NOTE: This should only be called for definitions.
void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV);
- /// SetFunctionDefinitionAttributes - Set attributes for a global definition.
- void SetFunctionDefinitionAttributes(const FunctionDecl *D,
- llvm::GlobalValue *GV);
+ void setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO);
- /// SetFunctionAttributes - Set function attributes for a function
- /// declaration.
+ /// Set attributes for a global definition.
+ void setFunctionDefinitionAttributes(const FunctionDecl *D,
+ llvm::Function *F);
+
+ /// Set function attributes for a function declaration.
void SetFunctionAttributes(GlobalDecl GD,
llvm::Function *F,
bool IsIncompleteFunction);
- void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = 0);
+ void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr);
void EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV);
void EmitGlobalVarDefinition(const VarDecl *D);
@@ -1064,44 +1069,41 @@
void EmitLinkageSpec(const LinkageSpecDecl *D);
void CompleteDIClassType(const CXXMethodDecl* D);
- /// EmitCXXConstructor - Emit a single constructor with the given type from
- /// a C++ constructor Decl.
+ /// Emit a single constructor with the given type from a C++ constructor Decl.
void EmitCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type);
- /// EmitCXXDestructor - Emit a single destructor with the given type from
- /// a C++ destructor Decl.
+ /// Emit a single destructor with the given type from a C++ destructor Decl.
void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type);
/// \brief Emit the function that initializes C++ thread_local variables.
void EmitCXXThreadLocalInitFunc();
- /// EmitCXXGlobalInitFunc - Emit the function that initializes C++ globals.
+ /// Emit the function that initializes C++ globals.
void EmitCXXGlobalInitFunc();
- /// EmitCXXGlobalDtorFunc - Emit the function that destroys C++ globals.
+ /// Emit the function that destroys C++ globals.
void EmitCXXGlobalDtorFunc();
- /// EmitCXXGlobalVarDeclInitFunc - Emit the function that initializes the
- /// specified global (if PerformInit is true) and registers its destructor.
+ /// Emit the function that initializes the specified global (if PerformInit is
+ /// true) and registers its destructor.
void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
llvm::GlobalVariable *Addr,
bool PerformInit);
// FIXME: Hardcoding priority here is gross.
- void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535);
- void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535);
+ void AddGlobalCtor(llvm::Function *Ctor, int Priority = 65535,
+ llvm::Constant *AssociatedData = 0);
+ void AddGlobalDtor(llvm::Function *Dtor, int Priority = 65535);
- /// EmitCtorList - Generates a global array of functions and priorities using
- /// the given list and name. This array will have appending linkage and is
- /// suitable for use as a LLVM constructor or destructor array.
+ /// Generates a global array of functions and priorities using the given list
+ /// and name. This array will have appending linkage and is suitable for use
+ /// as a LLVM constructor or destructor array.
void EmitCtorList(const CtorList &Fns, const char *GlobalName);
- /// EmitFundamentalRTTIDescriptor - Emit the RTTI descriptors for the
- /// given type.
+ /// Emit the RTTI descriptors for the given type.
void EmitFundamentalRTTIDescriptor(QualType Type);
- /// EmitDeferred - Emit any needed decls for which code generation
- /// was deferred.
+ /// Emit any needed decls for which code generation was deferred.
void EmitDeferred();
/// Call replaceAllUsesWith on all pairs in Replacements.
@@ -1109,8 +1111,7 @@
void checkAliases();
- /// EmitDeferredVTables - Emit any vtables which we deferred and
- /// still have a use for.
+ /// Emit any vtables which we deferred and still have a use for.
void EmitDeferredVTables();
/// Emit the llvm.used and llvm.compiler.used metadata.
@@ -1128,20 +1129,19 @@
/// \brief Emit the Clang version as llvm.ident metadata.
void EmitVersionIdentMetadata();
- /// EmitCoverageFile - Emit the llvm.gcov metadata used to tell LLVM where
- /// to emit the .gcno and .gcda files in a way that persists in .bc files.
+ /// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and
+ /// .gcda files in a way that persists in .bc files.
void EmitCoverageFile();
/// Emits the initializer for a uuidof string.
llvm::Constant *EmitUuidofInitializer(StringRef uuidstr, QualType IIDType);
- /// MayDeferGeneration - Determine if the given decl can be emitted
- /// lazily; this is only relevant for definitions. The given decl
- /// must be either a function or var decl.
+ /// Determine if the given decl can be emitted lazily; this is only relevant
+ /// for definitions. The given decl must be either a function or var decl.
bool MayDeferGeneration(const ValueDecl *D);
- /// SimplifyPersonality - Check whether we can use a "simpler", more
- /// core exceptions personality function.
+ /// Check whether we can use a "simpler", more core exceptions personality
+ /// function.
void SimplifyPersonality();
};
} // end namespace CodeGen
diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp
index ac6b7bc..22534b8 100644
--- a/lib/CodeGen/CodeGenPGO.cpp
+++ b/lib/CodeGen/CodeGenPGO.cpp
@@ -15,143 +15,15 @@
#include "CodeGenFunction.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
-#include "llvm/Config/config.h" // for strtoull()/strtoll() define
#include "llvm/IR/MDBuilder.h"
+#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MD5.h"
using namespace clang;
using namespace CodeGen;
-static void ReportBadPGOData(CodeGenModule &CGM, const char *Message) {
- DiagnosticsEngine &Diags = CGM.getDiags();
- unsigned diagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0");
- Diags.Report(diagID) << Message;
-}
-
-PGOProfileData::PGOProfileData(CodeGenModule &CGM, std::string Path)
- : CGM(CGM) {
- if (llvm::MemoryBuffer::getFile(Path, DataBuffer)) {
- ReportBadPGOData(CGM, "failed to open pgo data file");
- return;
- }
-
- if (DataBuffer->getBufferSize() > std::numeric_limits<unsigned>::max()) {
- ReportBadPGOData(CGM, "pgo data file too big");
- return;
- }
-
- // Scan through the data file and map each function to the corresponding
- // file offset where its counts are stored.
- const char *BufferStart = DataBuffer->getBufferStart();
- const char *BufferEnd = DataBuffer->getBufferEnd();
- const char *CurPtr = BufferStart;
- uint64_t MaxCount = 0;
- while (CurPtr < BufferEnd) {
- // Read the function name.
- const char *FuncStart = CurPtr;
- // For Objective-C methods, the name may include whitespace, so search
- // backward from the end of the line to find the space that separates the
- // name from the number of counters. (This is a temporary hack since we are
- // going to completely replace this file format in the near future.)
- CurPtr = strchr(CurPtr, '\n');
- if (!CurPtr) {
- ReportBadPGOData(CGM, "pgo data file has malformed function entry");
- return;
- }
- StringRef FuncName(FuncStart, CurPtr - FuncStart);
-
- // Skip over the function hash.
- CurPtr = strchr(++CurPtr, '\n');
- if (!CurPtr) {
- ReportBadPGOData(CGM, "pgo data file is missing the function hash");
- return;
- }
-
- // Read the number of counters.
- char *EndPtr;
- unsigned NumCounters = strtol(++CurPtr, &EndPtr, 10);
- if (EndPtr == CurPtr || *EndPtr != '\n' || NumCounters <= 0) {
- ReportBadPGOData(CGM, "pgo data file has unexpected number of counters");
- return;
- }
- CurPtr = EndPtr;
-
- // Read function count.
- uint64_t Count = strtoll(CurPtr, &EndPtr, 10);
- if (EndPtr == CurPtr || *EndPtr != '\n') {
- ReportBadPGOData(CGM, "pgo-data file has bad count value");
- return;
- }
- CurPtr = EndPtr; // Point to '\n'.
- FunctionCounts[FuncName] = Count;
- MaxCount = Count > MaxCount ? Count : MaxCount;
-
- // There is one line for each counter; skip over those lines.
- // Since function count is already read, we start the loop from 1.
- for (unsigned N = 1; N < NumCounters; ++N) {
- CurPtr = strchr(++CurPtr, '\n');
- if (!CurPtr) {
- ReportBadPGOData(CGM, "pgo data file is missing some counter info");
- return;
- }
- }
-
- // Skip over the blank line separating functions.
- CurPtr += 2;
-
- DataOffsets[FuncName] = FuncStart - BufferStart;
- }
- MaxFunctionCount = MaxCount;
-}
-
-bool PGOProfileData::getFunctionCounts(StringRef FuncName, uint64_t &FuncHash,
- std::vector<uint64_t> &Counts) {
- // Find the relevant section of the pgo-data file.
- llvm::StringMap<unsigned>::const_iterator OffsetIter =
- DataOffsets.find(FuncName);
- if (OffsetIter == DataOffsets.end())
- return true;
- const char *CurPtr = DataBuffer->getBufferStart() + OffsetIter->getValue();
-
- // Skip over the function name.
- CurPtr = strchr(CurPtr, '\n');
- assert(CurPtr && "pgo-data has corrupted function entry");
-
- char *EndPtr;
- // Read the function hash.
- FuncHash = strtoll(++CurPtr, &EndPtr, 10);
- assert(EndPtr != CurPtr && *EndPtr == '\n' &&
- "pgo-data file has corrupted function hash");
- CurPtr = EndPtr;
-
- // Read the number of counters.
- unsigned NumCounters = strtol(++CurPtr, &EndPtr, 10);
- assert(EndPtr != CurPtr && *EndPtr == '\n' && NumCounters > 0 &&
- "pgo-data file has corrupted number of counters");
- CurPtr = EndPtr;
-
- Counts.reserve(NumCounters);
-
- for (unsigned N = 0; N < NumCounters; ++N) {
- // Read the count value.
- uint64_t Count = strtoll(CurPtr, &EndPtr, 10);
- if (EndPtr == CurPtr || *EndPtr != '\n') {
- ReportBadPGOData(CGM, "pgo-data file has bad count value");
- return true;
- }
- Counts.push_back(Count);
- CurPtr = EndPtr + 1;
- }
-
- // Make sure the number of counters matches up.
- if (Counts.size() != NumCounters) {
- ReportBadPGOData(CGM, "pgo-data file has inconsistent counters");
- return true;
- }
-
- return false;
-}
-
void CodeGenPGO::setFuncName(llvm::Function *Fn) {
RawFuncName = Fn->getName();
@@ -268,13 +140,22 @@
Data->setSection(getDataSection(CGM));
Data->setAlignment(8);
+ // Hide all these symbols so that we correctly get a copy for each
+ // executable. The profile format expects names and counters to be
+ // contiguous, so references into shared objects would be invalid.
+ if (!llvm::GlobalValue::isLocalLinkage(VarLinkage)) {
+ Name->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ Data->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ }
+
// Make sure the data doesn't get deleted.
CGM.addUsedGlobal(Data);
return Data;
}
void CodeGenPGO::emitInstrumentationData() {
- if (!CGM.getCodeGenOpts().ProfileInstrGenerate)
+ if (!RegionCounters)
return;
// Build the data.
@@ -294,9 +175,8 @@
if (!CGM.getCodeGenOpts().ProfileInstrGenerate)
return nullptr;
- // Only need to create this once per module.
- if (CGM.getModule().getFunction("__llvm_profile_init"))
- return nullptr;
+ assert(CGM.getModule().getFunction("__llvm_profile_init") == nullptr &&
+ "profile initialization already emitted");
// Get the function to call at initialization.
llvm::Constant *RegisterF = getRegisterFunc(CGM);
@@ -322,144 +202,154 @@
}
namespace {
- /// A StmtVisitor that fills a map of statements to PGO counters.
- struct MapRegionCounters : public ConstStmtVisitor<MapRegionCounters> {
+/// \brief Stable hasher for PGO region counters.
+///
+/// PGOHash produces a stable hash of a given function's control flow.
+///
+/// Changing the output of this hash will invalidate all previously generated
+/// profiles -- i.e., don't do it.
+///
+/// \note When this hash does eventually change (years?), we still need to
+/// support old hashes. We'll need to pull in the version number from the
+/// profile data format and use the matching hash function.
+class PGOHash {
+ uint64_t Working;
+ unsigned Count;
+ llvm::MD5 MD5;
+
+ static const int NumBitsPerType = 6;
+ static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType;
+ static const unsigned TooBig = 1u << NumBitsPerType;
+
+public:
+ /// \brief Hash values for AST nodes.
+ ///
+ /// Distinct values for AST nodes that have region counters attached.
+ ///
+ /// These values must be stable. All new members must be added at the end,
+ /// and no members should be removed. Changing the enumeration value for an
+ /// AST node will affect the hash of every function that contains that node.
+ enum HashType : unsigned char {
+ None = 0,
+ LabelStmt = 1,
+ WhileStmt,
+ DoStmt,
+ ForStmt,
+ CXXForRangeStmt,
+ ObjCForCollectionStmt,
+ SwitchStmt,
+ CaseStmt,
+ DefaultStmt,
+ IfStmt,
+ CXXTryStmt,
+ CXXCatchStmt,
+ ConditionalOperator,
+ BinaryOperatorLAnd,
+ BinaryOperatorLOr,
+ BinaryConditionalOperator,
+
+ // Keep this last. It's for the static assert that follows.
+ LastHashType
+ };
+ static_assert(LastHashType <= TooBig, "Too many types in HashType");
+
+ // TODO: When this format changes, take in a version number here, and use the
+ // old hash calculation for file formats that used the old hash.
+ PGOHash() : Working(0), Count(0) {}
+ void combine(HashType Type);
+ uint64_t finalize();
+};
+const int PGOHash::NumBitsPerType;
+const unsigned PGOHash::NumTypesPerWord;
+const unsigned PGOHash::TooBig;
+
+ /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
+ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
/// The next counter value to assign.
unsigned NextCounter;
+ /// The function hash.
+ PGOHash Hash;
/// The map of statements to counters.
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
MapRegionCounters(llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
: NextCounter(0), CounterMap(CounterMap) {}
- void VisitChildren(const Stmt *S) {
- for (Stmt::const_child_range I = S->children(); I; ++I)
- if (*I)
- this->Visit(*I);
- }
- void VisitStmt(const Stmt *S) { VisitChildren(S); }
+ // Blocks and lambdas are handled as separate functions, so we need not
+ // traverse them in the parent context.
+ bool TraverseBlockExpr(BlockExpr *BE) { return true; }
+ bool TraverseLambdaBody(LambdaExpr *LE) { return true; }
+ bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
- /// Assign a counter to track entry to the function body.
- void VisitFunctionDecl(const FunctionDecl *S) {
- CounterMap[S->getBody()] = NextCounter++;
- Visit(S->getBody());
+ bool VisitDecl(const Decl *D) {
+ switch (D->getKind()) {
+ default:
+ break;
+ case Decl::Function:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::ObjCMethod:
+ case Decl::Block:
+ case Decl::Captured:
+ CounterMap[D->getBody()] = NextCounter++;
+ break;
+ }
+ return true;
}
- void VisitObjCMethodDecl(const ObjCMethodDecl *S) {
- CounterMap[S->getBody()] = NextCounter++;
- Visit(S->getBody());
- }
- void VisitBlockDecl(const BlockDecl *S) {
- CounterMap[S->getBody()] = NextCounter++;
- Visit(S->getBody());
- }
- /// Assign a counter to track the block following a label.
- void VisitLabelStmt(const LabelStmt *S) {
+
+ bool VisitStmt(const Stmt *S) {
+ auto Type = getHashType(S);
+ if (Type == PGOHash::None)
+ return true;
+
CounterMap[S] = NextCounter++;
- Visit(S->getSubStmt());
+ Hash.combine(Type);
+ return true;
}
- /// Assign a counter for the body of a while loop.
- void VisitWhileStmt(const WhileStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getCond());
- Visit(S->getBody());
- }
- /// Assign a counter for the body of a do-while loop.
- void VisitDoStmt(const DoStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getBody());
- Visit(S->getCond());
- }
- /// Assign a counter for the body of a for loop.
- void VisitForStmt(const ForStmt *S) {
- CounterMap[S] = NextCounter++;
- if (S->getInit())
- Visit(S->getInit());
- const Expr *E;
- if ((E = S->getCond()))
- Visit(E);
- if ((E = S->getInc()))
- Visit(E);
- Visit(S->getBody());
- }
- /// Assign a counter for the body of a for-range loop.
- void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getRangeStmt());
- Visit(S->getBeginEndStmt());
- Visit(S->getCond());
- Visit(S->getLoopVarStmt());
- Visit(S->getBody());
- Visit(S->getInc());
- }
- /// Assign a counter for the body of a for-collection loop.
- void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getElement());
- Visit(S->getBody());
- }
- /// Assign a counter for the exit block of the switch statement.
- void VisitSwitchStmt(const SwitchStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getCond());
- Visit(S->getBody());
- }
- /// Assign a counter for a particular case in a switch. This counts jumps
- /// from the switch header as well as fallthrough from the case before this
- /// one.
- void VisitCaseStmt(const CaseStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getSubStmt());
- }
- /// Assign a counter for the default case of a switch statement. The count
- /// is the number of branches from the loop header to the default, and does
- /// not include fallthrough from previous cases. If we have multiple
- /// conditional branch blocks from the switch instruction to the default
- /// block, as with large GNU case ranges, this is the counter for the last
- /// edge in that series, rather than the first.
- void VisitDefaultStmt(const DefaultStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getSubStmt());
- }
- /// Assign a counter for the "then" part of an if statement. The count for
- /// the "else" part, if it exists, will be calculated from this counter.
- void VisitIfStmt(const IfStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getCond());
- Visit(S->getThen());
- if (S->getElse())
- Visit(S->getElse());
- }
- /// Assign a counter for the continuation block of a C++ try statement.
- void VisitCXXTryStmt(const CXXTryStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getTryBlock());
- for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
- Visit(S->getHandler(I));
- }
- /// Assign a counter for a catch statement's handler block.
- void VisitCXXCatchStmt(const CXXCatchStmt *S) {
- CounterMap[S] = NextCounter++;
- Visit(S->getHandlerBlock());
- }
- /// Assign a counter for the "true" part of a conditional operator. The
- /// count in the "false" part will be calculated from this counter.
- void VisitConditionalOperator(const ConditionalOperator *E) {
- CounterMap[E] = NextCounter++;
- Visit(E->getCond());
- Visit(E->getTrueExpr());
- Visit(E->getFalseExpr());
- }
- /// Assign a counter for the right hand side of a logical and operator.
- void VisitBinLAnd(const BinaryOperator *E) {
- CounterMap[E] = NextCounter++;
- Visit(E->getLHS());
- Visit(E->getRHS());
- }
- /// Assign a counter for the right hand side of a logical or operator.
- void VisitBinLOr(const BinaryOperator *E) {
- CounterMap[E] = NextCounter++;
- Visit(E->getLHS());
- Visit(E->getRHS());
+ PGOHash::HashType getHashType(const Stmt *S) {
+ switch (S->getStmtClass()) {
+ default:
+ break;
+ case Stmt::LabelStmtClass:
+ return PGOHash::LabelStmt;
+ case Stmt::WhileStmtClass:
+ return PGOHash::WhileStmt;
+ case Stmt::DoStmtClass:
+ return PGOHash::DoStmt;
+ case Stmt::ForStmtClass:
+ return PGOHash::ForStmt;
+ case Stmt::CXXForRangeStmtClass:
+ return PGOHash::CXXForRangeStmt;
+ case Stmt::ObjCForCollectionStmtClass:
+ return PGOHash::ObjCForCollectionStmt;
+ case Stmt::SwitchStmtClass:
+ return PGOHash::SwitchStmt;
+ case Stmt::CaseStmtClass:
+ return PGOHash::CaseStmt;
+ case Stmt::DefaultStmtClass:
+ return PGOHash::DefaultStmt;
+ case Stmt::IfStmtClass:
+ return PGOHash::IfStmt;
+ case Stmt::CXXTryStmtClass:
+ return PGOHash::CXXTryStmt;
+ case Stmt::CXXCatchStmtClass:
+ return PGOHash::CXXCatchStmt;
+ case Stmt::ConditionalOperatorClass:
+ return PGOHash::ConditionalOperator;
+ case Stmt::BinaryConditionalOperatorClass:
+ return PGOHash::BinaryConditionalOperator;
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator *BO = cast<BinaryOperator>(S);
+ if (BO->getOpcode() == BO_LAnd)
+ return PGOHash::BinaryOperatorLAnd;
+ if (BO->getOpcode() == BO_LOr)
+ return PGOHash::BinaryOperatorLOr;
+ break;
+ }
+ }
+ return PGOHash::None;
}
};
@@ -476,7 +366,7 @@
/// The map of statements to count values.
llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
- /// BreakContinueStack - Keep counts of breaks and continues inside loops.
+ /// BreakContinueStack - Keep counts of breaks and continues inside loops.
struct BreakContinue {
uint64_t BreakCount;
uint64_t ContinueCount;
@@ -503,25 +393,41 @@
}
}
- void VisitFunctionDecl(const FunctionDecl *S) {
- RegionCounter Cnt(PGO, S->getBody());
+ void VisitFunctionDecl(const FunctionDecl *D) {
+ // Counter tracks entry to the function body.
+ RegionCounter Cnt(PGO, D->getBody());
Cnt.beginRegion();
- CountMap[S->getBody()] = PGO.getCurrentRegionCount();
- Visit(S->getBody());
+ CountMap[D->getBody()] = PGO.getCurrentRegionCount();
+ Visit(D->getBody());
}
- void VisitObjCMethodDecl(const ObjCMethodDecl *S) {
- RegionCounter Cnt(PGO, S->getBody());
+ // Skip lambda expressions. We visit these as FunctionDecls when we're
+ // generating them and aren't interested in the body when generating a
+ // parent context.
+ void VisitLambdaExpr(const LambdaExpr *LE) {}
+
+ void VisitCapturedDecl(const CapturedDecl *D) {
+ // Counter tracks entry to the capture body.
+ RegionCounter Cnt(PGO, D->getBody());
Cnt.beginRegion();
- CountMap[S->getBody()] = PGO.getCurrentRegionCount();
- Visit(S->getBody());
+ CountMap[D->getBody()] = PGO.getCurrentRegionCount();
+ Visit(D->getBody());
}
- void VisitBlockDecl(const BlockDecl *S) {
- RegionCounter Cnt(PGO, S->getBody());
+ void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
+ // Counter tracks entry to the method body.
+ RegionCounter Cnt(PGO, D->getBody());
Cnt.beginRegion();
- CountMap[S->getBody()] = PGO.getCurrentRegionCount();
- Visit(S->getBody());
+ CountMap[D->getBody()] = PGO.getCurrentRegionCount();
+ Visit(D->getBody());
+ }
+
+ void VisitBlockDecl(const BlockDecl *D) {
+ // Counter tracks entry to the block body.
+ RegionCounter Cnt(PGO, D->getBody());
+ Cnt.beginRegion();
+ CountMap[D->getBody()] = PGO.getCurrentRegionCount();
+ Visit(D->getBody());
}
void VisitReturnStmt(const ReturnStmt *S) {
@@ -540,6 +446,7 @@
void VisitLabelStmt(const LabelStmt *S) {
RecordNextStmtCount = false;
+ // Counter tracks the block following the label.
RegionCounter Cnt(PGO, S);
Cnt.beginRegion();
CountMap[S] = PGO.getCurrentRegionCount();
@@ -564,6 +471,7 @@
void VisitWhileStmt(const WhileStmt *S) {
RecordStmtCount(S);
+ // Counter tracks the body of the loop.
RegionCounter Cnt(PGO, S);
BreakContinueStack.push_back(BreakContinue());
// Visit the body region first so the break/continue adjustments can be
@@ -589,6 +497,7 @@
void VisitDoStmt(const DoStmt *S) {
RecordStmtCount(S);
+ // Counter tracks the body of the loop.
RegionCounter Cnt(PGO, S);
BreakContinueStack.push_back(BreakContinue());
Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
@@ -615,6 +524,7 @@
RecordStmtCount(S);
if (S->getInit())
Visit(S->getInit());
+ // Counter tracks the body of the loop.
RegionCounter Cnt(PGO, S);
BreakContinueStack.push_back(BreakContinue());
// Visit the body region first. (This is basically the same as a while
@@ -653,6 +563,7 @@
RecordStmtCount(S);
Visit(S->getRangeStmt());
Visit(S->getBeginEndStmt());
+ // Counter tracks the body of the loop.
RegionCounter Cnt(PGO, S);
BreakContinueStack.push_back(BreakContinue());
// Visit the body region first. (This is basically the same as a while
@@ -687,6 +598,7 @@
void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
RecordStmtCount(S);
Visit(S->getElement());
+ // Counter tracks the body of the loop.
RegionCounter Cnt(PGO, S);
BreakContinueStack.push_back(BreakContinue());
Cnt.beginRegion();
@@ -708,6 +620,7 @@
BreakContinue BC = BreakContinueStack.pop_back_val();
if (!BreakContinueStack.empty())
BreakContinueStack.back().ContinueCount += BC.ContinueCount;
+ // Counter tracks the exit block of the switch.
RegionCounter ExitCnt(PGO, S);
ExitCnt.beginRegion();
RecordNextStmtCount = true;
@@ -715,6 +628,9 @@
void VisitCaseStmt(const CaseStmt *S) {
RecordNextStmtCount = false;
+ // Counter for this particular case. This counts only jumps from the
+ // switch header and does not include fallthrough from the case before
+ // this one.
RegionCounter Cnt(PGO, S);
Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
CountMap[S] = Cnt.getCount();
@@ -724,6 +640,8 @@
void VisitDefaultStmt(const DefaultStmt *S) {
RecordNextStmtCount = false;
+ // Counter for this default case. This does not include fallthrough from
+ // the previous case.
RegionCounter Cnt(PGO, S);
Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
CountMap[S] = Cnt.getCount();
@@ -733,6 +651,8 @@
void VisitIfStmt(const IfStmt *S) {
RecordStmtCount(S);
+ // Counter tracks the "then" part of an if statement. The count for
+ // the "else" part, if it exists, will be calculated from this counter.
RegionCounter Cnt(PGO, S);
Visit(S->getCond());
@@ -756,6 +676,7 @@
Visit(S->getTryBlock());
for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
Visit(S->getHandler(I));
+ // Counter tracks the continuation block of the try statement.
RegionCounter Cnt(PGO, S);
Cnt.beginRegion();
RecordNextStmtCount = true;
@@ -763,14 +684,18 @@
void VisitCXXCatchStmt(const CXXCatchStmt *S) {
RecordNextStmtCount = false;
+ // Counter tracks the catch statement's handler block.
RegionCounter Cnt(PGO, S);
Cnt.beginRegion();
CountMap[S] = PGO.getCurrentRegionCount();
Visit(S->getHandlerBlock());
}
- void VisitConditionalOperator(const ConditionalOperator *E) {
+ void VisitAbstractConditionalOperator(
+ const AbstractConditionalOperator *E) {
RecordStmtCount(E);
+ // Counter tracks the "true" part of a conditional operator. The
+ // count in the "false" part will be calculated from this counter.
RegionCounter Cnt(PGO, E);
Visit(E->getCond());
@@ -790,6 +715,7 @@
void VisitBinLAnd(const BinaryOperator *E) {
RecordStmtCount(E);
+ // Counter tracks the right hand side of a logical and operator.
RegionCounter Cnt(PGO, E);
Visit(E->getLHS());
Cnt.beginRegion();
@@ -802,6 +728,7 @@
void VisitBinLOr(const BinaryOperator *E) {
RecordStmtCount(E);
+ // Counter tracks the right hand side of a logical or operator.
RegionCounter Cnt(PGO, E);
Visit(E->getLHS());
Cnt.beginRegion();
@@ -814,9 +741,46 @@
};
}
+void PGOHash::combine(HashType Type) {
+ // Check that we never combine 0 and only have six bits.
+ assert(Type && "Hash is invalid: unexpected type 0");
+ assert(unsigned(Type) < TooBig && "Hash is invalid: too many types");
+
+ // Pass through MD5 if enough work has built up.
+ if (Count && Count % NumTypesPerWord == 0) {
+ using namespace llvm::support;
+ uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
+ MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
+ Working = 0;
+ }
+
+ // Accumulate the current type.
+ ++Count;
+ Working = Working << NumBitsPerType | Type;
+}
+
+uint64_t PGOHash::finalize() {
+ // Use Working as the hash directly if we never used MD5.
+ if (Count <= NumTypesPerWord)
+ // No need to byte swap here, since none of the math was endian-dependent.
+ // This number will be byte-swapped as required on endianness transitions,
+ // so we will see the same value on the other side.
+ return Working;
+
+ // Check for remaining work in Working.
+ if (Working)
+ MD5.update(Working);
+
+ // Finalize the MD5 and return the hash.
+ llvm::MD5::MD5Result Result;
+ MD5.final(Result);
+ using namespace llvm::support;
+ return endian::read<uint64_t, little, unaligned>(Result);
+}
+
static void emitRuntimeHook(CodeGenModule &CGM) {
- LLVM_CONSTEXPR const char *RuntimeVarName = "__llvm_profile_runtime";
- LLVM_CONSTEXPR const char *RuntimeUserName = "__llvm_profile_runtime_user";
+ const char *const RuntimeVarName = "__llvm_profile_runtime";
+ const char *const RuntimeUserName = "__llvm_profile_runtime_user";
if (CGM.getModule().getGlobalVariable(RuntimeVarName))
return;
@@ -845,10 +809,10 @@
void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
- PGOProfileData *PGOData = CGM.getPGOData();
- if (!InstrumentRegions && !PGOData)
+ llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
+ if (!InstrumentRegions && !PGOReader)
return;
- if (!D)
+ if (D->isImplicit())
return;
setFuncName(Fn);
@@ -872,10 +836,10 @@
emitRuntimeHook(CGM);
emitCounterVariables();
}
- if (PGOData) {
- loadRegionCounts(PGOData);
+ if (PGOReader) {
+ loadRegionCounts(PGOReader);
computeRegionCounts(D);
- applyFunctionAttributes(PGOData, Fn);
+ applyFunctionAttributes(PGOReader, Fn);
}
}
@@ -883,14 +847,16 @@
RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
MapRegionCounters Walker(*RegionCounterMap);
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
- Walker.VisitFunctionDecl(FD);
+ Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
- Walker.VisitObjCMethodDecl(MD);
+ Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD));
else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
- Walker.VisitBlockDecl(BD);
+ Walker.TraverseDecl(const_cast<BlockDecl *>(BD));
+ else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
+ Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
+ assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
NumRegionCounters = Walker.NextCounter;
- // FIXME: The number of counters isn't sufficient for the hash
- FunctionHash = NumRegionCounters;
+ FunctionHash = Walker.Hash.finalize();
}
void CodeGenPGO::computeRegionCounts(const Decl *D) {
@@ -902,14 +868,17 @@
Walker.VisitObjCMethodDecl(MD);
else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
Walker.VisitBlockDecl(BD);
+ else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
+ Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD));
}
-void CodeGenPGO::applyFunctionAttributes(PGOProfileData *PGOData,
- llvm::Function *Fn) {
+void
+CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
+ llvm::Function *Fn) {
if (!haveRegionCounts())
return;
- uint64_t MaxFunctionCount = PGOData->getMaximumFunctionCount();
+ uint64_t MaxFunctionCount = PGOReader->getMaximumFunctionCount();
uint64_t FunctionCount = getRegionCount(0);
if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount))
// Turn on InlineHint attribute for hot functions.
@@ -943,22 +912,25 @@
Builder.CreateStore(Count, Addr);
}
-void CodeGenPGO::loadRegionCounts(PGOProfileData *PGOData) {
- // For now, ignore the counts from the PGO data file only if the number of
- // counters does not match. This could be tightened down in the future to
- // ignore counts when the input changes in various ways, e.g., by comparing a
- // hash value based on some characteristics of the input.
+void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader) {
+ CGM.getPGOStats().Visited++;
RegionCounts.reset(new std::vector<uint64_t>);
uint64_t Hash;
- if (PGOData->getFunctionCounts(getFuncName(), Hash, *RegionCounts) ||
- Hash != FunctionHash || RegionCounts->size() != NumRegionCounters)
+ if (PGOReader->getFunctionCounts(getFuncName(), Hash, *RegionCounts)) {
+ CGM.getPGOStats().Missing++;
RegionCounts.reset();
+ } else if (Hash != FunctionHash ||
+ RegionCounts->size() != NumRegionCounters) {
+ CGM.getPGOStats().Mismatched++;
+ RegionCounts.reset();
+ }
}
void CodeGenPGO::destroyRegionCounters() {
RegionCounterMap.reset();
StmtCountMap.reset();
RegionCounts.reset();
+ RegionCounters = nullptr;
}
/// \brief Calculate what to divide by to scale weights.
@@ -1004,9 +976,13 @@
if (Weights.size() < 2)
return nullptr;
+ // Check for empty weights.
+ uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
+ if (MaxWeight == 0)
+ return nullptr;
+
// Calculate how to scale down to 32-bits.
- uint64_t Scale = calculateWeightScale(*std::max_element(Weights.begin(),
- Weights.end()));
+ uint64_t Scale = calculateWeightScale(MaxWeight);
SmallVector<uint32_t, 16> ScaledWeights;
ScaledWeights.reserve(Weights.size());
diff --git a/lib/CodeGen/CodeGenPGO.h b/lib/CodeGen/CodeGenPGO.h
index c59a58e..c434808 100644
--- a/lib/CodeGen/CodeGenPGO.h
+++ b/lib/CodeGen/CodeGenPGO.h
@@ -26,28 +26,6 @@
namespace CodeGen {
class RegionCounter;
-/// The raw counter data from an instrumented PGO binary
-class PGOProfileData {
-private:
- /// The PGO data
- std::unique_ptr<llvm::MemoryBuffer> DataBuffer;
- /// Offsets into DataBuffer for each function's counters
- llvm::StringMap<unsigned> DataOffsets;
- /// Execution counts for each function.
- llvm::StringMap<uint64_t> FunctionCounts;
- /// The maximal execution count among all functions.
- uint64_t MaxFunctionCount;
- CodeGenModule &CGM;
-public:
- PGOProfileData(CodeGenModule &CGM, std::string Path);
- /// Fill Counts with the profile data for the given function name. Returns
- /// false on success.
- bool getFunctionCounts(StringRef FuncName, uint64_t &FuncHash,
- std::vector<uint64_t> &Counts);
- /// Return the maximum of all known function counts.
- uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
-};
-
/// Per-function PGO state. This class should generally not be used directly,
/// but instead through the CodeGenFunction and RegionCounter types.
class CodeGenPGO {
@@ -67,13 +45,13 @@
public:
CodeGenPGO(CodeGenModule &CGM)
- : CGM(CGM), NumRegionCounters(0), FunctionHash(0), RegionCounters(0),
- CurrentRegionCount(0) {}
+ : CGM(CGM), NumRegionCounters(0), FunctionHash(0),
+ RegionCounters(nullptr), CurrentRegionCount(0) {}
/// Whether or not we have PGO region data for the current function. This is
/// false both when we have no data at all and when our data has been
/// discarded.
- bool haveRegionCounts() const { return RegionCounts != 0; }
+ bool haveRegionCounts() const { return RegionCounts != nullptr; }
/// Get the string used to identify this function in the profile data.
/// For functions with local linkage, this includes the main file name.
@@ -138,8 +116,9 @@
void setFuncName(llvm::Function *Fn);
void mapRegionCounters(const Decl *D);
void computeRegionCounts(const Decl *D);
- void applyFunctionAttributes(PGOProfileData *PGOData, llvm::Function *Fn);
- void loadRegionCounts(PGOProfileData *PGOData);
+ void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
+ llvm::Function *Fn);
+ void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader);
void emitCounterVariables();
llvm::GlobalVariable *buildDataVar();
@@ -149,7 +128,7 @@
/// Return the region counter for the given statement. This should only be
/// called on statements that have a dedicated counter.
unsigned getRegionCounter(const Stmt *S) {
- if (RegionCounterMap == 0)
+ if (!RegionCounterMap)
return 0;
return (*RegionCounterMap)[S];
}
diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp
index 699cc2e..53ba02a 100644
--- a/lib/CodeGen/CodeGenTBAA.cpp
+++ b/lib/CodeGen/CodeGenTBAA.cpp
@@ -33,7 +33,7 @@
const CodeGenOptions &CGO,
const LangOptions &Features, MangleContext &MContext)
: Context(Ctx), CodeGenOpts(CGO), Features(Features), MContext(MContext),
- MDHelper(VMContext), Root(0), Char(0) {
+ MDHelper(VMContext), Root(nullptr), Char(nullptr) {
}
CodeGenTBAA::~CodeGenTBAA() {
@@ -88,7 +88,7 @@
CodeGenTBAA::getTBAAInfo(QualType QTy) {
// At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
- return NULL;
+ return nullptr;
// If the type has the may_alias attribute (even on a typedef), it is
// effectively in the general char alias class.
@@ -221,7 +221,7 @@
return MDHelper.createTBAAStructNode(Fields);
// For now, handle any other kind of type conservatively.
- return StructMetadataCache[Ty] = NULL;
+ return StructMetadataCache[Ty] = nullptr;
}
/// Check if the given type can be handled by path-aware TBAA.
@@ -261,7 +261,7 @@
else
FieldNode = getTBAAInfo(FieldQTy);
if (!FieldNode)
- return StructTypeMetadataCache[Ty] = NULL;
+ return StructTypeMetadataCache[Ty] = nullptr;
Fields.push_back(std::make_pair(
FieldNode, Layout.getFieldOffset(idx) / Context.getCharWidth()));
}
@@ -280,7 +280,7 @@
MDHelper.createTBAAStructTypeNode(OutName, Fields);
}
- return StructMetadataCache[Ty] = NULL;
+ return StructMetadataCache[Ty] = nullptr;
}
/// Return a TBAA tag node for both scalar TBAA and struct-path aware TBAA.
@@ -288,7 +288,7 @@
CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,
uint64_t Offset) {
if (!AccessNode)
- return NULL;
+ return nullptr;
if (!CodeGenOpts.StructPathTBAA)
return getTBAAScalarTagInfo(AccessNode);
@@ -298,7 +298,7 @@
if (llvm::MDNode *N = StructTagMetadataCache[PathTag])
return N;
- llvm::MDNode *BNode = 0;
+ llvm::MDNode *BNode = nullptr;
if (isTBAAPathStruct(BaseQTy))
BNode = getTBAAStructTypeInfo(BaseQTy);
if (!BNode)
@@ -312,7 +312,7 @@
llvm::MDNode *
CodeGenTBAA::getTBAAScalarTagInfo(llvm::MDNode *AccessNode) {
if (!AccessNode)
- return NULL;
+ return nullptr;
if (llvm::MDNode *N = ScalarTagMetadataCache[AccessNode])
return N;
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index b7f3746..d4e2262 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -189,15 +189,15 @@
bool CodeGenTypes::isFuncParamTypeConvertible(QualType Ty) {
// If this isn't a tagged type, we can convert it!
const TagType *TT = Ty->getAs<TagType>();
- if (TT == 0) return true;
-
+ if (!TT) return true;
+
// Incomplete types cannot be converted.
if (TT->isIncompleteType())
return false;
// If this is an enum, then it is always safe to convert.
const RecordType *RT = dyn_cast<RecordType>(TT);
- if (RT == 0) return true;
+ if (!RT) return true;
// Otherwise, we have to be careful. If it is a struct that we're in the
// process of expanding, then we can't convert the function type. That's ok
@@ -242,6 +242,10 @@
if (!ConvertType(ED->getIntegerType())->isIntegerTy(32))
TypeCache.clear();
}
+ // If necessary, provide the full definition of a type only used with a
+ // declaration so far.
+ if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
+ DI->completeType(ED);
return;
}
@@ -300,7 +304,7 @@
return TCI->second;
// If we don't have it in the cache, convert it now.
- llvm::Type *ResultType = 0;
+ llvm::Type *ResultType = nullptr;
switch (Ty->getTypeClass()) {
case Type::Record: // Handled above.
#define TYPE(Class, Base)
@@ -625,7 +629,7 @@
llvm::StructType *&Entry = RecordDeclTypes[Key];
// If we don't have a StructType at all yet, create the forward declaration.
- if (Entry == 0) {
+ if (!Entry) {
Entry = llvm::StructType::create(getLLVMContext());
addRecordTypeName(RD, Entry, "");
}
@@ -634,7 +638,7 @@
// If this is still a forward declaration, or the LLVM type is already
// complete, there's nothing more to do.
RD = RD->getDefinition();
- if (RD == 0 || !RD->isCompleteDefinition() || !Ty->isOpaque())
+ if (!RD || !RD->isCompleteDefinition() || !Ty->isOpaque())
return Ty;
// If converting this type would cause us to infinitely loop, don't do it!
diff --git a/lib/CodeGen/EHScopeStack.h b/lib/CodeGen/EHScopeStack.h
index 166d420..b9ccfb6 100644
--- a/lib/CodeGen/EHScopeStack.h
+++ b/lib/CodeGen/EHScopeStack.h
@@ -301,8 +301,8 @@
void *pushCleanup(CleanupKind K, size_t DataSize);
public:
- EHScopeStack() : StartOfBuffer(0), EndOfBuffer(0), StartOfData(0),
- InnermostNormalCleanup(stable_end()),
+ EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr),
+ StartOfData(nullptr), InnermostNormalCleanup(stable_end()),
InnermostEHScope(stable_end()) {}
~EHScopeStack() { delete[] StartOfBuffer; }
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 27825ab..f5d2372 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -52,16 +52,14 @@
CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
UseARMGuardVarABI(UseARMGuardVarABI) { }
- bool isReturnTypeIndirect(const CXXRecordDecl *RD) const override {
- // Structures with either a non-trivial destructor or a non-trivial
- // copy constructor are always indirect.
- return !RD->hasTrivialDestructor() || RD->hasNonTrivialCopyConstructor();
- }
+ bool classifyReturnType(CGFunctionInfo &FI) const override;
RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
- if (!RD->hasTrivialDestructor() || RD->hasNonTrivialCopyConstructor())
+ // FIXME: Use canCopyArgument() when it is fixed to handle lazily declared
+ // special members.
+ if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor())
return RAA_Indirect;
return RAA_Default;
}
@@ -761,6 +759,21 @@
return Result;
}
+bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
+ const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
+ if (!RD)
+ return false;
+
+ // Return indirectly if we have a non-trivial copy ctor or non-trivial dtor.
+ // FIXME: Use canCopyArgument() when it is fixed to handle lazily declared
+ // special members.
+ if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor()) {
+ FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return true;
+ }
+ return false;
+}
+
/// The Itanium ABI requires non-zero initialization only for data
/// member pointers, for which '0' is a valid offset.
bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
@@ -886,7 +899,7 @@
// FIXME: avoid the fake decl
QualType T = Context.getPointerType(Context.VoidPtrTy);
ImplicitParamDecl *VTTDecl
- = ImplicitParamDecl::Create(Context, 0, MD->getLocation(),
+ = ImplicitParamDecl::Create(Context, nullptr, MD->getLocation(),
&Context.Idents.get("vtt"), T);
Params.insert(Params.begin() + 1, VTTDecl);
getStructorImplicitParamDecl(CGF) = VTTDecl;
@@ -938,7 +951,7 @@
llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
- llvm::Value *Callee = 0;
+ llvm::Value *Callee = nullptr;
if (getContext().getLangOpts().AppleKext)
Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent());
@@ -947,7 +960,7 @@
// FIXME: Provide a source location here.
CGF.EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
- VTT, VTTTy, 0, 0);
+ VTT, VTTTy, nullptr, nullptr);
}
void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -1087,7 +1100,8 @@
getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty);
CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
- /*ImplicitParam=*/0, QualType(), 0, 0);
+ /*ImplicitParam=*/nullptr, QualType(), nullptr,
+ nullptr);
}
void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
@@ -1393,25 +1407,7 @@
}
// Test whether the variable has completed initialization.
- llvm::Value *isInitialized;
-
- // ARM C++ ABI 3.2.3.1:
- // To support the potential use of initialization guard variables
- // as semaphores that are the target of ARM SWP and LDREX/STREX
- // synchronizing instructions we define a static initialization
- // guard variable to be a 4-byte aligned, 4- byte word with the
- // following inline access protocol.
- // #define INITIALIZED 1
- // if ((obj_guard & INITIALIZED) != INITIALIZED) {
- // if (__cxa_guard_acquire(&obj_guard))
- // ...
- // }
- if (UseARMGuardVarABI && !useInt8GuardVariable) {
- llvm::Value *V = Builder.CreateLoad(guard);
- llvm::Value *Test1 = llvm::ConstantInt::get(guardTy, 1);
- V = Builder.CreateAnd(V, Test1);
- isInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
-
+ //
// Itanium C++ ABI 3.3.2:
// The following is pseudo-code showing how these functions can be used:
// if (obj_guard.first_byte == 0) {
@@ -1427,29 +1423,45 @@
// }
// }
- // ARM64 C++ ABI 3.2.2:
- // This ABI instead only specifies the value bit 0 of the static guard
- // variable; all other bits are platform defined. Bit 0 shall be 0 when the
- // variable is not initialized and 1 when it is.
- // FIXME: Reading one bit is no more efficient than reading one byte so
- // the codegen is same as generic Itanium ABI.
- } else {
- // Load the first byte of the guard variable.
- llvm::LoadInst *LI =
+ // Load the first byte of the guard variable.
+ llvm::LoadInst *LI =
Builder.CreateLoad(Builder.CreateBitCast(guard, CGM.Int8PtrTy));
- LI->setAlignment(1);
+ LI->setAlignment(1);
- // Itanium ABI:
- // An implementation supporting thread-safety on multiprocessor
- // systems must also guarantee that references to the initialized
- // object do not occur before the load of the initialization flag.
- //
- // In LLVM, we do this by marking the load Acquire.
- if (threadsafe)
- LI->setAtomic(llvm::Acquire);
+ // Itanium ABI:
+ // An implementation supporting thread-safety on multiprocessor
+ // systems must also guarantee that references to the initialized
+ // object do not occur before the load of the initialization flag.
+ //
+ // In LLVM, we do this by marking the load Acquire.
+ if (threadsafe)
+ LI->setAtomic(llvm::Acquire);
- isInitialized = Builder.CreateIsNull(LI, "guard.uninitialized");
- }
+ // For ARM, we should only check the first bit, rather than the entire byte:
+ //
+ // ARM C++ ABI 3.2.3.1:
+ // To support the potential use of initialization guard variables
+ // as semaphores that are the target of ARM SWP and LDREX/STREX
+ // synchronizing instructions we define a static initialization
+ // guard variable to be a 4-byte aligned, 4-byte word with the
+ // following inline access protocol.
+ // #define INITIALIZED 1
+ // if ((obj_guard & INITIALIZED) != INITIALIZED) {
+ // if (__cxa_guard_acquire(&obj_guard))
+ // ...
+ // }
+ //
+ // and similarly for ARM64:
+ //
+ // ARM64 C++ ABI 3.2.2:
+ // This ABI instead only specifies the value bit 0 of the static guard
+ // variable; all other bits are platform defined. Bit 0 shall be 0 when the
+ // variable is not initialized and 1 when it is.
+ llvm::Value *V =
+ (UseARMGuardVarABI && !useInt8GuardVariable)
+ ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
+ : LI;
+ llvm::Value *isInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
@@ -1584,10 +1596,12 @@
llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, false);
llvm::Function *Wrapper = llvm::Function::Create(
- FnTy, getThreadLocalWrapperLinkage(Var->getLinkage()), WrapperName.str(),
- &CGM.getModule());
+ FnTy, getThreadLocalWrapperLinkage(
+ CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)),
+ WrapperName.str(), &CGM.getModule());
// Always resolve references to the wrapper at link time.
- Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ if (!Wrapper->hasLocalLinkage())
+ Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
return Wrapper;
}
@@ -1609,14 +1623,13 @@
// If we have a definition for the variable, emit the initialization
// function as an alias to the global Init function (if any). Otherwise,
// produce a declaration of the initialization function.
- llvm::GlobalValue *Init = 0;
+ llvm::GlobalValue *Init = nullptr;
bool InitIsInitFunc = false;
if (VD->hasDefinition()) {
InitIsInitFunc = true;
if (InitFunc)
- Init =
- new llvm::GlobalAlias(InitFunc->getType(), Var->getLinkage(),
- InitFnName.str(), InitFunc, &CGM.getModule());
+ Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
+ InitFunc);
} else {
// Emit a weak global function referring to the initialization function.
// This function will not exist if the TU defining the thread_local
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 9832969..dee565a 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -39,29 +39,18 @@
bool HasThisReturn(GlobalDecl GD) const override;
- bool isReturnTypeIndirect(const CXXRecordDecl *RD) const override {
- // Structures that are not C++03 PODs are always indirect.
- return !RD->isPOD();
- }
+ bool classifyReturnType(CGFunctionInfo &FI) const override;
- RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
- if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialDestructor()) {
- llvm::Triple::ArchType Arch = CGM.getTarget().getTriple().getArch();
- if (Arch == llvm::Triple::x86)
- return RAA_DirectInMemory;
- // On x64, pass non-trivial records indirectly.
- // FIXME: Test other Windows architectures.
- return RAA_Indirect;
- }
- return RAA_Default;
- }
+ RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override;
+
+ bool isSRetParameterAfterThis() const override { return true; }
StringRef GetPureVirtualCallName() override { return "_purecall"; }
// No known support for deleted functions in MSVC yet, so this choice is
// arbitrary.
StringRef GetDeletedVirtualCallName() override { return "_purecall"; }
- bool isInlineInitializedStaticDataMemberLinkOnce() override{ return true; }
+ bool isInlineInitializedStaticDataMemberLinkOnce() override { return true; }
llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
llvm::Value *ptr,
@@ -143,7 +132,7 @@
// FIXME: might want to have a more precise type in the non-virtual
// multiple inheritance case.
if (ML.VBase || !ML.VFPtrOffset.isZero())
- return 0;
+ return nullptr;
}
return MD->getParent();
}
@@ -296,13 +285,13 @@
llvm::Value *Base,
llvm::Value *VBPtrOffset,
llvm::Value *VBTableOffset,
- llvm::Value **VBPtr = 0);
+ llvm::Value **VBPtr = nullptr);
llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
llvm::Value *Base,
int32_t VBPtrOffset,
int32_t VBTableOffset,
- llvm::Value **VBPtr = 0) {
+ llvm::Value **VBPtr = nullptr) {
llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
*VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset);
return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
@@ -395,7 +384,7 @@
/// Info on the global variable used to guard initialization of static locals.
/// The BitIndex field is only used for externally invisible declarations.
struct GuardInfo {
- GuardInfo() : Guard(0), BitIndex(0) {}
+ GuardInfo() : Guard(nullptr), BitIndex(0) {}
llvm::GlobalVariable *Guard;
unsigned BitIndex;
};
@@ -407,6 +396,60 @@
}
+CGCXXABI::RecordArgABI
+MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
+ switch (CGM.getTarget().getTriple().getArch()) {
+ default:
+ // FIXME: Implement for other architectures.
+ return RAA_Default;
+
+ case llvm::Triple::x86:
+ // All record arguments are passed in memory on x86. Decide whether to
+ // construct the object directly in argument memory, or to construct the
+ // argument elsewhere and copy the bytes during the call.
+
+ // If C++ prohibits us from making a copy, construct the arguments directly
+ // into argument memory.
+ if (!canCopyArgument(RD))
+ return RAA_DirectInMemory;
+
+ // Otherwise, construct the argument into a temporary and copy the bytes
+ // into the outgoing argument memory.
+ return RAA_Default;
+
+ case llvm::Triple::x86_64:
+ // Win64 passes objects with non-trivial copy ctors indirectly.
+ if (RD->hasNonTrivialCopyConstructor())
+ return RAA_Indirect;
+
+ // Win64 passes objects larger than 8 bytes indirectly.
+ if (getContext().getTypeSize(RD->getTypeForDecl()) > 64)
+ return RAA_Indirect;
+
+ // We have a trivial copy constructor or no copy constructors, but we have
+ // to make sure it isn't deleted.
+ bool CopyDeleted = false;
+ for (const CXXConstructorDecl *CD : RD->ctors()) {
+ if (CD->isCopyConstructor()) {
+ assert(CD->isTrivial());
+ // We had at least one undeleted trivial copy ctor. Return directly.
+ if (!CD->isDeleted())
+ return RAA_Default;
+ CopyDeleted = true;
+ }
+ }
+
+ // The trivial copy constructor was deleted. Return indirectly.
+ if (CopyDeleted)
+ return RAA_Indirect;
+
+ // There were no copy ctors. Return in RAX.
+ return RAA_Default;
+ }
+
+ llvm_unreachable("invalid enum");
+}
+
llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
llvm::Value *ptr,
QualType type) {
@@ -440,6 +483,27 @@
return isa<CXXConstructorDecl>(GD.getDecl());
}
+bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
+ const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
+ if (!RD)
+ return false;
+
+ if (FI.isInstanceMethod()) {
+ // If it's an instance method, aggregates are always returned indirectly via
+ // the second parameter.
+ FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
+ return true;
+ } else if (!RD->isPOD()) {
+ // If it's a free function, non-POD types are returned indirectly.
+ FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return true;
+ }
+
+ // Otherwise, use the C ABI rules.
+ return false;
+}
+
void MicrosoftCXXABI::BuildConstructorSignature(
const CXXConstructorDecl *Ctor, CXXCtorType Type, CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
@@ -503,7 +567,7 @@
unsigned AS =
cast<llvm::PointerType>(getThisValue(CGF)->getType())->getAddressSpace();
- llvm::Value *Int8This = 0; // Initialize lazily.
+ llvm::Value *Int8This = nullptr; // Initialize lazily.
for (VBOffsets::const_iterator I = VBaseMap.begin(), E = VBaseMap.end();
I != E; ++I) {
@@ -704,7 +768,7 @@
assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
ImplicitParamDecl *IsMostDerived
- = ImplicitParamDecl::Create(Context, 0,
+ = ImplicitParamDecl::Create(Context, nullptr,
CGF.CurGD.getDecl()->getLocation(),
&Context.Idents.get("is_most_derived"),
Context.IntTy);
@@ -718,7 +782,7 @@
getStructorImplicitParamDecl(CGF) = IsMostDerived;
} else if (IsDeletingDtor(CGF.CurGD)) {
ImplicitParamDecl *ShouldDelete
- = ImplicitParamDecl::Create(Context, 0,
+ = ImplicitParamDecl::Create(Context, nullptr,
CGF.CurGD.getDecl()->getLocation(),
&Context.Idents.get("should_call_delete"),
Context.IntTy);
@@ -823,7 +887,8 @@
// FIXME: Provide a source location here.
CGF.EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
- /*ImplicitParam=*/0, /*ImplicitParamTy=*/QualType(), 0, 0);
+ /*ImplicitParam=*/nullptr,
+ /*ImplicitParamTy=*/QualType(), nullptr, nullptr);
}
void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -832,14 +897,15 @@
VPtrInfoVector VFPtrs = VFTContext.getVFPtrOffsets(RD);
llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
- for (VPtrInfoVector::iterator I = VFPtrs.begin(), E = VFPtrs.end(); I != E;
- ++I) {
- llvm::GlobalVariable *VTable = getAddrOfVTable(RD, (*I)->FullOffsetInMDC);
+ for (VPtrInfo *Info : VFPtrs) {
+ llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC);
if (VTable->hasInitializer())
continue;
+ if (getContext().getLangOpts().RTTI)
+ CGM.getMSCompleteObjectLocator(RD, Info);
const VTableLayout &VTLayout =
- VFTContext.getVFTableLayout(RD, (*I)->FullOffsetInMDC);
+ VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC);
llvm::Constant *Init = CGVT.CreateVTableInitializer(
RD, VTLayout.vtable_component_begin(),
VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(),
@@ -854,7 +920,7 @@
llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
- NeedsVirtualOffset = (NearestVBase != 0);
+ NeedsVirtualOffset = (NearestVBase != nullptr);
llvm::Value *VTableAddressPoint =
getAddrOfVTable(VTableClass, Base.getBaseOffset());
@@ -887,8 +953,7 @@
VFTableIdTy ID(RD, VPtrOffset);
VFTablesMapTy::iterator I;
bool Inserted;
- std::tie(I, Inserted) = VFTablesMap.insert(
- std::make_pair(ID, static_cast<llvm::GlobalVariable *>(0)));
+ std::tie(I, Inserted) = VFTablesMap.insert(std::make_pair(ID, nullptr));
if (!Inserted)
return I->second;
@@ -976,7 +1041,7 @@
This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);
CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
- ImplicitParam, Context.IntTy, 0, 0);
+ ImplicitParam, Context.IntTy, nullptr, nullptr);
}
const VBTableGlobals &
@@ -1047,8 +1112,31 @@
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
llvm::Value *Callee = CGF.Builder.CreateLoad(VFuncPtr);
- // Make the call and return the result.
- CGF.EmitCallAndReturnForThunk(MD, Callee, 0);
+ unsigned CallingConv;
+ CodeGen::AttributeListType AttributeList;
+ CGM.ConstructAttributeList(FnInfo, MD, AttributeList, CallingConv, true);
+ llvm::AttributeSet Attrs =
+ llvm::AttributeSet::get(CGF.getLLVMContext(), AttributeList);
+
+ // Do a musttail call with perfect argument forwarding. Any inalloca argument
+ // will be forwarded in place without any copy.
+ SmallVector<llvm::Value *, 8> Args;
+ for (llvm::Argument &A : ThunkFn->args())
+ Args.push_back(&A);
+ llvm::CallInst *Call = CGF.Builder.CreateCall(Callee, Args);
+ Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
+ Call->setAttributes(Attrs);
+ Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
+
+ if (Call->getType()->isVoidTy())
+ CGF.Builder.CreateRetVoid();
+ else
+ CGF.Builder.CreateRet(Call);
+
+ // Finish the function to maintain CodeGenFunction invariants.
+ // FIXME: Don't emit unreachable code.
+ CGF.EmitBlock(CGF.createBasicBlock());
+ CGF.FinishFunction();
return ThunkFn;
}
@@ -1097,7 +1185,8 @@
const ASTRecordLayout &DerivedLayout =
CGM.getContext().getASTRecordLayout(RD);
- SmallVector<llvm::Constant *, 4> Offsets(1 + ReusingBase->getNumVBases(), 0);
+ SmallVector<llvm::Constant *, 4> Offsets(1 + ReusingBase->getNumVBases(),
+ nullptr);
// The offset from ReusingBase's vbptr to itself always leads.
CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset();
@@ -1117,7 +1206,7 @@
Offset -= CompleteVBPtrOffset;
unsigned VBIndex = Context.getVBTableIndex(ReusingBase, VBase);
- assert(Offsets[VBIndex] == 0 && "The same vbindex seen twice?");
+ assert(Offsets[VBIndex] == nullptr && "The same vbindex seen twice?");
Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity());
}
@@ -1260,6 +1349,15 @@
void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
llvm::GlobalVariable *GV,
bool PerformInit) {
+ // MSVC only uses guards for static locals.
+ if (!D.isStaticLocal()) {
+ assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage());
+ // GlobalOpt is allowed to discard the initializer, so use linkonce_odr.
+ CGF.CurFn->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
+ CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
+ return;
+ }
+
// MSVC always uses an i32 bitfield to guard initialization, which is *not*
// threadsafe. Since the user may be linking in inline functions compiled by
// cl.exe, there's no reason to provide a false sense of security by using
@@ -1273,10 +1371,10 @@
llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0);
// Get the guard variable for this function if we have one already.
- GuardInfo &GI = GuardVariableMap[D.getDeclContext()];
+ GuardInfo *GI = &GuardVariableMap[D.getDeclContext()];
unsigned BitIndex;
- if (D.isExternallyVisible()) {
+ if (D.isStaticLocal() && D.isExternallyVisible()) {
// Externally visible variables have to be numbered in Sema to properly
// handle unreachable VarDecls.
BitIndex = getContext().getStaticLocalNumber(&D);
@@ -1284,18 +1382,18 @@
BitIndex--;
} else {
// Non-externally visible variables are numbered here in CodeGen.
- BitIndex = GI.BitIndex++;
+ BitIndex = GI->BitIndex++;
}
if (BitIndex >= 32) {
if (D.isExternallyVisible())
ErrorUnsupportedABI(CGF, "more than 32 guarded initializations");
BitIndex %= 32;
- GI.Guard = 0;
+ GI->Guard = nullptr;
}
// Lazily create the i32 bitfield for this function.
- if (!GI.Guard) {
+ if (!GI->Guard) {
// Mangle the name for the guard.
SmallString<256> GuardName;
{
@@ -1306,11 +1404,12 @@
// Create the guard variable with a zero-initializer. Just absorb linkage
// and visibility from the guarded variable.
- GI.Guard = new llvm::GlobalVariable(CGM.getModule(), GuardTy, false,
- GV->getLinkage(), Zero, GuardName.str());
- GI.Guard->setVisibility(GV->getVisibility());
+ GI->Guard =
+ new llvm::GlobalVariable(CGM.getModule(), GuardTy, false,
+ GV->getLinkage(), Zero, GuardName.str());
+ GI->Guard->setVisibility(GV->getVisibility());
} else {
- assert(GI.Guard->getLinkage() == GV->getLinkage() &&
+ assert(GI->Guard->getLinkage() == GV->getLinkage() &&
"static local from the same function had different linkage");
}
@@ -1322,7 +1421,7 @@
// Test our bit from the guard variable.
llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1U << BitIndex);
- llvm::LoadInst *LI = Builder.CreateLoad(GI.Guard);
+ llvm::LoadInst *LI = Builder.CreateLoad(GI->Guard);
llvm::Value *IsInitialized =
Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
@@ -1332,7 +1431,7 @@
// Set our bit in the guard variable and emit the initializer and add a global
// destructor if appropriate.
CGF.EmitBlock(InitBlock);
- Builder.CreateStore(Builder.CreateOr(LI, Bit), GI.Guard);
+ Builder.CreateStore(Builder.CreateOr(LI, Bit), GI->Guard);
CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
Builder.CreateBr(EndBlock);
@@ -1572,7 +1671,7 @@
llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0, "memptr.cmp.first");
// Compare everything other than the first field.
- llvm::Value *Res = 0;
+ llvm::Value *Res = nullptr;
llvm::StructType *LType = cast<llvm::StructType>(L->getType());
for (unsigned I = 1, E = LType->getNumElements(); I != E; ++I) {
llvm::Value *LF = Builder.CreateExtractValue(L, I);
@@ -1623,7 +1722,7 @@
for (int I = 1, E = fields.size(); I < E; ++I) {
llvm::Value *Field = Builder.CreateExtractValue(MemPtr, I);
llvm::Value *Next = Builder.CreateICmpNE(Field, fields[I], "memptr.cmp");
- Res = Builder.CreateAnd(Res, Next, "memptr.tobool");
+ Res = Builder.CreateOr(Res, Next, "memptr.tobool");
}
return Res;
}
@@ -1687,9 +1786,9 @@
llvm::Value *Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
CGBuilderTy &Builder = CGF.Builder;
Base = Builder.CreateBitCast(Base, CGM.Int8PtrTy);
- llvm::BasicBlock *OriginalBB = 0;
- llvm::BasicBlock *SkipAdjustBB = 0;
- llvm::BasicBlock *VBaseAdjustBB = 0;
+ llvm::BasicBlock *OriginalBB = nullptr;
+ llvm::BasicBlock *SkipAdjustBB = nullptr;
+ llvm::BasicBlock *VBaseAdjustBB = nullptr;
// In the unspecified inheritance model, there might not be a vbtable at all,
// in which case we need to skip the virtual base lookup. If there is a
@@ -1721,7 +1820,7 @@
offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity());
}
- llvm::Value *VBPtr = 0;
+ llvm::Value *VBPtr = nullptr;
llvm::Value *VBaseOffs =
GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr);
llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs);
@@ -1752,8 +1851,8 @@
// Extract the fields we need, regardless of model. We'll apply them if we
// have them.
llvm::Value *FieldOffset = MemPtr;
- llvm::Value *VirtualBaseAdjustmentOffset = 0;
- llvm::Value *VBPtrOffset = 0;
+ llvm::Value *VirtualBaseAdjustmentOffset = nullptr;
+ llvm::Value *VBPtrOffset = nullptr;
if (MemPtr->getType()->isStructTy()) {
// We need to extract values.
unsigned I = 0;
@@ -1839,9 +1938,9 @@
// Decompose src.
llvm::Value *FirstField = Src;
- llvm::Value *NonVirtualBaseAdjustment = 0;
- llvm::Value *VirtualBaseAdjustmentOffset = 0;
- llvm::Value *VBPtrOffset = 0;
+ llvm::Value *NonVirtualBaseAdjustment = nullptr;
+ llvm::Value *VirtualBaseAdjustmentOffset = nullptr;
+ llvm::Value *VBPtrOffset = nullptr;
MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel();
if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) {
// We need to extract values.
@@ -1924,9 +2023,9 @@
// Decompose src.
llvm::Constant *FirstField = Src;
- llvm::Constant *NonVirtualBaseAdjustment = 0;
- llvm::Constant *VirtualBaseAdjustmentOffset = 0;
- llvm::Constant *VBPtrOffset = 0;
+ llvm::Constant *NonVirtualBaseAdjustment = nullptr;
+ llvm::Constant *VirtualBaseAdjustmentOffset = nullptr;
+ llvm::Constant *VBPtrOffset = nullptr;
bool IsFunc = SrcTy->isMemberFunctionPointer();
if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) {
// We need to extract values.
@@ -1990,9 +2089,9 @@
// Extract the fields we need, regardless of model. We'll apply them if we
// have them.
llvm::Value *FunctionPointer = MemPtr;
- llvm::Value *NonVirtualBaseAdjustment = NULL;
- llvm::Value *VirtualBaseAdjustmentOffset = NULL;
- llvm::Value *VBPtrOffset = NULL;
+ llvm::Value *NonVirtualBaseAdjustment = nullptr;
+ llvm::Value *VirtualBaseAdjustmentOffset = nullptr;
+ llvm::Value *VBPtrOffset = nullptr;
if (MemPtr->getType()->isStructTy()) {
// We need to extract values.
unsigned I = 0;
diff --git a/lib/CodeGen/MicrosoftRTTI.cpp b/lib/CodeGen/MicrosoftRTTI.cpp
new file mode 100644
index 0000000..0eb8100
--- /dev/null
+++ b/lib/CodeGen/MicrosoftRTTI.cpp
@@ -0,0 +1,447 @@
+//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of RTTI descriptors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+#include "CGObjCRuntime.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Frontend/CodeGenOptions.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+// MS RTTI Overview:
+// The run time type information emitted by cl.exe contains 5 distinct types of
+// structures. Many of them reference each other.
+//
+// TypeInfo: Static classes that are returned by typeid.
+//
+// CompleteObjectLocator: Referenced by vftables. They contain information
+// required for dynamic casting, including OffsetFromTop. They also contain
+// a reference to the TypeInfo for the type and a reference to the
+// CompleteHierarchyDescriptor for the type.
+//
+// ClassHieararchyDescriptor: Contains information about a class hierarchy.
+// Used during dynamic_cast to walk a class hierarchy. References a base
+// class array and the size of said array.
+//
+// BaseClassArray: Contains a list of classes in a hierarchy. BaseClassArray is
+// somewhat of a misnomer because the most derived class is also in the list
+// as well as multiple copies of virtual bases (if they occur multiple times
+// in the hiearchy.) The BaseClassArray contains one BaseClassDescriptor for
+// every path in the hierarchy, in pre-order depth first order. Note, we do
+// not declare a specific llvm type for BaseClassArray, it's merely an array
+// of BaseClassDescriptor pointers.
+//
+// BaseClassDescriptor: Contains information about a class in a class hierarchy.
+// BaseClassDescriptor is also somewhat of a misnomer for the same reason that
+// BaseClassArray is. It contains information about a class within a
+// hierarchy such as: is this base is ambiguous and what is its offset in the
+// vbtable. The names of the BaseClassDescriptors have all of their fields
+// mangled into them so they can be aggressively deduplicated by the linker.
+
+// 5 routines for constructing the llvm types for MS RTTI structs.
+static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM);
+
+static llvm::StructType *getTypeDescriptorType(CodeGenModule &CGM,
+ StringRef TypeInfoString) {
+ llvm::SmallString<32> TDTypeName("MSRTTITypeDescriptor");
+ TDTypeName += TypeInfoString.size();
+ if (auto Type = CGM.getModule().getTypeByName(TDTypeName))
+ return Type;
+ llvm::Type *FieldTypes[] = {
+ CGM.Int8PtrPtrTy,
+ CGM.Int8PtrTy,
+ llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)};
+ return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName);
+}
+
+static llvm::StructType *getBaseClassDescriptorType(CodeGenModule &CGM) {
+ static const char Name[] = "MSRTTIBaseClassDescriptor";
+ if (auto Type = CGM.getModule().getTypeByName(Name))
+ return Type;
+ llvm::Type *FieldTypes[] = {
+ CGM.Int8PtrTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ getClassHierarchyDescriptorType(CGM)->getPointerTo()};
+ return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
+}
+
+static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM) {
+ static const char Name[] = "MSRTTIClassHierarchyDescriptor";
+ if (auto Type = CGM.getModule().getTypeByName(Name))
+ return Type;
+ // Forward declare RTTIClassHierarchyDescriptor to break a cycle.
+ llvm::StructType *Type = llvm::StructType::create(CGM.getLLVMContext(), Name);
+ llvm::Type *FieldTypes[] = {
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ getBaseClassDescriptorType(CGM)->getPointerTo()->getPointerTo()};
+ Type->setBody(FieldTypes);
+ return Type;
+}
+
+static llvm::StructType *getCompleteObjectLocatorType(CodeGenModule &CGM) {
+ static const char Name[] = "MSRTTICompleteObjectLocator";
+ if (auto Type = CGM.getModule().getTypeByName(Name))
+ return Type;
+ llvm::Type *FieldTypes[] = {
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.Int8PtrTy,
+ getClassHierarchyDescriptorType(CGM)->getPointerTo() };
+ return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
+}
+
+static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
+ StringRef MangledName("\01??_7type_info@@6B@");
+ if (auto VTable = CGM.getModule().getNamedGlobal(MangledName))
+ return VTable;
+ return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
+ /*Constant=*/true,
+ llvm::GlobalVariable::ExternalLinkage,
+ /*Initializer=*/0, MangledName);
+}
+
+namespace {
+
+/// \brief A Helper struct that stores information about a class in a class
+/// hierarchy. The information stored in these structs struct is used during
+/// the generation of ClassHierarchyDescriptors and BaseClassDescriptors.
+// During RTTI creation, MSRTTIClasses are stored in a contiguous array with
+// implicit depth first pre-order tree connectivity. getFirstChild and
+// getNextSibling allow us to walk the tree efficiently.
+struct MSRTTIClass {
+ enum {
+ IsPrivateOnPath = 1 | 8,
+ IsAmbiguous = 2,
+ IsPrivate = 4,
+ IsVirtual = 16,
+ HasHierarchyDescriptor = 64
+ };
+ MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {}
+ uint32_t initialize(const MSRTTIClass *Parent,
+ const CXXBaseSpecifier *Specifier);
+
+ MSRTTIClass *getFirstChild() { return this + 1; }
+ static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
+ return Child + 1 + Child->NumBases;
+ }
+
+ const CXXRecordDecl *RD, *VirtualRoot;
+ uint32_t Flags, NumBases, OffsetInVBase;
+};
+
+/// \brief Recursively initialize the base class array.
+uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent,
+ const CXXBaseSpecifier *Specifier) {
+ Flags = HasHierarchyDescriptor;
+ if (!Parent) {
+ VirtualRoot = 0;
+ OffsetInVBase = 0;
+ } else {
+ if (Specifier->getAccessSpecifier() != AS_public)
+ Flags |= IsPrivate | IsPrivateOnPath;
+ if (Specifier->isVirtual()) {
+ Flags |= IsVirtual;
+ VirtualRoot = RD;
+ OffsetInVBase = 0;
+ } else {
+ if (Parent->Flags & IsPrivateOnPath)
+ Flags |= IsPrivateOnPath;
+ VirtualRoot = Parent->VirtualRoot;
+ OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()
+ .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();
+ }
+ }
+ NumBases = 0;
+ MSRTTIClass *Child = getFirstChild();
+ for (const CXXBaseSpecifier &Base : RD->bases()) {
+ NumBases += Child->initialize(this, &Base) + 1;
+ Child = getNextChild(Child);
+ }
+ return NumBases;
+}
+
+/// \brief An ephemeral helper class for building MS RTTI types. It caches some
+/// calls to the module and information about the most derived class in a
+/// hierarchy.
+struct MSRTTIBuilder {
+ enum {
+ HasBranchingHierarchy = 1,
+ HasVirtualBranchingHierarchy = 2,
+ HasAmbiguousBases = 4
+ };
+
+ MSRTTIBuilder(CodeGenModule &CGM, const CXXRecordDecl *RD)
+ : CGM(CGM), Context(CGM.getContext()), VMContext(CGM.getLLVMContext()),
+ Module(CGM.getModule()), RD(RD), Linkage(CGM.getVTableLinkage(RD)),
+ Mangler(
+ cast<MicrosoftMangleContext>(CGM.getCXXABI().getMangleContext())) {}
+
+ llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes);
+ llvm::GlobalVariable *
+ getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
+ llvm::GlobalVariable *getClassHierarchyDescriptor();
+ llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo *Info);
+
+ CodeGenModule &CGM;
+ ASTContext &Context;
+ llvm::LLVMContext &VMContext;
+ llvm::Module &Module;
+ const CXXRecordDecl *RD;
+ llvm::GlobalVariable::LinkageTypes Linkage;
+ MicrosoftMangleContext &Mangler;
+};
+
+} // namespace
+
+/// \brief Recursively serializes a class hierarchy in pre-order depth first
+/// order.
+static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes,
+ const CXXRecordDecl *RD) {
+ Classes.push_back(MSRTTIClass(RD));
+ for (const CXXBaseSpecifier &Base : RD->bases())
+ serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl());
+}
+
+/// \brief Find ambiguity among base classes.
+static void
+detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases;
+ for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
+ if ((Class->Flags & MSRTTIClass::IsVirtual) &&
+ !VirtualBases.insert(Class->RD)) {
+ Class = MSRTTIClass::getNextChild(Class);
+ continue;
+ }
+ if (!UniqueBases.insert(Class->RD))
+ AmbiguousBases.insert(Class->RD);
+ Class++;
+ }
+ if (AmbiguousBases.empty())
+ return;
+ for (MSRTTIClass &Class : Classes)
+ if (AmbiguousBases.count(Class.RD))
+ Class.Flags |= MSRTTIClass::IsAmbiguous;
+}
+
+llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ Mangler.mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
+ }
+
+ // Check to see if we've already declared this ClassHierarchyDescriptor.
+ if (auto CHD = Module.getNamedGlobal(MangledName))
+ return CHD;
+
+ // Serialize the class hierarchy and initalize the CHD Fields.
+ SmallVector<MSRTTIClass, 8> Classes;
+ serializeClassHierarchy(Classes, RD);
+ Classes.front().initialize(/*Parent=*/0, /*Specifier=*/0);
+ detectAmbiguousBases(Classes);
+ int Flags = 0;
+ for (auto Class : Classes) {
+ if (Class.RD->getNumBases() > 1)
+ Flags |= HasBranchingHierarchy;
+ // Note: cl.exe does not calculate "HasAmbiguousBases" correctly. We
+ // believe the field isn't actually used.
+ if (Class.Flags & MSRTTIClass::IsAmbiguous)
+ Flags |= HasAmbiguousBases;
+ }
+ if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
+ Flags |= HasVirtualBranchingHierarchy;
+ // These gep indices are used to get the address of the first element of the
+ // base class array.
+ llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
+ llvm::ConstantInt::get(CGM.IntTy, 0)};
+
+ // Forward declare the class hierarchy descriptor
+ auto Type = getClassHierarchyDescriptorType(CGM);
+ auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+ /*Initializer=*/0, MangledName.c_str());
+
+ // 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()),
+ llvm::ConstantExpr::getInBoundsGetElementPtr(
+ getBaseClassArray(Classes),
+ llvm::ArrayRef<llvm::Value *>(GEPIndices))};
+ CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+ return CHD;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ Mangler.mangleCXXRTTIBaseClassArray(RD, Out);
+ }
+
+ // Foward declare the base class array.
+ // cl.exe pads the base class array with 1 (in 32 bit mode) or 4 (in 64 bit
+ // mode) bytes of padding. We provide a pointer sized amount of padding by
+ // adding +1 to Classes.size(). The sections have pointer alignment and are
+ // marked pick-any so it shouldn't matter.
+ auto PtrType = getBaseClassDescriptorType(CGM)->getPointerTo();
+ auto ArrayType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
+ auto BCA = new llvm::GlobalVariable(Module, ArrayType,
+ /*Constant=*/true, Linkage, /*Initializer=*/0, MangledName.c_str());
+
+ // Initialize the BaseClassArray.
+ SmallVector<llvm::Constant *, 8> BaseClassArrayData;
+ for (MSRTTIClass &Class : Classes)
+ BaseClassArrayData.push_back(getBaseClassDescriptor(Class));
+ BaseClassArrayData.push_back(llvm::ConstantPointerNull::get(PtrType));
+ BCA->setInitializer(llvm::ConstantArray::get(ArrayType, BaseClassArrayData));
+ return BCA;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
+ // Compute the fields for the BaseClassDescriptor. They are computed up front
+ // because they are mangled into the name of the object.
+ uint32_t OffsetInVBTable = 0;
+ int32_t VBPtrOffset = -1;
+ if (Class.VirtualRoot) {
+ auto &VTableContext = CGM.getMicrosoftVTableContext();
+ OffsetInVBTable = VTableContext.getVBTableIndex(RD, Class.VirtualRoot) * 4;
+ VBPtrOffset = Context.getASTRecordLayout(RD).getVBPtrOffset().getQuantity();
+ }
+
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ Mangler.mangleCXXRTTIBaseClassDescriptor(Class.RD, Class.OffsetInVBase,
+ VBPtrOffset, OffsetInVBTable,
+ Class.Flags, Out);
+ }
+
+ // Check to see if we've already declared declared this object.
+ if (auto BCD = Module.getNamedGlobal(MangledName))
+ return BCD;
+
+ // Forward declare the base class descriptor.
+ auto Type = getBaseClassDescriptorType(CGM);
+ auto BCD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+ /*Initializer=*/0, MangledName.c_str());
+
+ // Initialize the BaseClassDescriptor.
+ llvm::Constant *Fields[] = {
+ CGM.getMSTypeDescriptor(Context.getTypeDeclType(Class.RD)),
+ llvm::ConstantInt::get(CGM.IntTy, Class.NumBases),
+ llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase),
+ llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
+ llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable),
+ llvm::ConstantInt::get(CGM.IntTy, Class.Flags),
+ MSRTTIBuilder(CGM, Class.RD).getClassHierarchyDescriptor()};
+ BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+ return BCD;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ Mangler.mangleCXXRTTICompleteObjectLocator(RD, Info->MangledPath, Out);
+ }
+
+ // Check to see if we've already computed this complete object locator.
+ if (auto COL = Module.getNamedGlobal(MangledName))
+ return COL;
+
+ // Compute the fields of the complete object locator.
+ int OffsetToTop = Info->FullOffsetInMDC.getQuantity();
+ int VFPtrOffset = 0;
+ // The offset includes the vtordisp if one exists.
+ if (const CXXRecordDecl *VBase = Info->getVBaseWithVPtr())
+ if (Context.getASTRecordLayout(RD)
+ .getVBaseOffsetsMap()
+ .find(VBase)
+ ->second.hasVtorDisp())
+ VFPtrOffset = Info->NonVirtualOffset.getQuantity() + 4;
+
+ // Forward declare the complete object locator.
+ llvm::StructType *Type = getCompleteObjectLocatorType(CGM);
+ auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+ /*Initializer=*/0, MangledName.c_str());
+
+ // Initialize the CompleteObjectLocator.
+ llvm::Constant *Fields[] = {
+ llvm::ConstantInt::get(CGM.IntTy, 0), // IsDeltaEncoded
+ llvm::ConstantInt::get(CGM.IntTy, OffsetToTop),
+ llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset),
+ CGM.getMSTypeDescriptor(Context.getTypeDeclType(RD)),
+ getClassHierarchyDescriptor()};
+ COL->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+ return COL;
+}
+
+
+/// \brief Gets a TypeDescriptor. Returns a llvm::Constant * rather than a
+/// llvm::GlobalVariable * because different type descriptors have different
+/// types, and need to be abstracted. They are abstracting by casting the
+/// address to an Int8PtrTy.
+llvm::Constant *CodeGenModule::getMSTypeDescriptor(QualType Type) {
+ auto &Mangler(cast<MicrosoftMangleContext>(getCXXABI().getMangleContext()));
+ SmallString<256> MangledName, TypeInfoString;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ Mangler.mangleCXXRTTI(Type, Out);
+ }
+
+ // Check to see if we've already declared this TypeDescriptor.
+ if (auto TypeDescriptor = getModule().getNamedGlobal(MangledName))
+ return llvm::ConstantExpr::getBitCast(TypeDescriptor, Int8PtrTy);
+
+ // Compute the fields for the TypeDescriptor.
+ {
+ llvm::raw_svector_ostream Out(TypeInfoString);
+ Mangler.mangleCXXRTTIName(Type, Out);
+ }
+
+ // Declare and initialize the TypeDescriptor.
+ llvm::Constant *Fields[] = {
+ getTypeInfoVTable(*this), // VFPtr
+ llvm::ConstantPointerNull::get(Int8PtrTy), // Runtime data
+ llvm::ConstantDataArray::getString(VMContext, TypeInfoString)};
+ auto TypeDescriptorType = getTypeDescriptorType(*this, TypeInfoString);
+ return llvm::ConstantExpr::getBitCast(
+ new llvm::GlobalVariable(
+ getModule(), TypeDescriptorType, /*Constant=*/false,
+ getTypeInfoLinkage(Type),
+ llvm::ConstantStruct::get(TypeDescriptorType, Fields),
+ MangledName.c_str()),
+ Int8PtrTy);
+}
+
+llvm::GlobalVariable *
+CodeGenModule::getMSCompleteObjectLocator(const CXXRecordDecl *RD,
+ const VPtrInfo *Info) {
+ return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);
+}
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index 7873f44..78cb82d 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -81,6 +81,20 @@
return true;
}
+ void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ assert(D->doesThisDeclarationHaveABody());
+
+ // We may have member functions that need to be emitted at this point.
+ if (!D->isDependentContext() &&
+ (D->hasAttr<UsedAttr>() || D->hasAttr<ConstructorAttr>() ||
+ D->hasAttr<DLLExportAttr>())) {
+ Builder->EmitTopLevelDecl(D);
+ }
+ }
+
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
/// to (e.g. struct, union, enum, class) is completed. This allows the
/// client hack on the type, which can occur at any point in the file
@@ -90,17 +104,6 @@
return;
Builder->UpdateCompletedType(D);
-
- // In C++, we may have member functions that need to be emitted at this
- // point.
- if (Ctx->getLangOpts().CPlusPlus && !D->isDependentContext()) {
- for (auto *M : D->decls())
- if (auto *Method = dyn_cast<CXXMethodDecl>(M))
- if (Method->doesThisDeclarationHaveABody() &&
- (Method->hasAttr<UsedAttr>() ||
- Method->hasAttr<ConstructorAttr>()))
- Builder->EmitTopLevelDecl(Method);
- }
}
void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index c602b1f..ab4c388 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -23,6 +23,9 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
+
+#include <algorithm> // std::sort
+
using namespace clang;
using namespace CodeGen;
@@ -45,22 +48,6 @@
ABIInfo::~ABIInfo() {}
-static bool isRecordReturnIndirect(const RecordType *RT,
- CGCXXABI &CXXABI) {
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
- return false;
- return CXXABI.isReturnTypeIndirect(RD);
-}
-
-
-static bool isRecordReturnIndirect(QualType T, CGCXXABI &CXXABI) {
- const RecordType *RT = T->getAs<RecordType>();
- if (!RT)
- return false;
- return isRecordReturnIndirect(RT, CXXABI);
-}
-
static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,
CGCXXABI &CXXABI) {
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
@@ -230,13 +217,13 @@
static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
const RecordType *RT = T->getAsStructureType();
if (!RT)
- return 0;
+ return nullptr;
const RecordDecl *RD = RT->getDecl();
if (RD->hasFlexibleArrayMember())
- return 0;
+ return nullptr;
- const Type *Found = 0;
+ const Type *Found = nullptr;
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
@@ -247,13 +234,13 @@
// If we already found an element then this isn't a single-element struct.
if (Found)
- return 0;
+ return nullptr;
// If this is non-empty and not a single element struct, the composite
// cannot be a single element struct.
Found = isSingleElementStruct(I.getType(), Context);
if (!Found)
- return 0;
+ return nullptr;
}
}
@@ -268,7 +255,7 @@
// If we already found an element then this isn't a single-element
// struct.
if (Found)
- return 0;
+ return nullptr;
// Treat single element arrays as the element.
while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
@@ -282,14 +269,14 @@
} else {
Found = isSingleElementStruct(FT, Context);
if (!Found)
- return 0;
+ return nullptr;
}
}
// We don't consider a struct a single-element struct if it has
// padding beyond the element type.
if (Found && Context.getTypeSize(Found) != Context.getTypeSize(T))
- return 0;
+ return nullptr;
return Found;
}
@@ -367,7 +354,8 @@
ABIArgInfo classifyArgumentType(QualType RetTy) const;
void computeInfo(CGFunctionInfo &FI) const override {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &I : FI.arguments())
I.info = classifyArgumentType(I.type);
}
@@ -384,18 +372,12 @@
llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const {
- return 0;
+ return nullptr;
}
ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
- if (isAggregateTypeForABI(Ty)) {
- // Records with non-trivial destructors/constructors should not be passed
- // by value.
- if (isRecordReturnIndirect(Ty, getCXXABI()))
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
-
+ if (isAggregateTypeForABI(Ty))
return ABIArgInfo::getIndirect(0);
- }
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
@@ -446,15 +428,16 @@
};
void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ if (!getCXXABI().classifyReturnType(FI))
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
- for (auto &I : FI.arguments())
- I.info = classifyArgumentType(I.type);
- }
+ for (auto &I : FI.arguments())
+ I.info = classifyArgumentType(I.type);
+}
llvm::Value *PNaClABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const {
- return 0;
+ return nullptr;
}
/// \brief Classify argument of given type \p Ty.
@@ -505,7 +488,7 @@
if ((Constraint == "y" || Constraint == "&y") && Ty->isVectorTy()) {
if (cast<llvm::VectorType>(Ty)->getBitWidth() != 64) {
// Invalid MMX constraint
- return 0;
+ return nullptr;
}
return llvm::Type::getX86_MMXTy(CGF.getLLVMContext());
@@ -547,8 +530,7 @@
return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
}
- bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context,
- bool IsInstanceMethod) const;
+ bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context) const;
/// getIndirectResult - Give a source type \arg Ty, return a suitable result
/// such that the argument will be passed in memory.
@@ -560,8 +542,7 @@
unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const;
Class classify(QualType Ty) const;
- ABIArgInfo classifyReturnType(QualType RetTy, CCState &State,
- bool IsInstanceMethod) const;
+ ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const;
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
bool shouldUseInReg(QualType Ty, CCState &State, bool &NeedsPadding) const;
@@ -627,8 +608,8 @@
/// shouldReturnTypeInRegister - Determine if the given type should be
/// passed in a register (for the Darwin ABI).
-bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, ASTContext &Context,
- bool IsInstanceMethod) const {
+bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
+ ASTContext &Context) const {
uint64_t Size = Context.getTypeSize(Ty);
// Type must be register sized.
@@ -653,8 +634,7 @@
// Arrays are treated like records.
if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty))
- return shouldReturnTypeInRegister(AT->getElementType(), Context,
- IsInstanceMethod);
+ return shouldReturnTypeInRegister(AT->getElementType(), Context);
// Otherwise, it must be a record type.
const RecordType *RT = Ty->getAs<RecordType>();
@@ -662,11 +642,6 @@
// FIXME: Traverse bases here too.
- // For thiscall conventions, structures will never be returned in
- // a register. This is for compatibility with the MSVC ABI
- if (IsWin32StructABI && IsInstanceMethod && RT->isStructureType())
- return false;
-
// Structure types are passed in register if all fields would be
// passed in a register.
for (const auto *FD : RT->getDecl()->fields()) {
@@ -675,7 +650,7 @@
continue;
// Check fields recursively.
- if (!shouldReturnTypeInRegister(FD->getType(), Context, IsInstanceMethod))
+ if (!shouldReturnTypeInRegister(FD->getType(), Context))
return false;
}
return true;
@@ -691,8 +666,7 @@
return ABIArgInfo::getIndirect(/*Align=*/0, /*ByVal=*/false);
}
-ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, CCState &State,
- bool IsInstanceMethod) const {
+ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, CCState &State) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
@@ -723,9 +697,6 @@
if (isAggregateTypeForABI(RetTy)) {
if (const RecordType *RT = RetTy->getAs<RecordType>()) {
- if (isRecordReturnIndirect(RT, getCXXABI()))
- return getIndirectReturnResult(State);
-
// Structures with flexible arrays are always indirect.
if (RT->getDecl()->hasFlexibleArrayMember())
return getIndirectReturnResult(State);
@@ -737,7 +708,7 @@
// Small structures which are register sized are generally returned
// in a register.
- if (shouldReturnTypeInRegister(RetTy, getContext(), IsInstanceMethod)) {
+ if (shouldReturnTypeInRegister(RetTy, getContext())) {
uint64_t Size = getContext().getTypeSize(RetTy);
// As a special-case, if the struct is a "single-element" struct, and
@@ -929,7 +900,7 @@
llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
return ABIArgInfo::getDirectInReg(Result);
}
- llvm::IntegerType *PaddingType = NeedsPadding ? Int32 : 0;
+ llvm::IntegerType *PaddingType = NeedsPadding ? Int32 : nullptr;
// Expand small (<= 128-bit) record types when we know that the stack layout
// of those arguments will match the struct. This is important because the
@@ -986,16 +957,8 @@
else
State.FreeRegs = DefaultNumRegisterParameters;
- FI.getReturnInfo() =
- classifyReturnType(FI.getReturnType(), State, FI.isInstanceMethod());
-
- // On win32, use the x86_cdeclmethodcc convention for cdecl methods that use
- // sret. This convention swaps the order of the first two parameters behind
- // the scenes to match MSVC.
- if (IsWin32StructABI && FI.isInstanceMethod() &&
- FI.getCallingConvention() == llvm::CallingConv::C &&
- FI.getReturnInfo().isIndirect())
- FI.setEffectiveCallingConvention(llvm::CallingConv::X86_CDeclMethod);
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State);
bool UsedInAlloca = false;
for (auto &I : FI.arguments()) {
@@ -1013,24 +976,22 @@
X86_32ABIInfo::addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
unsigned &StackOffset,
ABIArgInfo &Info, QualType Type) const {
+ assert(StackOffset % 4U == 0 && "unaligned inalloca struct");
+ Info = ABIArgInfo::getInAlloca(FrameFields.size());
+ FrameFields.push_back(CGT.ConvertTypeForMem(Type));
+ StackOffset += getContext().getTypeSizeInChars(Type).getQuantity();
+
// Insert padding bytes to respect alignment. For x86_32, each argument is 4
// byte aligned.
- unsigned Align = 4U;
- if (Info.getKind() == ABIArgInfo::Indirect && Info.getIndirectByVal())
- Align = std::max(Align, Info.getIndirectAlign());
- if (StackOffset & (Align - 1)) {
+ if (StackOffset % 4U) {
unsigned OldOffset = StackOffset;
- StackOffset = llvm::RoundUpToAlignment(StackOffset, Align);
+ StackOffset = llvm::RoundUpToAlignment(StackOffset, 4U);
unsigned NumBytes = StackOffset - OldOffset;
assert(NumBytes);
llvm::Type *Ty = llvm::Type::getInt8Ty(getVMContext());
Ty = llvm::ArrayType::get(Ty, NumBytes);
FrameFields.push_back(Ty);
}
-
- Info = ABIArgInfo::getInAlloca(FrameFields.size());
- FrameFields.push_back(CGT.ConvertTypeForMem(Type));
- StackOffset += getContext().getTypeSizeInChars(Type).getQuantity();
}
void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI) const {
@@ -2203,7 +2164,7 @@
assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification.");
- llvm::Type *ResType = 0;
+ llvm::Type *ResType = nullptr;
switch (Lo) {
case NoClass:
if (Hi == NoClass)
@@ -2264,7 +2225,7 @@
break;
}
- llvm::Type *HighPart = 0;
+ llvm::Type *HighPart = nullptr;
switch (Hi) {
// Memory was handled previously and X87 should
// never occur as a hi class.
@@ -2336,7 +2297,7 @@
neededInt = 0;
neededSSE = 0;
- llvm::Type *ResType = 0;
+ llvm::Type *ResType = nullptr;
switch (Lo) {
case NoClass:
if (Hi == NoClass)
@@ -2397,7 +2358,7 @@
}
}
- llvm::Type *HighPart = 0;
+ llvm::Type *HighPart = nullptr;
switch (Hi) {
// Memory was handled previously, ComplexX87 and X87 should
// never occur as hi classes, and X87Up must be preceded by X87,
@@ -2450,7 +2411,8 @@
void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
// Keep track of the number of assigned registers.
unsigned freeIntRegs = 6, freeSSERegs = 8;
@@ -2571,9 +2533,9 @@
// NOTE: 304 is a typo, there are (6 * 8 + 8 * 16) = 176 bytes of
// register save space).
- llvm::Value *InRegs = 0;
- llvm::Value *gp_offset_p = 0, *gp_offset = 0;
- llvm::Value *fp_offset_p = 0, *fp_offset = 0;
+ llvm::Value *InRegs = nullptr;
+ 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 = CGF.Builder.CreateLoad(gp_offset_p, "gp_offset");
@@ -2719,11 +2681,9 @@
uint64_t Size = getContext().getTypeSize(Ty);
- if (const RecordType *RT = Ty->getAs<RecordType>()) {
- if (IsReturnType) {
- if (isRecordReturnIndirect(RT, getCXXABI()))
- return ABIArgInfo::getIndirect(0, false);
- } else {
+ const RecordType *RT = Ty->getAs<RecordType>();
+ if (RT) {
+ if (!IsReturnType) {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
}
@@ -2735,15 +2695,24 @@
if (Size == 128 && getTarget().getTriple().isWindowsGNUEnvironment())
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
Size));
+ }
+ if (Ty->isMemberPointerType()) {
+ // If the member pointer is represented by an LLVM int or ptr, pass it
+ // directly.
+ llvm::Type *LLTy = CGT.ConvertType(Ty);
+ if (LLTy->isPointerTy() || LLTy->isIntegerTy())
+ return ABIArgInfo::getDirect();
+ }
+
+ if (RT || Ty->isMemberPointerType()) {
// MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
// not 1, 2, 4, or 8 bytes, must be passed by reference."
- if (Size <= 64 &&
- (Size & (Size - 1)) == 0)
- return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
- Size));
+ if (Size > 64 || !llvm::isPowerOf2_64(Size))
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ // Otherwise, coerce it to a small integer.
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
}
if (Ty->isPromotableIntegerType())
@@ -2753,9 +2722,8 @@
}
void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
-
- QualType RetTy = FI.getReturnType();
- FI.getReturnInfo() = classify(RetTy, true);
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classify(FI.getReturnType(), true);
for (auto &I : FI.arguments())
I.info = classify(I.type, false);
@@ -2900,7 +2868,8 @@
// entry. This would require changing the logic in PPCISelLowering
// when lowering the parameters in the caller and args in the callee.
void computeInfo(CGFunctionInfo &FI) const override {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &I : FI.arguments()) {
// We rely on the default argument classification for the most part.
// One exception: An aggregate containing a single floating-point
@@ -3135,12 +3104,12 @@
}
//===----------------------------------------------------------------------===//
-// ARM64 ABI Implementation
+// AArch64 ABI Implementation
//===----------------------------------------------------------------------===//
namespace {
-class ARM64ABIInfo : public ABIInfo {
+class AArch64ABIInfo : public ABIInfo {
public:
enum ABIKind {
AAPCS = 0,
@@ -3151,7 +3120,7 @@
ABIKind Kind;
public:
- ARM64ABIInfo(CodeGenTypes &CGT, ABIKind Kind) : ABIInfo(CGT), Kind(Kind) {}
+ AArch64ABIInfo(CodeGenTypes &CGT, ABIKind Kind) : ABIInfo(CGT), Kind(Kind) {}
private:
ABIKind getABIKind() const { return Kind; }
@@ -3160,7 +3129,7 @@
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType RetTy, unsigned &AllocatedVFP,
bool &IsHA, unsigned &AllocatedGPR,
- bool &IsSmallAggr) const;
+ bool &IsSmallAggr, bool IsNamedArg) const;
bool isIllegalVectorType(QualType Ty) const;
virtual void computeInfo(CGFunctionInfo &FI) const {
@@ -3171,40 +3140,54 @@
// and Floating-point Registers (with one register per member of the HFA or
// HVA). Otherwise, the NSRN is set to 8.
unsigned AllocatedVFP = 0;
+
// To correctly handle small aggregates, we need to keep track of the number
// of GPRs allocated so far. If the small aggregate can't all fit into
// registers, it will be on stack. We don't allow the aggregate to be
// partially in registers.
unsigned AllocatedGPR = 0;
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+ // Find the number of named arguments. Variadic arguments get special
+ // treatment with the Darwin ABI.
+ unsigned NumRequiredArgs = (FI.isVariadic() ?
+ FI.getRequiredArgs().getNumRequiredArgs() :
+ FI.arg_size());
+
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it) {
unsigned PreAllocation = AllocatedVFP, PreGPR = AllocatedGPR;
bool IsHA = false, IsSmallAggr = false;
const unsigned NumVFPs = 8;
const unsigned NumGPRs = 8;
+ bool IsNamedArg = ((it - FI.arg_begin()) <
+ static_cast<signed>(NumRequiredArgs));
it->info = classifyArgumentType(it->type, AllocatedVFP, IsHA,
- AllocatedGPR, IsSmallAggr);
+ AllocatedGPR, IsSmallAggr, IsNamedArg);
+
+ // Under AAPCS the 64-bit stack slot alignment means we can't pass HAs
+ // as sequences of floats since they'll get "holes" inserted as
+ // padding by the back end.
+ if (IsHA && AllocatedVFP > NumVFPs && !isDarwinPCS() &&
+ getContext().getTypeAlign(it->type) < 64) {
+ uint32_t NumStackSlots = getContext().getTypeSize(it->type);
+ NumStackSlots = llvm::RoundUpToAlignment(NumStackSlots, 64) / 64;
+
+ llvm::Type *CoerceTy = llvm::ArrayType::get(
+ llvm::Type::getDoubleTy(getVMContext()), NumStackSlots);
+ it->info = ABIArgInfo::getDirect(CoerceTy);
+ }
+
// If we do not have enough VFP registers for the HA, any VFP registers
// that are unallocated are marked as unavailable. To achieve this, we add
// padding of (NumVFPs - PreAllocation) floats.
if (IsHA && AllocatedVFP > NumVFPs && PreAllocation < NumVFPs) {
llvm::Type *PaddingTy = llvm::ArrayType::get(
llvm::Type::getFloatTy(getVMContext()), NumVFPs - PreAllocation);
- if (isDarwinPCS())
- it->info = ABIArgInfo::getExpandWithPadding(false, PaddingTy);
- else {
- // Under AAPCS the 64-bit stack slot alignment means we can't pass HAs
- // as sequences of floats since they'll get "holes" inserted as
- // padding by the back end.
- uint32_t NumStackSlots = getContext().getTypeSize(it->type);
- NumStackSlots = llvm::RoundUpToAlignment(NumStackSlots, 64) / 64;
-
- llvm::Type *CoerceTy = llvm::ArrayType::get(
- llvm::Type::getDoubleTy(getVMContext()), NumStackSlots);
- it->info = ABIArgInfo::getDirect(CoerceTy, 0, PaddingTy);
- }
+ it->info.setPaddingType(PaddingTy);
}
+
// If we do not have enough GPRs for the small aggregate, any GPR regs
// that are unallocated are marked as unavailable.
if (IsSmallAggr && AllocatedGPR > NumGPRs && PreGPR < NumGPRs) {
@@ -3229,10 +3212,10 @@
}
};
-class ARM64TargetCodeGenInfo : public TargetCodeGenInfo {
+class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- ARM64TargetCodeGenInfo(CodeGenTypes &CGT, ARM64ABIInfo::ABIKind Kind)
- : TargetCodeGenInfo(new ARM64ABIInfo(CGT, Kind)) {}
+ AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind Kind)
+ : TargetCodeGenInfo(new AArch64ABIInfo(CGT, Kind)) {}
StringRef getARCRetainAutoreleasedReturnValueMarker() const {
return "mov\tfp, fp\t\t; marker for objc_retainAutoreleaseReturnValue";
@@ -3246,13 +3229,14 @@
static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
ASTContext &Context,
- uint64_t *HAMembers = 0);
+ uint64_t *HAMembers = nullptr);
-ABIArgInfo ARM64ABIInfo::classifyArgumentType(QualType Ty,
- unsigned &AllocatedVFP,
- bool &IsHA,
- unsigned &AllocatedGPR,
- bool &IsSmallAggr) const {
+ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty,
+ unsigned &AllocatedVFP,
+ bool &IsHA,
+ unsigned &AllocatedGPR,
+ bool &IsSmallAggr,
+ bool IsNamedArg) const {
// Handle illegal vector types here.
if (isIllegalVectorType(Ty)) {
uint64_t Size = getContext().getTypeSize(Ty);
@@ -3293,6 +3277,10 @@
Ty = EnumTy->getDecl()->getIntegerType();
if (!Ty->isFloatingType() && !Ty->isVectorType()) {
+ unsigned Alignment = getContext().getTypeAlign(Ty);
+ if (!isDarwinPCS() && Alignment > 64)
+ AllocatedGPR = llvm::RoundUpToAlignment(AllocatedGPR, Alignment / 64);
+
int RegsNeeded = getContext().getTypeSize(Ty) > 64 ? 2 : 1;
AllocatedGPR += RegsNeeded;
}
@@ -3303,9 +3291,10 @@
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
- if (isRecordReturnIndirect(Ty, getCXXABI())) {
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
AllocatedGPR++;
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/RAA ==
+ CGCXXABI::RAA_DirectInMemory);
}
// Empty records are always ignored on Darwin, but actually passed in C++ mode
@@ -3319,23 +3308,34 @@
}
// Homogeneous Floating-point Aggregates (HFAs) need to be expanded.
- const Type *Base = 0;
+ const Type *Base = nullptr;
uint64_t Members = 0;
if (isHomogeneousAggregate(Ty, Base, getContext(), &Members)) {
- AllocatedVFP += Members;
IsHA = true;
+ if (!IsNamedArg && isDarwinPCS()) {
+ // With the Darwin ABI, variadic arguments are always passed on the stack
+ // and should not be expanded. Treat variadic HFAs as arrays of doubles.
+ uint64_t Size = getContext().getTypeSize(Ty);
+ llvm::Type *BaseTy = llvm::Type::getDoubleTy(getVMContext());
+ return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64));
+ }
+ AllocatedVFP += Members;
return ABIArgInfo::getExpand();
}
// Aggregates <= 16 bytes are passed directly in registers or on the stack.
uint64_t Size = getContext().getTypeSize(Ty);
if (Size <= 128) {
+ unsigned Alignment = getContext().getTypeAlign(Ty);
+ if (!isDarwinPCS() && Alignment > 64)
+ AllocatedGPR = llvm::RoundUpToAlignment(AllocatedGPR, Alignment / 64);
+
Size = 64 * ((Size + 63) / 64); // round up to multiple of 8 bytes
AllocatedGPR += Size / 64;
IsSmallAggr = true;
// We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
// For aggregates with 16-byte alignment, we use i128.
- if (getContext().getTypeAlign(Ty) < 128 && Size == 128) {
+ if (Alignment < 128 && Size == 128) {
llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext());
return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64));
}
@@ -3346,7 +3346,7 @@
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
}
-ABIArgInfo ARM64ABIInfo::classifyReturnType(QualType RetTy) const {
+ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
@@ -3359,19 +3359,15 @@
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend()
- : ABIArgInfo::getDirect());
+ return (RetTy->isPromotableIntegerType() && isDarwinPCS()
+ ? ABIArgInfo::getExtend()
+ : ABIArgInfo::getDirect());
}
- // Structures with either a non-trivial destructor or a non-trivial
- // copy constructor are always indirect.
- if (isRecordReturnIndirect(RetTy, getCXXABI()))
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
-
if (isEmptyRecord(getContext(), RetTy, true))
return ABIArgInfo::getIgnore();
- const Type *Base = 0;
+ const Type *Base = nullptr;
if (isHomogeneousAggregate(RetTy, Base, getContext()))
// Homogeneous Floating-point Aggregates (HFAs) are returned directly.
return ABIArgInfo::getDirect();
@@ -3386,8 +3382,8 @@
return ABIArgInfo::getIndirect(0);
}
-/// isIllegalVectorType - check whether the vector type is legal for ARM64.
-bool ARM64ABIInfo::isIllegalVectorType(QualType Ty) const {
+/// isIllegalVectorType - check whether the vector type is legal for AArch64.
+bool AArch64ABIInfo::isIllegalVectorType(QualType Ty) const {
if (const VectorType *VT = Ty->getAs<VectorType>()) {
// Check whether VT is legal.
unsigned NumElements = VT->getNumElements();
@@ -3420,7 +3416,7 @@
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
auto &Ctx = CGF.getContext();
- llvm::Value *reg_offs_p = 0, *reg_offs = 0;
+ llvm::Value *reg_offs_p = nullptr, *reg_offs = nullptr;
int reg_top_index;
int RegSize;
if (AllocatedGPR) {
@@ -3447,14 +3443,14 @@
// argument. We don't want to keep updating reg_offs (in case it overflows,
// though anyone passing 2GB of arguments, each at most 16 bytes, deserves
// whatever they get).
- llvm::Value *UsingStack = 0;
+ llvm::Value *UsingStack = nullptr;
UsingStack = CGF.Builder.CreateICmpSGE(
reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, 0));
CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, MaybeRegBlock);
// Otherwise, at least some kind of argument could go in these registers, the
- // quesiton is whether this particular type is too big.
+ // question is whether this particular type is too big.
CGF.EmitBlock(MaybeRegBlock);
// Integer arguments may need to correct register alignment (for example a
@@ -3472,14 +3468,14 @@
}
// Update the gr_offs/vr_offs pointer for next call to va_arg on this va_list.
- llvm::Value *NewOffset = 0;
+ llvm::Value *NewOffset = nullptr;
NewOffset = CGF.Builder.CreateAdd(
reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, RegSize), "new_reg_offs");
CGF.Builder.CreateStore(NewOffset, reg_offs_p);
// Now we're in a position to decide whether this argument really was in
// registers or not.
- llvm::Value *InRegs = 0;
+ llvm::Value *InRegs = nullptr;
InRegs = CGF.Builder.CreateICmpSLE(
NewOffset, llvm::ConstantInt::get(CGF.Int32Ty, 0), "inreg");
@@ -3493,12 +3489,12 @@
// registers. First start the appropriate block:
CGF.EmitBlock(InRegBlock);
- llvm::Value *reg_top_p = 0, *reg_top = 0;
+ llvm::Value *reg_top_p = nullptr, *reg_top = nullptr;
reg_top_p =
CGF.Builder.CreateStructGEP(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 = 0;
+ llvm::Value *RegAddr = nullptr;
llvm::Type *MemTy = llvm::PointerType::getUnqual(CGF.ConvertTypeForMem(Ty));
if (IsIndirect) {
@@ -3507,9 +3503,10 @@
MemTy = llvm::PointerType::getUnqual(MemTy);
}
- const Type *Base = 0;
+ const Type *Base = nullptr;
uint64_t NumMembers;
- if (isHomogeneousAggregate(Ty, Base, Ctx, &NumMembers) && NumMembers > 1) {
+ bool IsHFA = isHomogeneousAggregate(Ty, Base, Ctx, &NumMembers);
+ if (IsHFA && NumMembers > 1) {
// Homogeneous aggregates passed in registers will have their elements split
// and stored 16-bytes apart regardless of size (they're notionally in qN,
// qN+1, ...). We reload and store into a temporary local variable
@@ -3538,7 +3535,8 @@
} else {
// Otherwise the object is contiguous in memory
unsigned BeAlign = reg_top_index == 2 ? 16 : 8;
- if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) &&
+ if (CGF.CGM.getDataLayout().isBigEndian() &&
+ (IsHFA || !isAggregateTypeForABI(Ty)) &&
Ctx.getTypeSize(Ty) < (BeAlign * 8)) {
int Offset = BeAlign - Ctx.getTypeSize(Ty) / 8;
BaseAddr = CGF.Builder.CreatePtrToInt(BaseAddr, CGF.Int64Ty);
@@ -3559,7 +3557,7 @@
//=======================================
CGF.EmitBlock(OnStackBlock);
- llvm::Value *stack_p = 0, *OnStackAddr = 0;
+ llvm::Value *stack_p = nullptr, *OnStackAddr = nullptr;
stack_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "stack_p");
OnStackAddr = CGF.Builder.CreateLoad(stack_p, "stack");
@@ -3626,30 +3624,30 @@
return ResAddr;
}
-llvm::Value *ARM64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr, QualType Ty,
+llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const {
unsigned AllocatedGPR = 0, AllocatedVFP = 0;
bool IsHA = false, IsSmallAggr = false;
- ABIArgInfo AI =
- classifyArgumentType(Ty, AllocatedVFP, IsHA, AllocatedGPR, IsSmallAggr);
+ ABIArgInfo AI = classifyArgumentType(Ty, AllocatedVFP, IsHA, AllocatedGPR,
+ IsSmallAggr, false /*IsNamedArg*/);
return EmitAArch64VAArg(VAListAddr, Ty, AllocatedGPR, AllocatedVFP,
AI.isIndirect(), CGF);
}
-llvm::Value *ARM64ABIInfo::EmitDarwinVAArg(llvm::Value *VAListAddr, QualType Ty,
+llvm::Value *AArch64ABIInfo::EmitDarwinVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const {
// We do not support va_arg for aggregates or illegal vector types.
// Lower VAArg here for these cases and use the LLVM va_arg instruction for
// other cases.
if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty))
- return 0;
+ return nullptr;
uint64_t Size = CGF.getContext().getTypeSize(Ty) / 8;
uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8;
- const Type *Base = 0;
+ const Type *Base = nullptr;
bool isHA = isHomogeneousAggregate(Ty, Base, getContext());
bool isIndirect = false;
@@ -3753,7 +3751,7 @@
private:
ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic) const;
- ABIArgInfo classifyArgumentType(QualType RetTy, bool &IsHA, bool isVariadic,
+ ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic,
bool &IsCPRC) const;
bool isIllegalVectorType(QualType Ty) const;
@@ -3854,38 +3852,37 @@
// unallocated are marked as unavailable.
resetAllocatedRegs();
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic());
+ if (getCXXABI().classifyReturnType(FI)) {
+ if (FI.getReturnInfo().isIndirect())
+ markAllocatedGPRs(1, 1);
+ } else {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic());
+ }
for (auto &I : FI.arguments()) {
unsigned PreAllocationVFPs = AllocatedVFPs;
unsigned PreAllocationGPRs = AllocatedGPRs;
- bool IsHA = false;
bool IsCPRC = false;
// 6.1.2.3 There is one VFP co-processor register class using registers
// s0-s15 (d0-d7) for passing arguments.
- I.info = classifyArgumentType(I.type, IsHA, FI.isVariadic(), IsCPRC);
- assert((IsCPRC || !IsHA) && "Homogeneous aggregates must be CPRCs");
- // If we do not have enough VFP registers for the HA, any VFP registers
- // that are unallocated are marked as unavailable. To achieve this, we add
- // padding of (NumVFPs - PreAllocationVFP) floats.
- // Note that IsHA will only be set when using the AAPCS-VFP calling convention,
- // and the callee is not variadic.
- if (IsHA && AllocatedVFPs > NumVFPs && PreAllocationVFPs < NumVFPs) {
- llvm::Type *PaddingTy = llvm::ArrayType::get(
- llvm::Type::getFloatTy(getVMContext()), NumVFPs - PreAllocationVFPs);
- I.info = ABIArgInfo::getExpandWithPadding(false, PaddingTy);
- }
+ I.info = classifyArgumentType(I.type, FI.isVariadic(), IsCPRC);
// If we have allocated some arguments onto the stack (due to running
// out of VFP registers), we cannot split an argument between GPRs and
// the stack. If this situation occurs, we add padding to prevent the
- // GPRs from being used. In this situiation, the current argument could
+ // GPRs from being used. In this situation, the current argument could
// only be allocated by rule C.8, so rule C.6 would mark these GPRs as
// unusable anyway.
const bool StackUsed = PreAllocationGPRs > NumGPRs || PreAllocationVFPs > NumVFPs;
if (!IsCPRC && PreAllocationGPRs < NumGPRs && AllocatedGPRs > NumGPRs && StackUsed) {
llvm::Type *PaddingTy = llvm::ArrayType::get(
llvm::Type::getInt32Ty(getVMContext()), NumGPRs - PreAllocationGPRs);
- I.info = ABIArgInfo::getExpandWithPadding(false, PaddingTy);
+ if (I.info.canHaveCoerceToType()) {
+ I.info = ABIArgInfo::getDirect(I.info.getCoerceToType() /* type */, 0 /* offset */,
+ PaddingTy);
+ } else {
+ I.info = ABIArgInfo::getDirect(nullptr /* type */, 0 /* offset */,
+ PaddingTy);
+ }
}
}
@@ -4069,8 +4066,7 @@
VFPRegs[i] = 0;
}
-ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool &IsHA,
- bool isVariadic,
+ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
bool &IsCPRC) const {
// We update number of allocated VFPs according to
// 6.1.2.1 The following argument types are VFP CPRCs:
@@ -4165,7 +4161,7 @@
if (getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic) {
// Homogeneous Aggregates need to be expanded when we can fit the aggregate
// into VFP registers.
- const Type *Base = 0;
+ const Type *Base = nullptr;
uint64_t Members = 0;
if (isHomogeneousAggregate(Ty, Base, getContext(), &Members)) {
assert(Base && "Base class should be set for homogeneous aggregate");
@@ -4182,9 +4178,8 @@
Base->isSpecificBuiltinType(BuiltinType::LongDouble));
markAllocatedVFPs(2, Members * 2);
}
- IsHA = true;
IsCPRC = true;
- return ABIArgInfo::getExpand();
+ return ABIArgInfo::getDirect();
}
}
@@ -4198,7 +4193,7 @@
getABIKind() == ARMABIInfo::AAPCS)
ABIAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) {
- // Update Allocated GPRs
+ // Update Allocated GPRs
markAllocatedGPRs(1, 1);
return ABIArgInfo::getIndirect(TyAlign, /*ByVal=*/true,
/*Realign=*/TyAlign > ABIAlign);
@@ -4329,13 +4324,6 @@
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
- // Structures with either a non-trivial destructor or a non-trivial
- // copy constructor are always indirect.
- if (isRecordReturnIndirect(RetTy, getCXXABI())) {
- markAllocatedGPRs(1, 1);
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
- }
-
// Are we following APCS?
if (getABIKind() == APCS) {
if (isEmptyRecord(getContext(), RetTy, false))
@@ -4372,7 +4360,7 @@
// Check for homogeneous aggregates with AAPCS-VFP.
if (getABIKind() == AAPCS_VFP && !isVariadic) {
- const Type *Base = 0;
+ const Type *Base = nullptr;
if (isHomogeneousAggregate(RetTy, Base, getContext())) {
assert(Base && "Base class should be set for homogeneous aggregate");
// Homogeneous Aggregates are returned directly.
@@ -4521,221 +4509,6 @@
}
//===----------------------------------------------------------------------===//
-// AArch64 ABI Implementation
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class AArch64ABIInfo : public ABIInfo {
-public:
- AArch64ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
-
-private:
- // The AArch64 PCS is explicit about return types and argument types being
- // handled identically, so we don't need to draw a distinction between
- // Argument and Return classification.
- ABIArgInfo classifyGenericType(QualType Ty, int &FreeIntRegs,
- int &FreeVFPRegs) const;
-
- ABIArgInfo tryUseRegs(QualType Ty, int &FreeRegs, int RegsNeeded, bool IsInt,
- llvm::Type *DirectTy = 0) const;
-
- void computeInfo(CGFunctionInfo &FI) const override;
-
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
-};
-
-class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
-public:
- AArch64TargetCodeGenInfo(CodeGenTypes &CGT)
- :TargetCodeGenInfo(new AArch64ABIInfo(CGT)) {}
-
- const AArch64ABIInfo &getABIInfo() const {
- return static_cast<const AArch64ABIInfo&>(TargetCodeGenInfo::getABIInfo());
- }
-
- int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
- return 31;
- }
-
- bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *Address) const override {
- // 0-31 are x0-x30 and sp: 8 bytes each
- llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.Int8Ty, 8);
- AssignToArrayRange(CGF.Builder, Address, Eight8, 0, 31);
-
- // 64-95 are v0-v31: 16 bytes each
- llvm::Value *Sixteen8 = llvm::ConstantInt::get(CGF.Int8Ty, 16);
- AssignToArrayRange(CGF.Builder, Address, Sixteen8, 64, 95);
-
- return false;
- }
-
-};
-
-}
-
-void AArch64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
- int FreeIntRegs = 8, FreeVFPRegs = 8;
-
- FI.getReturnInfo() = classifyGenericType(FI.getReturnType(),
- FreeIntRegs, FreeVFPRegs);
-
- FreeIntRegs = FreeVFPRegs = 8;
- for (auto &I : FI.arguments()) {
- I.info = classifyGenericType(I.type, FreeIntRegs, FreeVFPRegs);
-
- }
-}
-
-ABIArgInfo
-AArch64ABIInfo::tryUseRegs(QualType Ty, int &FreeRegs, int RegsNeeded,
- bool IsInt, llvm::Type *DirectTy) const {
- if (FreeRegs >= RegsNeeded) {
- FreeRegs -= RegsNeeded;
- return ABIArgInfo::getDirect(DirectTy);
- }
-
- llvm::Type *Padding = 0;
-
- // We need padding so that later arguments don't get filled in anyway. That
- // wouldn't happen if only ByVal arguments followed in the same category, but
- // a large structure will simply seem to be a pointer as far as LLVM is
- // concerned.
- if (FreeRegs > 0) {
- if (IsInt)
- Padding = llvm::Type::getInt64Ty(getVMContext());
- else
- Padding = llvm::Type::getFloatTy(getVMContext());
-
- // Either [N x i64] or [N x float].
- Padding = llvm::ArrayType::get(Padding, FreeRegs);
- FreeRegs = 0;
- }
-
- return ABIArgInfo::getIndirect(getContext().getTypeAlign(Ty) / 8,
- /*IsByVal=*/ true, /*Realign=*/ false,
- Padding);
-}
-
-
-ABIArgInfo AArch64ABIInfo::classifyGenericType(QualType Ty,
- int &FreeIntRegs,
- int &FreeVFPRegs) const {
- // Can only occurs for return, but harmless otherwise.
- if (Ty->isVoidType())
- return ABIArgInfo::getIgnore();
-
- // Large vector types should be returned via memory. There's no such concept
- // in the ABI, but they'd be over 16 bytes anyway so no matter how they're
- // classified they'd go into memory (see B.3).
- if (Ty->isVectorType() && getContext().getTypeSize(Ty) > 128) {
- if (FreeIntRegs > 0)
- --FreeIntRegs;
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
- }
-
- // All non-aggregate LLVM types have a concrete ABI representation so they can
- // be passed directly. After this block we're guaranteed to be in a
- // complicated case.
- if (!isAggregateTypeForABI(Ty)) {
- // Treat an enum type as its underlying type.
- if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
-
- if (Ty->isFloatingType() || Ty->isVectorType())
- return tryUseRegs(Ty, FreeVFPRegs, /*RegsNeeded=*/ 1, /*IsInt=*/ false);
-
- assert(getContext().getTypeSize(Ty) <= 128 &&
- "unexpectedly large scalar type");
-
- int RegsNeeded = getContext().getTypeSize(Ty) > 64 ? 2 : 1;
-
- // If the type may need padding registers to ensure "alignment", we must be
- // careful when this is accounted for. Increasing the effective size covers
- // all cases.
- if (getContext().getTypeAlign(Ty) == 128)
- RegsNeeded += FreeIntRegs % 2 != 0;
-
- return tryUseRegs(Ty, FreeIntRegs, RegsNeeded, /*IsInt=*/ true);
- }
-
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
- if (FreeIntRegs > 0 && RAA == CGCXXABI::RAA_Indirect)
- --FreeIntRegs;
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
- }
-
- if (isEmptyRecord(getContext(), Ty, true)) {
- if (!getContext().getLangOpts().CPlusPlus) {
- // Empty structs outside C++ mode are a GNU extension, so no ABI can
- // possibly tell us what to do. It turns out (I believe) that GCC ignores
- // the object for parameter-passsing purposes.
- return ABIArgInfo::getIgnore();
- }
-
- // The combination of C++98 9p5 (sizeof(struct) != 0) and the pseudocode
- // description of va_arg in the PCS require that an empty struct does
- // actually occupy space for parameter-passing. I'm hoping for a
- // clarification giving an explicit paragraph to point to in future.
- return tryUseRegs(Ty, FreeIntRegs, /*RegsNeeded=*/ 1, /*IsInt=*/ true,
- llvm::Type::getInt8Ty(getVMContext()));
- }
-
- // Homogeneous vector aggregates get passed in registers or on the stack.
- const Type *Base = 0;
- uint64_t NumMembers = 0;
- if (isHomogeneousAggregate(Ty, Base, getContext(), &NumMembers)) {
- assert(Base && "Base class should be set for homogeneous aggregate");
- // Homogeneous aggregates are passed and returned directly.
- return tryUseRegs(Ty, FreeVFPRegs, /*RegsNeeded=*/ NumMembers,
- /*IsInt=*/ false);
- }
-
- uint64_t Size = getContext().getTypeSize(Ty);
- if (Size <= 128) {
- // Small structs can use the same direct type whether they're in registers
- // or on the stack.
- llvm::Type *BaseTy;
- unsigned NumBases;
- int SizeInRegs = (Size + 63) / 64;
-
- if (getContext().getTypeAlign(Ty) == 128) {
- BaseTy = llvm::Type::getIntNTy(getVMContext(), 128);
- NumBases = 1;
-
- // If the type may need padding registers to ensure "alignment", we must
- // be careful when this is accounted for. Increasing the effective size
- // covers all cases.
- SizeInRegs += FreeIntRegs % 2 != 0;
- } else {
- BaseTy = llvm::Type::getInt64Ty(getVMContext());
- NumBases = SizeInRegs;
- }
- llvm::Type *DirectTy = llvm::ArrayType::get(BaseTy, NumBases);
-
- return tryUseRegs(Ty, FreeIntRegs, /*RegsNeeded=*/ SizeInRegs,
- /*IsInt=*/ true, DirectTy);
- }
-
- // If the aggregate is > 16 bytes, it's passed and returned indirectly. In
- // LLVM terms the return uses an "sret" pointer, but that's handled elsewhere.
- --FreeIntRegs;
- return ABIArgInfo::getIndirect(0, /* byVal = */ false);
-}
-
-llvm::Value *AArch64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- int FreeIntRegs = 8, FreeVFPRegs = 8;
- Ty = CGF.getContext().getCanonicalType(Ty);
- ABIArgInfo AI = classifyGenericType(Ty, FreeIntRegs, FreeVFPRegs);
-
- return EmitAArch64VAArg(VAListAddr, Ty, 8 - FreeIntRegs, 8 - FreeVFPRegs,
- AI.isIndirect(), CGF);
-}
-
-//===----------------------------------------------------------------------===//
// NVPTX ABI Implementation
//===----------------------------------------------------------------------===//
@@ -4761,7 +4534,9 @@
void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
private:
- static void addKernelMetadata(llvm::Function *F);
+ // Adds a NamedMDNode with F, Name, and Operand as operands, and adds the
+ // resulting MDNode to the nvvm.annotations MDNode.
+ static void addNVVMMetadata(llvm::Function *F, StringRef Name, int Operand);
};
ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const {
@@ -4790,7 +4565,8 @@
}
void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &I : FI.arguments())
I.info = classifyArgumentType(I.type);
@@ -4820,7 +4596,8 @@
// By default, all functions are device functions
if (FD->hasAttr<OpenCLKernelAttr>()) {
// OpenCL __kernel functions get kernel metadata
- addKernelMetadata(F);
+ // Create !{<func-ref>, metadata !"kernel", i32 1} node
+ addNVVMMetadata(F, "kernel", 1);
// And kernel functions are not subject to inlining
F->addFnAttr(llvm::Attribute::NoInline);
}
@@ -4831,28 +4608,41 @@
// CUDA __global__ functions get a kernel metadata entry. Since
// __global__ functions cannot be called from the device, we do not
// need to set the noinline attribute.
- if (FD->hasAttr<CUDAGlobalAttr>())
- addKernelMetadata(F);
+ if (FD->hasAttr<CUDAGlobalAttr>()) {
+ // Create !{<func-ref>, metadata !"kernel", i32 1} node
+ addNVVMMetadata(F, "kernel", 1);
+ }
+ if (FD->hasAttr<CUDALaunchBoundsAttr>()) {
+ // Create !{<func-ref>, metadata !"maxntidx", i32 <val>} node
+ addNVVMMetadata(F, "maxntidx",
+ FD->getAttr<CUDALaunchBoundsAttr>()->getMaxThreads());
+ // min blocks is a default argument for CUDALaunchBoundsAttr, so getting a
+ // zero value from getMinBlocks either means it was not specified in
+ // __launch_bounds__ or the user specified a 0 value. In both cases, we
+ // don't have to add a PTX directive.
+ int MinCTASM = FD->getAttr<CUDALaunchBoundsAttr>()->getMinBlocks();
+ if (MinCTASM > 0) {
+ // Create !{<func-ref>, metadata !"minctasm", i32 <val>} node
+ addNVVMMetadata(F, "minctasm", MinCTASM);
+ }
+ }
}
}
-void NVPTXTargetCodeGenInfo::addKernelMetadata(llvm::Function *F) {
+void NVPTXTargetCodeGenInfo::addNVVMMetadata(llvm::Function *F, StringRef Name,
+ int Operand) {
llvm::Module *M = F->getParent();
llvm::LLVMContext &Ctx = M->getContext();
// Get "nvvm.annotations" metadata node
llvm::NamedMDNode *MD = M->getOrInsertNamedMetadata("nvvm.annotations");
- // Create !{<func-ref>, metadata !"kernel", i32 1} node
- llvm::SmallVector<llvm::Value *, 3> MDVals;
- MDVals.push_back(F);
- MDVals.push_back(llvm::MDString::get(Ctx, "kernel"));
- MDVals.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 1));
-
+ llvm::Value *MDVals[] = {
+ F, llvm::MDString::get(Ctx, Name),
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), Operand)};
// Append metadata to nvvm.annotations
MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
}
-
}
//===----------------------------------------------------------------------===//
@@ -4873,7 +4663,8 @@
ABIArgInfo classifyArgumentType(QualType ArgTy) const;
void computeInfo(CGFunctionInfo &FI) const override {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &I : FI.arguments())
I.info = classifyArgumentType(I.type);
}
@@ -5171,7 +4962,7 @@
if (isCompoundType(Ty))
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
- return ABIArgInfo::getDirect(0);
+ return ABIArgInfo::getDirect(nullptr);
}
//===----------------------------------------------------------------------===//
@@ -5206,9 +4997,8 @@
// Step 3: Emit ISR vector alias.
unsigned Num = attr->getNumber() / 2;
- new llvm::GlobalAlias(GV->getType(), llvm::Function::ExternalLinkage,
- "__isr_" + Twine(Num),
- GV, &M.getModule());
+ llvm::GlobalAlias::create(llvm::Function::ExternalLinkage,
+ "__isr_" + Twine(Num), F);
}
}
}
@@ -5349,7 +5139,7 @@
llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
uint64_t Offset) const {
if (OrigOffset + MinABIStackAlignInBytes > Offset)
- return 0;
+ return nullptr;
return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
}
@@ -5390,7 +5180,7 @@
return ABIArgInfo::getExtend();
return ABIArgInfo::getDirect(
- 0, 0, IsO32 ? 0 : getPaddingType(OrigOffset, CurrOffset));
+ nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset));
}
llvm::Type*
@@ -5442,9 +5232,6 @@
return ABIArgInfo::getIgnore();
if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) {
- if (isRecordReturnIndirect(RetTy, getCXXABI()))
- return ABIArgInfo::getIndirect(0);
-
if (Size <= 128) {
if (RetTy->isAnyComplexType())
return ABIArgInfo::getDirect();
@@ -5470,7 +5257,8 @@
void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
ABIArgInfo &RetInfo = FI.getReturnInfo();
- RetInfo = classifyReturnType(FI.getReturnType());
+ if (!getCXXABI().classifyReturnType(FI))
+ RetInfo = classifyReturnType(FI.getReturnType());
// Check if a pointer to an aggregate is passed as a hidden argument.
uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
@@ -5638,7 +5426,8 @@
}
void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &I : FI.arguments())
I.info = classifyArgumentType(I.type);
}
@@ -5691,11 +5480,6 @@
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
- // Structures with either a non-trivial destructor or a non-trivial
- // copy constructor are always indirect.
- if (isRecordReturnIndirect(RetTy, getCXXABI()))
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
-
if (isEmptyRecord(getContext(), RetTy, true))
return ABIArgInfo::getIgnore();
@@ -6048,7 +5832,101 @@
//===----------------------------------------------------------------------===//
// XCore ABI Implementation
//===----------------------------------------------------------------------===//
+
namespace {
+
+/// A SmallStringEnc instance is used to build up the TypeString by passing
+/// it by reference between functions that append to it.
+typedef llvm::SmallString<128> SmallStringEnc;
+
+/// TypeStringCache caches the meta encodings of Types.
+///
+/// The reason for caching TypeStrings is two fold:
+/// 1. To cache a type's encoding for later uses;
+/// 2. As a means to break recursive member type inclusion.
+///
+/// A cache Entry can have a Status of:
+/// NonRecursive: The type encoding is not recursive;
+/// Recursive: The type encoding is recursive;
+/// Incomplete: An incomplete TypeString;
+/// IncompleteUsed: An incomplete TypeString that has been used in a
+/// Recursive type encoding.
+///
+/// A NonRecursive entry will have all of its sub-members expanded as fully
+/// as possible. Whilst it may contain types which are recursive, the type
+/// itself is not recursive and thus its encoding may be safely used whenever
+/// the type is encountered.
+///
+/// A Recursive entry will have all of its sub-members expanded as fully as
+/// possible. The type itself is recursive and it may contain other types which
+/// are recursive. The Recursive encoding must not be used during the expansion
+/// of a recursive type's recursive branch. For simplicity the code uses
+/// IncompleteCount to reject all usage of Recursive encodings for member types.
+///
+/// An Incomplete entry is always a RecordType and only encodes its
+/// identifier e.g. "s(S){}". Incomplete 'StubEnc' entries are ephemeral and
+/// are placed into the cache during type expansion as a means to identify and
+/// handle recursive inclusion of types as sub-members. If there is recursion
+/// the entry becomes IncompleteUsed.
+///
+/// During the expansion of a RecordType's members:
+///
+/// If the cache contains a NonRecursive encoding for the member type, the
+/// cached encoding is used;
+///
+/// If the cache contains a Recursive encoding for the member type, the
+/// cached encoding is 'Swapped' out, as it may be incorrect, and...
+///
+/// If the member is a RecordType, an Incomplete encoding is placed into the
+/// cache to break potential recursive inclusion of itself as a sub-member;
+///
+/// Once a member RecordType has been expanded, its temporary incomplete
+/// entry is removed from the cache. If a Recursive encoding was swapped out
+/// it is swapped back in;
+///
+/// If an incomplete entry is used to expand a sub-member, the incomplete
+/// entry is marked as IncompleteUsed. The cache keeps count of how many
+/// IncompleteUsed entries it currently contains in IncompleteUsedCount;
+///
+/// If a member's encoding is found to be a NonRecursive or Recursive viz:
+/// IncompleteUsedCount==0, the member's encoding is added to the cache.
+/// Else the member is part of a recursive type and thus the recursion has
+/// been exited too soon for the encoding to be correct for the member.
+///
+class TypeStringCache {
+ enum Status {NonRecursive, Recursive, Incomplete, IncompleteUsed};
+ struct Entry {
+ std::string Str; // The encoded TypeString for the type.
+ enum Status State; // Information about the encoding in 'Str'.
+ std::string Swapped; // A temporary place holder for a Recursive encoding
+ // during the expansion of RecordType's members.
+ };
+ std::map<const IdentifierInfo *, struct Entry> Map;
+ unsigned IncompleteCount; // Number of Incomplete entries in the Map.
+ unsigned IncompleteUsedCount; // Number of IncompleteUsed entries in the Map.
+public:
+ TypeStringCache() : IncompleteCount(0), IncompleteUsedCount(0) {};
+ void addIncomplete(const IdentifierInfo *ID, std::string StubEnc);
+ bool removeIncomplete(const IdentifierInfo *ID);
+ void addIfComplete(const IdentifierInfo *ID, StringRef Str,
+ bool IsRecursive);
+ StringRef lookupStr(const IdentifierInfo *ID);
+};
+
+/// TypeString encodings for enum & union fields must be order.
+/// FieldEncoding is a helper for this ordering process.
+class FieldEncoding {
+ bool HasName;
+ std::string Enc;
+public:
+ FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {};
+ StringRef str() {return Enc.c_str();};
+ bool operator<(const FieldEncoding &rhs) const {
+ if (HasName != rhs.HasName) return HasName;
+ return Enc < rhs.Enc;
+ }
+};
+
class XCoreABIInfo : public DefaultABIInfo {
public:
XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
@@ -6057,10 +5935,14 @@
};
class XCoreTargetCodeGenInfo : public TargetCodeGenInfo {
+ mutable TypeStringCache TSC;
public:
XCoreTargetCodeGenInfo(CodeGenTypes &CGT)
:TargetCodeGenInfo(new XCoreABIInfo(CGT)) {}
+ void emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const override;
};
+
} // End anonymous namespace.
llvm::Value *XCoreABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -6112,6 +5994,455 @@
return Val;
}
+/// During the expansion of a RecordType, an incomplete TypeString is placed
+/// into the cache as a means to identify and break recursion.
+/// If there is a Recursive encoding in the cache, it is swapped out and will
+/// be reinserted by removeIncomplete().
+/// All other types of encoding should have been used rather than arriving here.
+void TypeStringCache::addIncomplete(const IdentifierInfo *ID,
+ std::string StubEnc) {
+ if (!ID)
+ return;
+ Entry &E = Map[ID];
+ assert( (E.Str.empty() || E.State == Recursive) &&
+ "Incorrectly use of addIncomplete");
+ assert(!StubEnc.empty() && "Passing an empty string to addIncomplete()");
+ E.Swapped.swap(E.Str); // swap out the Recursive
+ E.Str.swap(StubEnc);
+ E.State = Incomplete;
+ ++IncompleteCount;
+}
+
+/// Once the RecordType has been expanded, the temporary incomplete TypeString
+/// must be removed from the cache.
+/// If a Recursive was swapped out by addIncomplete(), it will be replaced.
+/// Returns true if the RecordType was defined recursively.
+bool TypeStringCache::removeIncomplete(const IdentifierInfo *ID) {
+ if (!ID)
+ return false;
+ auto I = Map.find(ID);
+ assert(I != Map.end() && "Entry not present");
+ Entry &E = I->second;
+ assert( (E.State == Incomplete ||
+ E.State == IncompleteUsed) &&
+ "Entry must be an incomplete type");
+ bool IsRecursive = false;
+ if (E.State == IncompleteUsed) {
+ // We made use of our Incomplete encoding, thus we are recursive.
+ IsRecursive = true;
+ --IncompleteUsedCount;
+ }
+ if (E.Swapped.empty())
+ Map.erase(I);
+ else {
+ // Swap the Recursive back.
+ E.Swapped.swap(E.Str);
+ E.Swapped.clear();
+ E.State = Recursive;
+ }
+ --IncompleteCount;
+ return IsRecursive;
+}
+
+/// Add the encoded TypeString to the cache only if it is NonRecursive or
+/// Recursive (viz: all sub-members were expanded as fully as possible).
+void TypeStringCache::addIfComplete(const IdentifierInfo *ID, StringRef Str,
+ bool IsRecursive) {
+ if (!ID || IncompleteUsedCount)
+ return; // No key or it is is an incomplete sub-type so don't add.
+ Entry &E = Map[ID];
+ if (IsRecursive && !E.Str.empty()) {
+ assert(E.State==Recursive && E.Str.size() == Str.size() &&
+ "This is not the same Recursive entry");
+ // The parent container was not recursive after all, so we could have used
+ // this Recursive sub-member entry after all, but we assumed the worse when
+ // we started viz: IncompleteCount!=0.
+ return;
+ }
+ assert(E.Str.empty() && "Entry already present");
+ E.Str = Str.str();
+ E.State = IsRecursive? Recursive : NonRecursive;
+}
+
+/// Return a cached TypeString encoding for the ID. If there isn't one, or we
+/// are recursively expanding a type (IncompleteCount != 0) and the cached
+/// encoding is Recursive, return an empty StringRef.
+StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) {
+ if (!ID)
+ return StringRef(); // We have no key.
+ auto I = Map.find(ID);
+ if (I == Map.end())
+ return StringRef(); // We have no encoding.
+ Entry &E = I->second;
+ if (E.State == Recursive && IncompleteCount)
+ return StringRef(); // We don't use Recursive encodings for member types.
+
+ if (E.State == Incomplete) {
+ // The incomplete type is being used to break out of recursion.
+ E.State = IncompleteUsed;
+ ++IncompleteUsedCount;
+ }
+ return E.Str.c_str();
+}
+
+/// The XCore ABI includes a type information section that communicates symbol
+/// type information to the linker. The linker uses this information to verify
+/// safety/correctness of things such as array bound and pointers et al.
+/// The ABI only requires C (and XC) language modules to emit TypeStrings.
+/// This type information (TypeString) is emitted into meta data for all global
+/// symbols: definitions, declarations, functions & variables.
+///
+/// The TypeString carries type, qualifier, name, size & value details.
+/// Please see 'Tools Development Guide' section 2.16.2 for format details:
+/// <https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf>
+/// The output is tested by test/CodeGen/xcore-stringtype.c.
+///
+static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
+ CodeGen::CodeGenModule &CGM, TypeStringCache &TSC);
+
+/// XCore uses emitTargetMD to emit TypeString metadata for global symbols.
+void XCoreTargetCodeGenInfo::emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const {
+ SmallStringEnc Enc;
+ if (getTypeString(Enc, D, CGM, TSC)) {
+ llvm::LLVMContext &Ctx = CGM.getModule().getContext();
+ llvm::SmallVector<llvm::Value *, 2> MDVals;
+ MDVals.push_back(GV);
+ MDVals.push_back(llvm::MDString::get(Ctx, Enc.str()));
+ llvm::NamedMDNode *MD =
+ CGM.getModule().getOrInsertNamedMetadata("xcore.typestrings");
+ MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
+ }
+}
+
+static bool appendType(SmallStringEnc &Enc, QualType QType,
+ const CodeGen::CodeGenModule &CGM,
+ TypeStringCache &TSC);
+
+/// Helper function for appendRecordType().
+/// Builds a SmallVector containing the encoded field types in declaration order.
+static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE,
+ const RecordDecl *RD,
+ const CodeGen::CodeGenModule &CGM,
+ TypeStringCache &TSC) {
+ for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I) {
+ SmallStringEnc Enc;
+ Enc += "m(";
+ Enc += I->getName();
+ Enc += "){";
+ if (I->isBitField()) {
+ Enc += "b(";
+ llvm::raw_svector_ostream OS(Enc);
+ OS.resync();
+ OS << I->getBitWidthValue(CGM.getContext());
+ OS.flush();
+ Enc += ':';
+ }
+ if (!appendType(Enc, I->getType(), CGM, TSC))
+ return false;
+ if (I->isBitField())
+ Enc += ')';
+ Enc += '}';
+ FE.push_back(FieldEncoding(!I->getName().empty(), Enc));
+ }
+ return true;
+}
+
+/// Appends structure and union types to Enc and adds encoding to cache.
+/// Recursively calls appendType (via extractFieldType) for each field.
+/// Union types have their fields ordered according to the ABI.
+static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT,
+ const CodeGen::CodeGenModule &CGM,
+ TypeStringCache &TSC, const IdentifierInfo *ID) {
+ // Append the cached TypeString if we have one.
+ StringRef TypeString = TSC.lookupStr(ID);
+ if (!TypeString.empty()) {
+ Enc += TypeString;
+ return true;
+ }
+
+ // Start to emit an incomplete TypeString.
+ size_t Start = Enc.size();
+ Enc += (RT->isUnionType()? 'u' : 's');
+ Enc += '(';
+ if (ID)
+ Enc += ID->getName();
+ Enc += "){";
+
+ // We collect all encoded fields and order as necessary.
+ bool IsRecursive = false;
+ const RecordDecl *RD = RT->getDecl()->getDefinition();
+ if (RD && !RD->field_empty()) {
+ // An incomplete TypeString stub is placed in the cache for this RecordType
+ // so that recursive calls to this RecordType will use it whilst building a
+ // complete TypeString for this RecordType.
+ SmallVector<FieldEncoding, 16> FE;
+ std::string StubEnc(Enc.substr(Start).str());
+ StubEnc += '}'; // StubEnc now holds a valid incomplete TypeString.
+ TSC.addIncomplete(ID, std::move(StubEnc));
+ if (!extractFieldType(FE, RD, CGM, TSC)) {
+ (void) TSC.removeIncomplete(ID);
+ return false;
+ }
+ IsRecursive = TSC.removeIncomplete(ID);
+ // The ABI requires unions to be sorted but not structures.
+ // See FieldEncoding::operator< for sort algorithm.
+ if (RT->isUnionType())
+ std::sort(FE.begin(), FE.end());
+ // We can now complete the TypeString.
+ unsigned E = FE.size();
+ for (unsigned I = 0; I != E; ++I) {
+ if (I)
+ Enc += ',';
+ Enc += FE[I].str();
+ }
+ }
+ Enc += '}';
+ TSC.addIfComplete(ID, Enc.substr(Start), IsRecursive);
+ return true;
+}
+
+/// Appends enum types to Enc and adds the encoding to the cache.
+static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET,
+ TypeStringCache &TSC,
+ const IdentifierInfo *ID) {
+ // Append the cached TypeString if we have one.
+ StringRef TypeString = TSC.lookupStr(ID);
+ if (!TypeString.empty()) {
+ Enc += TypeString;
+ return true;
+ }
+
+ size_t Start = Enc.size();
+ Enc += "e(";
+ if (ID)
+ Enc += ID->getName();
+ Enc += "){";
+
+ // We collect all encoded enumerations and order them alphanumerically.
+ if (const EnumDecl *ED = ET->getDecl()->getDefinition()) {
+ SmallVector<FieldEncoding, 16> FE;
+ for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E;
+ ++I) {
+ SmallStringEnc EnumEnc;
+ EnumEnc += "m(";
+ EnumEnc += I->getName();
+ EnumEnc += "){";
+ I->getInitVal().toString(EnumEnc);
+ EnumEnc += '}';
+ FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc));
+ }
+ std::sort(FE.begin(), FE.end());
+ unsigned E = FE.size();
+ for (unsigned I = 0; I != E; ++I) {
+ if (I)
+ Enc += ',';
+ Enc += FE[I].str();
+ }
+ }
+ Enc += '}';
+ TSC.addIfComplete(ID, Enc.substr(Start), false);
+ return true;
+}
+
+/// Appends type's qualifier to Enc.
+/// This is done prior to appending the type's encoding.
+static void appendQualifier(SmallStringEnc &Enc, QualType QT) {
+ // Qualifiers are emitted in alphabetical order.
+ static const char *Table[] = {"","c:","r:","cr:","v:","cv:","rv:","crv:"};
+ int Lookup = 0;
+ if (QT.isConstQualified())
+ Lookup += 1<<0;
+ if (QT.isRestrictQualified())
+ Lookup += 1<<1;
+ if (QT.isVolatileQualified())
+ Lookup += 1<<2;
+ Enc += Table[Lookup];
+}
+
+/// Appends built-in types to Enc.
+static bool appendBuiltinType(SmallStringEnc &Enc, const BuiltinType *BT) {
+ const char *EncType;
+ switch (BT->getKind()) {
+ case BuiltinType::Void:
+ EncType = "0";
+ break;
+ case BuiltinType::Bool:
+ EncType = "b";
+ break;
+ case BuiltinType::Char_U:
+ EncType = "uc";
+ break;
+ case BuiltinType::UChar:
+ EncType = "uc";
+ break;
+ case BuiltinType::SChar:
+ EncType = "sc";
+ break;
+ case BuiltinType::UShort:
+ EncType = "us";
+ break;
+ case BuiltinType::Short:
+ EncType = "ss";
+ break;
+ case BuiltinType::UInt:
+ EncType = "ui";
+ break;
+ case BuiltinType::Int:
+ EncType = "si";
+ break;
+ case BuiltinType::ULong:
+ EncType = "ul";
+ break;
+ case BuiltinType::Long:
+ EncType = "sl";
+ break;
+ case BuiltinType::ULongLong:
+ EncType = "ull";
+ break;
+ case BuiltinType::LongLong:
+ EncType = "sll";
+ break;
+ case BuiltinType::Float:
+ EncType = "ft";
+ break;
+ case BuiltinType::Double:
+ EncType = "d";
+ break;
+ case BuiltinType::LongDouble:
+ EncType = "ld";
+ break;
+ default:
+ return false;
+ }
+ Enc += EncType;
+ return true;
+}
+
+/// Appends a pointer encoding to Enc before calling appendType for the pointee.
+static bool appendPointerType(SmallStringEnc &Enc, const PointerType *PT,
+ const CodeGen::CodeGenModule &CGM,
+ TypeStringCache &TSC) {
+ Enc += "p(";
+ if (!appendType(Enc, PT->getPointeeType(), CGM, TSC))
+ return false;
+ Enc += ')';
+ return true;
+}
+
+/// Appends array encoding to Enc before calling appendType for the element.
+static bool appendArrayType(SmallStringEnc &Enc, const ArrayType *AT,
+ const CodeGen::CodeGenModule &CGM,
+ TypeStringCache &TSC, StringRef NoSizeEnc) {
+ if (AT->getSizeModifier() != ArrayType::Normal)
+ return false;
+ Enc += "a(";
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
+ CAT->getSize().toStringUnsigned(Enc);
+ else
+ Enc += NoSizeEnc; // Global arrays use "*", otherwise it is "".
+ Enc += ':';
+ if (!appendType(Enc, AT->getElementType(), CGM, TSC))
+ return false;
+ Enc += ')';
+ return true;
+}
+
+/// Appends a function encoding to Enc, calling appendType for the return type
+/// and the arguments.
+static bool appendFunctionType(SmallStringEnc &Enc, const FunctionType *FT,
+ const CodeGen::CodeGenModule &CGM,
+ TypeStringCache &TSC) {
+ Enc += "f{";
+ if (!appendType(Enc, FT->getReturnType(), CGM, TSC))
+ return false;
+ Enc += "}(";
+ if (const FunctionProtoType *FPT = FT->getAs<FunctionProtoType>()) {
+ // N.B. we are only interested in the adjusted param types.
+ auto I = FPT->param_type_begin();
+ auto E = FPT->param_type_end();
+ if (I != E) {
+ do {
+ if (!appendType(Enc, *I, CGM, TSC))
+ return false;
+ ++I;
+ if (I != E)
+ Enc += ',';
+ } while (I != E);
+ if (FPT->isVariadic())
+ Enc += ",va";
+ } else {
+ if (FPT->isVariadic())
+ Enc += "va";
+ else
+ Enc += '0';
+ }
+ }
+ Enc += ')';
+ return true;
+}
+
+/// Handles the type's qualifier before dispatching a call to handle specific
+/// type encodings.
+static bool appendType(SmallStringEnc &Enc, QualType QType,
+ const CodeGen::CodeGenModule &CGM,
+ TypeStringCache &TSC) {
+
+ QualType QT = QType.getCanonicalType();
+
+ appendQualifier(Enc, QT);
+
+ if (const BuiltinType *BT = QT->getAs<BuiltinType>())
+ return appendBuiltinType(Enc, BT);
+
+ if (const ArrayType *AT = QT->getAsArrayTypeUnsafe())
+ return appendArrayType(Enc, AT, CGM, TSC, "");
+
+ if (const PointerType *PT = QT->getAs<PointerType>())
+ return appendPointerType(Enc, PT, CGM, TSC);
+
+ if (const EnumType *ET = QT->getAs<EnumType>())
+ return appendEnumType(Enc, ET, TSC, QT.getBaseTypeIdentifier());
+
+ if (const RecordType *RT = QT->getAsStructureType())
+ return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier());
+
+ if (const RecordType *RT = QT->getAsUnionType())
+ return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier());
+
+ if (const FunctionType *FT = QT->getAs<FunctionType>())
+ return appendFunctionType(Enc, FT, CGM, TSC);
+
+ return false;
+}
+
+static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
+ CodeGen::CodeGenModule &CGM, TypeStringCache &TSC) {
+ if (!D)
+ return false;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->getLanguageLinkage() != CLanguageLinkage)
+ return false;
+ return appendType(Enc, FD->getType(), CGM, TSC);
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->getLanguageLinkage() != CLanguageLinkage)
+ return false;
+ QualType QT = VD->getType().getCanonicalType();
+ if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) {
+ // Global ArrayTypes are given a size of '*' if the size is unknown.
+ appendQualifier(Enc, QT);
+ return appendArrayType(Enc, AT, CGM, TSC, "*");
+ }
+ return appendType(Enc, QT, CGM, TSC);
+ }
+ return false;
+}
+
+
//===----------------------------------------------------------------------===//
// Driver code
//===----------------------------------------------------------------------===//
@@ -6135,17 +6466,16 @@
case llvm::Triple::mips64el:
return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types, false));
- case llvm::Triple::arm64: {
- ARM64ABIInfo::ABIKind Kind = ARM64ABIInfo::AAPCS;
- if (strcmp(getTarget().getABI(), "darwinpcs") == 0)
- Kind = ARM64ABIInfo::DarwinPCS;
-
- return *(TheTargetCodeGenInfo = new ARM64TargetCodeGenInfo(Types, Kind));
- }
-
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- return *(TheTargetCodeGenInfo = new AArch64TargetCodeGenInfo(Types));
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be: {
+ AArch64ABIInfo::ABIKind Kind = AArch64ABIInfo::AAPCS;
+ if (strcmp(getTarget().getABI(), "darwinpcs") == 0)
+ Kind = AArch64ABIInfo::DarwinPCS;
+
+ return *(TheTargetCodeGenInfo = new AArch64TargetCodeGenInfo(Types, Kind));
+ }
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -6220,8 +6550,6 @@
switch (Triple.getOS()) {
case llvm::Triple::Win32:
- case llvm::Triple::MinGW32:
- case llvm::Triple::Cygwin:
return *(TheTargetCodeGenInfo = new WinX86_64TargetCodeGenInfo(Types));
case llvm::Triple::NaCl:
return *(TheTargetCodeGenInfo = new NaClX86_64TargetCodeGenInfo(Types,
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index 6c3ab64..2616820 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/lib/CodeGen/TargetInfo.h
@@ -21,189 +21,195 @@
#include "llvm/ADT/StringRef.h"
namespace llvm {
- class Constant;
- class GlobalValue;
- class Type;
- class Value;
+class Constant;
+class GlobalValue;
+class Type;
+class Value;
}
namespace clang {
- class ABIInfo;
- class Decl;
+class ABIInfo;
+class Decl;
- namespace CodeGen {
- class CallArgList;
- class CodeGenModule;
- class CodeGenFunction;
- class CGFunctionInfo;
+namespace CodeGen {
+class CallArgList;
+class CodeGenModule;
+class CodeGenFunction;
+class CGFunctionInfo;
+}
+
+/// TargetCodeGenInfo - This class organizes various target-specific
+/// codegeneration issues, like target-specific attributes, builtins and so
+/// on.
+class TargetCodeGenInfo {
+ ABIInfo *Info;
+
+public:
+ // WARNING: Acquires the ownership of ABIInfo.
+ TargetCodeGenInfo(ABIInfo *info = 0) : Info(info) {}
+ virtual ~TargetCodeGenInfo();
+
+ /// getABIInfo() - Returns ABI info helper for the target.
+ const ABIInfo &getABIInfo() const { return *Info; }
+
+ /// SetTargetAttributes - Provides a convenient hook to handle extra
+ /// target-specific attributes for the given global.
+ virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const {}
+
+ /// EmitTargetMD - Provides a convenient hook to handle extra
+ /// target-specific metadata for the given global.
+ virtual void emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const {}
+
+ /// Determines the size of struct _Unwind_Exception on this platform,
+ /// in 8-bit units. The Itanium ABI defines this as:
+ /// struct _Unwind_Exception {
+ /// uint64 exception_class;
+ /// _Unwind_Exception_Cleanup_Fn exception_cleanup;
+ /// uint64 private_1;
+ /// uint64 private_2;
+ /// };
+ virtual unsigned getSizeOfUnwindException() const;
+
+ /// Controls whether __builtin_extend_pointer should sign-extend
+ /// pointers to uint64_t or zero-extend them (the default). Has
+ /// no effect for targets:
+ /// - that have 64-bit pointers, or
+ /// - that cannot address through registers larger than pointers, or
+ /// - that implicitly ignore/truncate the top bits when addressing
+ /// through such registers.
+ virtual bool extendPointerWithSExt() const { return false; }
+
+ /// Determines the DWARF register number for the stack pointer, for
+ /// exception-handling purposes. Implements __builtin_dwarf_sp_column.
+ ///
+ /// Returns -1 if the operation is unsupported by this target.
+ virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
+ return -1;
}
- /// TargetCodeGenInfo - This class organizes various target-specific
- /// codegeneration issues, like target-specific attributes, builtins and so
- /// on.
- class TargetCodeGenInfo {
- ABIInfo *Info;
- public:
- // WARNING: Acquires the ownership of ABIInfo.
- TargetCodeGenInfo(ABIInfo *info = 0):Info(info) { }
- virtual ~TargetCodeGenInfo();
+ /// Initializes the given DWARF EH register-size table, a char*.
+ /// Implements __builtin_init_dwarf_reg_size_table.
+ ///
+ /// Returns true if the operation is unsupported by this target.
+ virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ return true;
+ }
- /// getABIInfo() - Returns ABI info helper for the target.
- const ABIInfo& getABIInfo() const { return *Info; }
+ /// Performs the code-generation required to convert a return
+ /// address as stored by the system into the actual address of the
+ /// next instruction that will be executed.
+ ///
+ /// Used by __builtin_extract_return_addr().
+ virtual llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ return Address;
+ }
- /// SetTargetAttributes - Provides a convenient hook to handle extra
- /// target-specific attributes for the given global.
- virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const { }
+ /// Performs the code-generation required to convert the address
+ /// of an instruction into a return address suitable for storage
+ /// by the system in a return slot.
+ ///
+ /// Used by __builtin_frob_return_addr().
+ virtual llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ return Address;
+ }
- /// Determines the size of struct _Unwind_Exception on this platform,
- /// in 8-bit units. The Itanium ABI defines this as:
- /// struct _Unwind_Exception {
- /// uint64 exception_class;
- /// _Unwind_Exception_Cleanup_Fn exception_cleanup;
- /// uint64 private_1;
- /// uint64 private_2;
- /// };
- virtual unsigned getSizeOfUnwindException() const;
+ /// Corrects the low-level LLVM type for a given constraint and "usual"
+ /// type.
+ ///
+ /// \returns A pointer to a new LLVM type, possibly the same as the original
+ /// on success; 0 on failure.
+ virtual llvm::Type *adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
+ StringRef Constraint,
+ llvm::Type *Ty) const {
+ return Ty;
+ }
- /// Controls whether __builtin_extend_pointer should sign-extend
- /// pointers to uint64_t or zero-extend them (the default). Has
- /// no effect for targets:
- /// - that have 64-bit pointers, or
- /// - that cannot address through registers larger than pointers, or
- /// - that implicitly ignore/truncate the top bits when addressing
- /// through such registers.
- virtual bool extendPointerWithSExt() const { return false; }
+ /// doesReturnSlotInterfereWithArgs - Return true if the target uses an
+ /// argument slot for an 'sret' type.
+ virtual bool doesReturnSlotInterfereWithArgs() const { return true; }
- /// Determines the DWARF register number for the stack pointer, for
- /// exception-handling purposes. Implements __builtin_dwarf_sp_column.
- ///
- /// Returns -1 if the operation is unsupported by this target.
- virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
- return -1;
- }
+ /// Retrieve the address of a function to call immediately before
+ /// calling objc_retainAutoreleasedReturnValue. The
+ /// implementation of objc_autoreleaseReturnValue sniffs the
+ /// instruction stream following its return address to decide
+ /// whether it's a call to objc_retainAutoreleasedReturnValue.
+ /// This can be prohibitively expensive, depending on the
+ /// relocation model, and so on some targets it instead sniffs for
+ /// a particular instruction sequence. This functions returns
+ /// that instruction sequence in inline assembly, which will be
+ /// empty if none is required.
+ virtual StringRef getARCRetainAutoreleasedReturnValueMarker() const {
+ return "";
+ }
- /// Initializes the given DWARF EH register-size table, a char*.
- /// Implements __builtin_init_dwarf_reg_size_table.
- ///
- /// Returns true if the operation is unsupported by this target.
- virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *Address) const {
- return true;
- }
+ /// Return a constant used by UBSan as a signature to identify functions
+ /// possessing type information, or 0 if the platform is unsupported.
+ virtual llvm::Constant *
+ getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const {
+ return nullptr;
+ }
- /// Performs the code-generation required to convert a return
- /// address as stored by the system into the actual address of the
- /// next instruction that will be executed.
- ///
- /// Used by __builtin_extract_return_addr().
- virtual llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
- llvm::Value *Address) const {
- return Address;
- }
+ /// Determine whether a call to an unprototyped functions under
+ /// the given calling convention should use the variadic
+ /// convention or the non-variadic convention.
+ ///
+ /// There's a good reason to make a platform's variadic calling
+ /// convention be different from its non-variadic calling
+ /// convention: the non-variadic arguments can be passed in
+ /// registers (better for performance), and the variadic arguments
+ /// can be passed on the stack (also better for performance). If
+ /// this is done, however, unprototyped functions *must* use the
+ /// non-variadic convention, because C99 states that a call
+ /// through an unprototyped function type must succeed if the
+ /// function was defined with a non-variadic prototype with
+ /// compatible parameters. Therefore, splitting the conventions
+ /// makes it impossible to call a variadic function through an
+ /// unprototyped type. Since function prototypes came out in the
+ /// late 1970s, this is probably an acceptable trade-off.
+ /// Nonetheless, not all platforms are willing to make it, and in
+ /// particularly x86-64 bends over backwards to make the
+ /// conventions compatible.
+ ///
+ /// The default is false. This is correct whenever:
+ /// - the conventions are exactly the same, because it does not
+ /// matter and the resulting IR will be somewhat prettier in
+ /// certain cases; or
+ /// - the conventions are substantively different in how they pass
+ /// arguments, because in this case using the variadic convention
+ /// will lead to C99 violations.
+ ///
+ /// However, some platforms make the conventions identical except
+ /// for passing additional out-of-band information to a variadic
+ /// function: for example, x86-64 passes the number of SSE
+ /// arguments in %al. On these platforms, it is desirable to
+ /// call unprototyped functions using the variadic convention so
+ /// that unprototyped calls to varargs functions still succeed.
+ ///
+ /// Relatedly, platforms which pass the fixed arguments to this:
+ /// A foo(B, C, D);
+ /// differently than they would pass them to this:
+ /// A foo(B, C, D, ...);
+ /// may need to adjust the debugger-support code in Sema to do the
+ /// right thing when calling a function with no know signature.
+ virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args,
+ const FunctionNoProtoType *fnType) const;
- /// Performs the code-generation required to convert the address
- /// of an instruction into a return address suitable for storage
- /// by the system in a return slot.
- ///
- /// Used by __builtin_frob_return_addr().
- virtual llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
- llvm::Value *Address) const {
- return Address;
- }
+ /// Gets the linker options necessary to link a dependent library on this
+ /// platform.
+ virtual void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const;
- /// Corrects the low-level LLVM type for a given constraint and "usual"
- /// type.
- ///
- /// \returns A pointer to a new LLVM type, possibly the same as the original
- /// on success; 0 on failure.
- virtual llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
- StringRef Constraint,
- llvm::Type* Ty) const {
- return Ty;
- }
-
- /// doesReturnSlotInterfereWithArgs - Return true if the target uses an
- /// argument slot for an 'sret' type.
- virtual bool doesReturnSlotInterfereWithArgs() const { return true; }
-
- /// Retrieve the address of a function to call immediately before
- /// calling objc_retainAutoreleasedReturnValue. The
- /// implementation of objc_autoreleaseReturnValue sniffs the
- /// instruction stream following its return address to decide
- /// whether it's a call to objc_retainAutoreleasedReturnValue.
- /// This can be prohibitively expensive, depending on the
- /// relocation model, and so on some targets it instead sniffs for
- /// a particular instruction sequence. This functions returns
- /// that instruction sequence in inline assembly, which will be
- /// empty if none is required.
- virtual StringRef getARCRetainAutoreleasedReturnValueMarker() const {
- return "";
- }
-
- /// Return a constant used by UBSan as a signature to identify functions
- /// possessing type information, or 0 if the platform is unsupported.
- virtual llvm::Constant *getUBSanFunctionSignature(
- CodeGen::CodeGenModule &CGM) const {
- return 0;
- }
-
- /// Determine whether a call to an unprototyped functions under
- /// the given calling convention should use the variadic
- /// convention or the non-variadic convention.
- ///
- /// There's a good reason to make a platform's variadic calling
- /// convention be different from its non-variadic calling
- /// convention: the non-variadic arguments can be passed in
- /// registers (better for performance), and the variadic arguments
- /// can be passed on the stack (also better for performance). If
- /// this is done, however, unprototyped functions *must* use the
- /// non-variadic convention, because C99 states that a call
- /// through an unprototyped function type must succeed if the
- /// function was defined with a non-variadic prototype with
- /// compatible parameters. Therefore, splitting the conventions
- /// makes it impossible to call a variadic function through an
- /// unprototyped type. Since function prototypes came out in the
- /// late 1970s, this is probably an acceptable trade-off.
- /// Nonetheless, not all platforms are willing to make it, and in
- /// particularly x86-64 bends over backwards to make the
- /// conventions compatible.
- ///
- /// The default is false. This is correct whenever:
- /// - the conventions are exactly the same, because it does not
- /// matter and the resulting IR will be somewhat prettier in
- /// certain cases; or
- /// - the conventions are substantively different in how they pass
- /// arguments, because in this case using the variadic convention
- /// will lead to C99 violations.
- ///
- /// However, some platforms make the conventions identical except
- /// for passing additional out-of-band information to a variadic
- /// function: for example, x86-64 passes the number of SSE
- /// arguments in %al. On these platforms, it is desirable to
- /// call unprototyped functions using the variadic convention so
- /// that unprototyped calls to varargs functions still succeed.
- ///
- /// Relatedly, platforms which pass the fixed arguments to this:
- /// A foo(B, C, D);
- /// differently than they would pass them to this:
- /// A foo(B, C, D, ...);
- /// may need to adjust the debugger-support code in Sema to do the
- /// right thing when calling a function with no know signature.
- virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args,
- const FunctionNoProtoType *fnType) const;
-
- /// Gets the linker options necessary to link a dependent library on this
- /// platform.
- virtual void getDependentLibraryOption(llvm::StringRef Lib,
- llvm::SmallString<24> &Opt) const;
-
- /// Gets the linker options necessary to detect object file mismatches on
- /// this platform.
- virtual void getDetectMismatchOption(llvm::StringRef Name,
- llvm::StringRef Value,
- llvm::SmallString<32> &Opt) const {}
- };
+ /// Gets the linker options necessary to detect object file mismatches on
+ /// this platform.
+ virtual void getDetectMismatchOption(llvm::StringRef Name,
+ llvm::StringRef Value,
+ llvm::SmallString<32> &Opt) const {}
+};
}
#endif // CLANG_CODEGEN_TARGETINFO_H
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index a20a2bd..8ec643c 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -27,7 +27,7 @@
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
InputArgList *_Args, DerivedArgList *_TranslatedArgs)
: TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
- TranslatedArgs(_TranslatedArgs), Redirects(0) {
+ TranslatedArgs(_TranslatedArgs), Redirects(nullptr) {
}
Compilation::~Compilation() {
@@ -199,7 +199,7 @@
if (const Command *C = dyn_cast<Command>(&J)) {
if (!InputsOk(*C, FailingCommands))
return;
- const Command *FailingCommand = 0;
+ const Command *FailingCommand = nullptr;
if (int Res = ExecuteCommand(*C, FailingCommand))
FailingCommands.push_back(std::make_pair(Res, FailingCommand));
} else {
@@ -232,7 +232,7 @@
// Redirect stdout/stderr to /dev/null.
Redirects = new const StringRef*[3]();
- Redirects[0] = 0;
+ Redirects[0] = nullptr;
Redirects[1] = new const StringRef();
Redirects[2] = new const StringRef();
}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 317b822..a0fcf41 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -47,15 +47,14 @@
Driver::Driver(StringRef ClangExecutable,
StringRef DefaultTargetTriple,
- StringRef DefaultImageName,
DiagnosticsEngine &Diags)
: Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
- DefaultImageName(DefaultImageName),
+ DefaultImageName("a.out"),
DriverTitle("clang LLVM compiler"),
- CCPrintOptionsFilename(0), CCPrintHeadersFilename(0),
- CCLogDiagnosticsFilename(0),
+ CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
+ CCLogDiagnosticsFilename(nullptr),
CCCPrintBindings(false),
CCPrintHeaders(false), CCLogDiagnostics(false),
CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
@@ -153,7 +152,7 @@
// option we used to determine the final phase.
phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg)
const {
- Arg *PhaseArg = 0;
+ Arg *PhaseArg = nullptr;
phases::ID FinalPhase;
// -{E,M,MM} and /P only run the preprocessor.
@@ -190,10 +189,11 @@
return FinalPhase;
}
-static Arg* MakeInputArg(const DerivedArgList &Args, OptTable *Opts,
+static Arg* MakeInputArg(DerivedArgList &Args, OptTable *Opts,
StringRef Value) {
Arg *A = new Arg(Opts->getOption(options::OPT_INPUT), Value,
Args.getBaseArgs().MakeIndex(Value), Value.data());
+ Args.AddSynthesizedArg(A);
A->claim();
return A;
}
@@ -419,7 +419,8 @@
// Suppress driver output and emit preprocessor output to temp file.
Mode = CPPMode;
CCGenDiagnostics = true;
- C.getArgs().AddFlagArg(0, Opts->getOption(options::OPT_frewrite_includes));
+ C.getArgs().AddFlagArg(nullptr,
+ Opts->getOption(options::OPT_frewrite_includes));
// Save the original job command(s).
std::string Cmd;
@@ -447,13 +448,14 @@
bool IgnoreInput = false;
// Ignore input from stdin or any inputs that cannot be preprocessed.
- if (!strcmp(it->second->getValue(), "-")) {
+ // Check type first as not all linker inputs have a value.
+ if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
+ IgnoreInput = true;
+ } else if (!strcmp(it->second->getValue(), "-")) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating preprocessed source(s) - ignoring input from stdin"
".";
IgnoreInput = true;
- } else if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
- IgnoreInput = true;
}
if (IgnoreInput) {
@@ -955,13 +957,13 @@
}
// Construct a the list of inputs and their types.
-void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
+void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
InputList &Inputs) const {
// Track the current user specified (-x) input. We also explicitly track the
// argument used to set the type; we only want to claim the type when we
// actually use it, so we warn about unused -x arguments.
types::ID InputType = types::TY_Nothing;
- Arg *InputTypeArg = 0;
+ Arg *InputTypeArg = nullptr;
// The last /TC or /TP option sets the input type to C or C++ globally.
if (Arg *TCTP = Args.getLastArg(options::OPT__SLASH_TC,
@@ -1340,7 +1342,7 @@
if (NumOutputs > 1) {
Diag(clang::diag::err_drv_output_argument_with_multiple_files);
- FinalOutput = 0;
+ FinalOutput = nullptr;
}
}
@@ -1365,7 +1367,7 @@
//
// FIXME: This is a hack; find a cleaner way to integrate this into the
// process.
- const char *LinkingOutput = 0;
+ const char *LinkingOutput = nullptr;
if (isa<LipoJobAction>(A)) {
if (FinalOutput)
LinkingOutput = FinalOutput->getValue();
@@ -1375,7 +1377,7 @@
InputInfo II;
BuildJobsForAction(C, A, &C.getDefaultToolChain(),
- /*BoundArch*/0,
+ /*BoundArch*/nullptr,
/*AtTopLevel*/ true,
/*MultipleArchs*/ ArchNames.size() > 1,
/*LinkingOutput*/ LinkingOutput,
@@ -1432,7 +1434,7 @@
static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
const JobAction *JA,
const ActionList *&Inputs) {
- const Tool *ToolForJob = 0;
+ const Tool *ToolForJob = nullptr;
// See if we should look for a compiler with an integrated assembler. We match
// bottom up, so what we are actually looking for is an assembler job with a
@@ -1448,7 +1450,7 @@
const Tool *Compiler =
TC->SelectTool(cast<JobAction>(**Inputs->begin()));
if (!Compiler)
- return NULL;
+ return nullptr;
if (Compiler->hasIntegratedAssembler()) {
Inputs = &(*Inputs)[0]->getInputs();
ToolForJob = Compiler;
@@ -1862,18 +1864,28 @@
}
}
- // Handle pseudo-target flags '-EL' and '-EB'.
- if (Arg *A = Args.getLastArg(options::OPT_EL, options::OPT_EB)) {
- if (A->getOption().matches(options::OPT_EL)) {
+ // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
+ // '-mbig-endian'/'-EB'.
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian)) {
+ if (A->getOption().matches(options::OPT_mlittle_endian)) {
if (Target.getArch() == llvm::Triple::mips)
Target.setArch(llvm::Triple::mipsel);
else if (Target.getArch() == llvm::Triple::mips64)
Target.setArch(llvm::Triple::mips64el);
+ else if (Target.getArch() == llvm::Triple::aarch64_be)
+ Target.setArch(llvm::Triple::aarch64);
+ else if (Target.getArch() == llvm::Triple::arm64_be)
+ Target.setArch(llvm::Triple::arm64);
} else {
if (Target.getArch() == llvm::Triple::mipsel)
Target.setArch(llvm::Triple::mips);
else if (Target.getArch() == llvm::Triple::mips64el)
Target.setArch(llvm::Triple::mips64);
+ else if (Target.getArch() == llvm::Triple::aarch64)
+ Target.setArch(llvm::Triple::aarch64_be);
+ else if (Target.getArch() == llvm::Triple::arm64)
+ Target.setArch(llvm::Triple::arm64_be);
}
}
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index 2775d89..38f68eb 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -62,7 +62,8 @@
// These flags are treated as a single argument (e.g., -F<Dir>).
StringRef FlagRef(Flag);
- if (FlagRef.startswith("-F") || FlagRef.startswith("-I"))
+ if (FlagRef.startswith("-F") || FlagRef.startswith("-I") ||
+ FlagRef.startswith("-fmodules-cache-path="))
return 1;
return 0;
@@ -123,9 +124,9 @@
Argv.push_back(Executable);
for (size_t i = 0, e = Arguments.size(); i != e; ++i)
Argv.push_back(Arguments[i]);
- Argv.push_back(0);
+ Argv.push_back(nullptr);
- return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ 0,
+ return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
Redirects, /*secondsToWait*/ 0,
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}
diff --git a/lib/Driver/Multilib.cpp b/lib/Driver/Multilib.cpp
index 910e638..484ce16 100644
--- a/lib/Driver/Multilib.cpp
+++ b/lib/Driver/Multilib.cpp
@@ -90,10 +90,9 @@
OS << StringRef(GCCSuffix).drop_front();
}
OS << ";";
- for (flags_list::const_iterator I = Flags.begin(), E = Flags.end(); I != E;
- ++I) {
- if (StringRef(*I).front() == '+')
- OS << "@" << I->substr(1);
+ for (StringRef Flag : Flags) {
+ if (Flag.front() == '+')
+ OS << "@" << Flag.substr(1);
}
}
@@ -117,16 +116,12 @@
// Check whether the flags sets match
// allowing for the match to be order invariant
llvm::StringSet<> MyFlags;
- for (flags_list::const_iterator I = Flags.begin(), E = Flags.end(); I != E;
- ++I) {
- MyFlags.insert(*I);
- }
- for (flags_list::const_iterator I = Other.Flags.begin(),
- E = Other.Flags.end();
- I != E; ++I) {
- if (MyFlags.find(*I) == MyFlags.end())
+ for (const auto &Flag : Flags)
+ MyFlags.insert(Flag);
+
+ for (const auto &Flag : Other.Flags)
+ if (MyFlags.find(Flag) == MyFlags.end())
return false;
- }
if (osSuffix() != Other.osSuffix())
return false;
@@ -148,10 +143,7 @@
MultilibSet &MultilibSet::Maybe(const Multilib &M) {
Multilib Opposite;
// Negate any '+' flags
- for (Multilib::flags_list::const_iterator I = M.flags().begin(),
- E = M.flags().end();
- I != E; ++I) {
- StringRef Flag(*I);
+ for (StringRef Flag : M.flags()) {
if (Flag.front() == '+')
Opposite.flags().push_back(("-" + Flag.substr(1)).str());
}
@@ -223,12 +215,9 @@
Multilibs.insert(Multilibs.end(), MultilibSegments.begin(),
MultilibSegments.end());
else {
- for (std::vector<Multilib>::const_iterator NewI = MultilibSegments.begin(),
- NewE = MultilibSegments.end();
- NewI != NewE; ++NewI) {
- for (const_iterator BaseI = begin(), BaseE = end(); BaseI != BaseE;
- ++BaseI) {
- Multilib MO = compose(*BaseI, *NewI);
+ for (const Multilib &New : MultilibSegments) {
+ for (const Multilib &Base : *this) {
+ Multilib MO = compose(Base, New);
if (MO.isValid())
Composed.push_back(MO);
}
@@ -282,20 +271,14 @@
// Stuff all of the flags into the FlagSet such that a true mappend
// indicates the flag was enabled, and a false mappend indicates the
// flag was disabled
- for (Multilib::flags_list::const_iterator I = Flags.begin(),
- E = Flags.end();
- I != E; ++I) {
- FlagSet[StringRef(*I).substr(1)] = isFlagEnabled(*I);
- }
+ for (StringRef Flag : Flags)
+ FlagSet[Flag.substr(1)] = isFlagEnabled(Flag);
}
bool operator()(const Multilib &M) const override {
- for (Multilib::flags_list::const_iterator I = M.flags().begin(),
- E = M.flags().end();
- I != E; ++I) {
- StringRef Flag(*I);
+ for (StringRef Flag : M.flags()) {
llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1));
if (SI != FlagSet.end())
- if ((*SI).getValue() != isFlagEnabled(Flag))
+ if (SI->getValue() != isFlagEnabled(Flag))
return true;
}
return false;
@@ -326,8 +309,8 @@
}
void MultilibSet::print(raw_ostream &OS) const {
- for (const_iterator I = begin(), E = end(); I != E; ++I)
- OS << *I << "\n";
+ for (const Multilib &M : *this)
+ OS << M << "\n";
}
MultilibSet::multilib_list
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 78c8d18..c336195 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -331,7 +331,7 @@
bool SanitizerArgs::getDefaultBlacklistForKind(const Driver &D, unsigned Kind,
std::string &BLPath) {
- const char *BlacklistFile = 0;
+ const char *BlacklistFile = nullptr;
if (Kind & NeedsAsanRt)
BlacklistFile = "asan_blacklist.txt";
else if (Kind & NeedsMsanRt)
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index d164edd..eefe487 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -205,6 +205,16 @@
bool IsBigEndian = getTriple().getArch() == llvm::Triple::armeb ||
getTriple().getArch() == llvm::Triple::thumbeb;
+ // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
+ // '-mbig-endian'/'-EB'.
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian)) {
+ if (A->getOption().matches(options::OPT_mlittle_endian))
+ IsBigEndian = false;
+ else
+ IsBigEndian = true;
+ }
+
// Thumb2 is the default for V7 on Darwin.
//
// FIXME: Thumb should just be another -target-feaure, not in the triple.
@@ -214,6 +224,9 @@
bool ThumbDefault = Suffix.startswith("v6m") || Suffix.startswith("v7m") ||
Suffix.startswith("v7em") ||
(Suffix.startswith("v7") && getTriple().isOSBinFormatMachO());
+ // FIXME: this is invalid for WindowsCE
+ if (getTriple().isOSWindows())
+ ThumbDefault = true;
std::string ArchName;
if (IsBigEndian)
ArchName = "armeb";
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index c1f7ccc..8d8e7c7 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -45,6 +45,14 @@
MachO::MachO(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
+ // We expect 'as', 'ld', etc. to be adjacent to our install dir.
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
}
/// Darwin - Darwin tool chain for i386 and x86_64.
@@ -118,7 +126,7 @@
.Cases("armv7k", "armv7-k", "armv7k")
.Cases("armv7m", "armv7-m", "armv7m")
.Cases("armv7s", "armv7-s", "armv7s")
- .Default(0);
+ .Default(nullptr);
}
static const char *GetArmArchForMCpu(StringRef Value) {
@@ -135,7 +143,7 @@
.Case("cortex-m3", "armv7m")
.Case("cortex-m4", "armv7em")
.Case("swift", "armv7s")
- .Default(0);
+ .Default(nullptr);
}
static bool isSoftFloatABI(const ArgList &Args) {
@@ -232,14 +240,6 @@
DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
: Darwin(D, Triple, Args) {
- getProgramPaths().push_back(getDriver().getInstalledDir());
- if (getDriver().getInstalledDir() != getDriver().Dir)
- getProgramPaths().push_back(getDriver().Dir);
-
- // We expect 'as', 'ld', etc. to be adjacent to our install dir.
- getProgramPaths().push_back(getDriver().getInstalledDir());
- if (getDriver().getInstalledDir() != getDriver().Dir)
- getProgramPaths().push_back(getDriver().Dir);
}
void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
@@ -400,7 +400,8 @@
// it never went into the SDK.
// Linking against libgcc_s.1 isn't needed for iOS 5.0+
if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
- getTriple().getArch() != llvm::Triple::arm64)
+ (getTriple().getArch() != llvm::Triple::arm64 &&
+ getTriple().getArch() != llvm::Triple::aarch64))
CmdArgs.push_back("-lgcc_s.1");
// We currently always need a static runtime library for iOS.
@@ -449,7 +450,7 @@
if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env) &&
StringRef(env) != "/") {
Args.append(Args.MakeSeparateArg(
- 0, Opts.getOption(options::OPT_isysroot), env));
+ nullptr, Opts.getOption(options::OPT_isysroot), env));
}
}
}
@@ -463,12 +464,12 @@
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
<< OSXVersion->getAsString(Args)
<< (iOSVersion ? iOSVersion : iOSSimVersion)->getAsString(Args);
- iOSVersion = iOSSimVersion = 0;
+ iOSVersion = iOSSimVersion = nullptr;
} else if (iOSVersion && iOSSimVersion) {
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
<< iOSVersion->getAsString(Args)
<< iOSSimVersion->getAsString(Args);
- iOSSimVersion = 0;
+ iOSSimVersion = nullptr;
} else if (!OSXVersion && !iOSVersion && !iOSSimVersion) {
// If no deployment target was specified on the command line, check for
// environment defines.
@@ -520,6 +521,7 @@
if (!OSXTarget.empty() && !iOSTarget.empty()) {
if (getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::thumb)
OSXTarget = "";
else
@@ -528,22 +530,22 @@
if (!OSXTarget.empty()) {
const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget);
+ OSXVersion = Args.MakeJoinedArg(nullptr, O, OSXTarget);
Args.append(OSXVersion);
} else if (!iOSTarget.empty()) {
const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
- iOSVersion = Args.MakeJoinedArg(0, O, iOSTarget);
+ iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget);
Args.append(iOSVersion);
} else if (!iOSSimTarget.empty()) {
const Option O = Opts.getOption(
options::OPT_mios_simulator_version_min_EQ);
- iOSSimVersion = Args.MakeJoinedArg(0, O, iOSSimTarget);
+ iOSSimVersion = Args.MakeJoinedArg(nullptr, O, iOSSimTarget);
Args.append(iOSSimVersion);
} else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
MachOArchName != "armv7em") {
// Otherwise, assume we are targeting OS X.
const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin);
+ OSXVersion = Args.MakeJoinedArg(nullptr, O, MacosxVersionMin);
Args.append(OSXVersion);
}
}
@@ -656,6 +658,7 @@
// Use the newer cc_kext for iOS ARM after 6.0.
if (!isTargetIPhoneOS() || isTargetIOSSimulator() ||
getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::aarch64 ||
!isIPhoneOSVersionLT(6, 0)) {
llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
} else {
@@ -680,10 +683,7 @@
// have something that works, we should reevaluate each translation
// and try to push it down into tool specific logic.
- for (ArgList::const_iterator it = Args.begin(),
- ie = Args.end(); it != ie; ++it) {
- Arg *A = *it;
-
+ for (Arg *A : Args) {
if (A->getOption().matches(options::OPT_Xarch__)) {
// Skip this argument unless the architecture matches either the toolchain
// triple arch, or the arch being bound.
@@ -697,7 +697,7 @@
Arg *OriginalArg = A;
unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
unsigned Prev = Index;
- Arg *XarchArg = Opts.ParseOneArg(Args, Index);
+ std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
// If the argument parsing failed or more than one argument was
// consumed, the -Xarch_ argument's parameter tried to consume
@@ -718,8 +718,8 @@
}
XarchArg->setBaseArg(A);
- A = XarchArg;
+ A = XarchArg.release();
DAL->AddSynthesizedArg(A);
// Linker input arguments require custom handling. The problem is that we
@@ -803,7 +803,8 @@
if (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64)
if (!Args.hasArgNoClaim(options::OPT_mtune_EQ))
- DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ), "core2");
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mtune_EQ),
+ "core2");
// Add the arch options based on the particular spelling of -arch, to match
// how the driver driver works.
@@ -817,76 +818,76 @@
if (Name == "ppc")
;
else if (Name == "ppc601")
- DAL->AddJoinedArg(0, MCpu, "601");
+ DAL->AddJoinedArg(nullptr, MCpu, "601");
else if (Name == "ppc603")
- DAL->AddJoinedArg(0, MCpu, "603");
+ DAL->AddJoinedArg(nullptr, MCpu, "603");
else if (Name == "ppc604")
- DAL->AddJoinedArg(0, MCpu, "604");
+ DAL->AddJoinedArg(nullptr, MCpu, "604");
else if (Name == "ppc604e")
- DAL->AddJoinedArg(0, MCpu, "604e");
+ DAL->AddJoinedArg(nullptr, MCpu, "604e");
else if (Name == "ppc750")
- DAL->AddJoinedArg(0, MCpu, "750");
+ DAL->AddJoinedArg(nullptr, MCpu, "750");
else if (Name == "ppc7400")
- DAL->AddJoinedArg(0, MCpu, "7400");
+ DAL->AddJoinedArg(nullptr, MCpu, "7400");
else if (Name == "ppc7450")
- DAL->AddJoinedArg(0, MCpu, "7450");
+ DAL->AddJoinedArg(nullptr, MCpu, "7450");
else if (Name == "ppc970")
- DAL->AddJoinedArg(0, MCpu, "970");
+ DAL->AddJoinedArg(nullptr, MCpu, "970");
else if (Name == "ppc64" || Name == "ppc64le")
- DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
else if (Name == "i386")
;
else if (Name == "i486")
- DAL->AddJoinedArg(0, MArch, "i486");
+ DAL->AddJoinedArg(nullptr, MArch, "i486");
else if (Name == "i586")
- DAL->AddJoinedArg(0, MArch, "i586");
+ DAL->AddJoinedArg(nullptr, MArch, "i586");
else if (Name == "i686")
- DAL->AddJoinedArg(0, MArch, "i686");
+ DAL->AddJoinedArg(nullptr, MArch, "i686");
else if (Name == "pentium")
- DAL->AddJoinedArg(0, MArch, "pentium");
+ DAL->AddJoinedArg(nullptr, MArch, "pentium");
else if (Name == "pentium2")
- DAL->AddJoinedArg(0, MArch, "pentium2");
+ DAL->AddJoinedArg(nullptr, MArch, "pentium2");
else if (Name == "pentpro")
- DAL->AddJoinedArg(0, MArch, "pentiumpro");
+ DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");
else if (Name == "pentIIm3")
- DAL->AddJoinedArg(0, MArch, "pentium2");
+ DAL->AddJoinedArg(nullptr, MArch, "pentium2");
else if (Name == "x86_64")
- DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
else if (Name == "x86_64h") {
- DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
- DAL->AddJoinedArg(0, MArch, "x86_64h");
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
+ DAL->AddJoinedArg(nullptr, MArch, "x86_64h");
}
else if (Name == "arm")
- DAL->AddJoinedArg(0, MArch, "armv4t");
+ DAL->AddJoinedArg(nullptr, MArch, "armv4t");
else if (Name == "armv4t")
- DAL->AddJoinedArg(0, MArch, "armv4t");
+ DAL->AddJoinedArg(nullptr, MArch, "armv4t");
else if (Name == "armv5")
- DAL->AddJoinedArg(0, MArch, "armv5tej");
+ DAL->AddJoinedArg(nullptr, MArch, "armv5tej");
else if (Name == "xscale")
- DAL->AddJoinedArg(0, MArch, "xscale");
+ DAL->AddJoinedArg(nullptr, MArch, "xscale");
else if (Name == "armv6")
- DAL->AddJoinedArg(0, MArch, "armv6k");
+ DAL->AddJoinedArg(nullptr, MArch, "armv6k");
else if (Name == "armv6m")
- DAL->AddJoinedArg(0, MArch, "armv6m");
+ DAL->AddJoinedArg(nullptr, MArch, "armv6m");
else if (Name == "armv7")
- DAL->AddJoinedArg(0, MArch, "armv7a");
+ DAL->AddJoinedArg(nullptr, MArch, "armv7a");
else if (Name == "armv7em")
- DAL->AddJoinedArg(0, MArch, "armv7em");
+ DAL->AddJoinedArg(nullptr, MArch, "armv7em");
else if (Name == "armv7k")
- DAL->AddJoinedArg(0, MArch, "armv7k");
+ DAL->AddJoinedArg(nullptr, MArch, "armv7k");
else if (Name == "armv7m")
- DAL->AddJoinedArg(0, MArch, "armv7m");
+ DAL->AddJoinedArg(nullptr, MArch, "armv7m");
else if (Name == "armv7s")
- DAL->AddJoinedArg(0, MArch, "armv7s");
+ DAL->AddJoinedArg(nullptr, MArch, "armv7s");
else if (Name == "arm64")
- DAL->AddJoinedArg(0, MArch, "arm64");
+ DAL->AddJoinedArg(nullptr, MArch, "arm64");
else if (Name == "armv8")
- DAL->AddJoinedArg(0, MArch, "arm64");
+ DAL->AddJoinedArg(nullptr, MArch, "arm64");
}
return DAL;
@@ -928,7 +929,8 @@
// but we can't check the deployment target in the translation code until
// it is set here.
if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0) &&
- getTriple().getArch() != llvm::Triple::arm64) {
+ getTriple().getArch() != llvm::Triple::arm64 &&
+ getTriple().getArch() != llvm::Triple::aarch64) {
for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
Arg *A = *it;
++it;
@@ -947,7 +949,8 @@
if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
(isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0))) &&
!Args.getLastArg(options::OPT_stdlib_EQ))
- DAL->AddJoinedArg(0, Opts.getOption(options::OPT_stdlib_EQ), "libc++");
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ),
+ "libc++");
// Validate the C++ standard library choice.
CXXStdlibType Type = GetCXXStdlibType(*DAL);
@@ -994,7 +997,8 @@
bool MachO::isPICDefaultForced() const {
return (getArch() == llvm::Triple::x86_64 ||
- getArch() == llvm::Triple::arm64);
+ getArch() == llvm::Triple::arm64 ||
+ getArch() == llvm::Triple::aarch64);
}
bool MachO::SupportsProfiling() const {
@@ -1083,7 +1087,8 @@
if (isTargetIOSSimulator()) {
; // iOS simulator does not need crt1.o.
} else if (isTargetIPhoneOS()) {
- if (getArch() == llvm::Triple::arm64)
+ if (getArch() == llvm::Triple::arm64 ||
+ getArch() == llvm::Triple::aarch64)
; // iOS does not need any crt1 files for arm64
else if (isIPhoneOSVersionLT(3, 1))
CmdArgs.push_back("-lcrt1.o");
@@ -1285,19 +1290,14 @@
}
void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
- for (std::set<std::string>::const_iterator
- I = CandidateGCCInstallPaths.begin(),
- E = CandidateGCCInstallPaths.end();
- I != E; ++I)
- OS << "Found candidate GCC installation: " << *I << "\n";
+ for (const auto &InstallPath : CandidateGCCInstallPaths)
+ OS << "Found candidate GCC installation: " << InstallPath << "\n";
if (!GCCInstallPath.empty())
OS << "Selected GCC installation: " << GCCInstallPath << "\n";
- for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end();
- I != E; ++I) {
- OS << "Candidate multilib: " << *I << "\n";
- }
+ for (const auto &Multilib : Multilibs)
+ OS << "Candidate multilib: " << Multilib << "\n";
if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())
OS << "Selected multilib: " << SelectedMultilib << "\n";
@@ -1320,9 +1320,11 @@
// Declare a bunch of static data sets that we'll select between below. These
// are specifically designed to always refer to string literals to avoid any
// lifetime or initialization issues.
- static const char *const AArch64LibDirs[] = { "/lib" };
+ static const char *const AArch64LibDirs[] = { "/lib64", "/lib" };
static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu",
- "aarch64-linux-gnu" };
+ "aarch64-linux-gnu",
+ "aarch64-linux-android",
+ "aarch64-redhat-linux" };
static const char *const AArch64beLibDirs[] = { "/lib" };
static const char *const AArch64beTriples[] = { "aarch64_be-none-linux-gnu",
"aarch64_be-linux-gnu" };
@@ -1409,6 +1411,7 @@
BiarchTripleAliases.append(
AArch64Triples, AArch64Triples + llvm::array_lengthof(AArch64Triples));
break;
+ case llvm::Triple::arm64_be:
case llvm::Triple::aarch64_be:
LibDirs.append(AArch64beLibDirs,
AArch64beLibDirs + llvm::array_lengthof(AArch64beLibDirs));
@@ -1651,9 +1654,21 @@
return A && A->getValue() == StringRef("2008");
}
-bool Generic_GCC::GCCInstallationDetector::findMIPSMultilibs(
- const llvm::Triple &TargetTriple, StringRef Path,
- const llvm::opt::ArgList &Args) {
+struct DetectedMultilibs {
+ /// The set of multilibs that the detected installation supports.
+ MultilibSet Multilibs;
+
+ /// The primary multilib appropriate for the given flags.
+ Multilib SelectedMultilib;
+
+ /// On Biarch systems, this corresponds to the default multilib when
+ /// targeting the non-default multilib. Otherwise, it is empty.
+ llvm::Optional<Multilib> BiarchSibling;
+};
+
+static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
+ const llvm::opt::ArgList &Args,
+ DetectedMultilibs &Result) {
// Some MIPS toolchains put libraries and object files compiled
// using different options in to the sub-directoris which names
// reflects the flags used for compilation. For example sysroot
@@ -1882,9 +1897,11 @@
if (TargetTriple.getEnvironment() == llvm::Triple::Android) {
// Select Android toolchain. It's the only choice in that case.
- Multilibs.clear();
- Multilibs.combineWith(AndroidMipsMultilibs);
- return Multilibs.select(Flags, SelectedMultilib);
+ if (AndroidMipsMultilibs.select(Flags, Result.SelectedMultilib)) {
+ Result.Multilibs = AndroidMipsMultilibs;
+ return true;
+ }
+ return false;
}
// Sort candidates. Toolchain that best meets the directories goes first.
@@ -1895,11 +1912,10 @@
std::begin(candidates), std::end(candidates),
[](MultilibSet *a, MultilibSet *b) { return a->size() > b->size(); });
for (const auto &candidate : candidates) {
- Multilibs.clear();
- Multilibs.combineWith(*candidate);
- if (Multilibs.select(Flags, SelectedMultilib)) {
+ if (candidate->select(Flags, Result.SelectedMultilib)) {
if (candidate == &DebianMipsMultilibs)
- BiarchSibling = Multilib();
+ Result.BiarchSibling = Multilib();
+ Result.Multilibs = *candidate;
return true;
}
}
@@ -1907,9 +1923,10 @@
return false;
}
-bool Generic_GCC::GCCInstallationDetector::findBiarchMultilibs(
- const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args,
- bool NeedsBiarchSuffix) {
+static bool findBiarchMultilibs(const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ bool NeedsBiarchSuffix,
+ DetectedMultilibs &Result) {
// Some versions of SUSE and Fedora on ppc64 put 32-bit libs
// in what would normally be GCCInstallPath and put the 64-bit
@@ -1949,22 +1966,21 @@
else
Default.flag("-m32").flag("+m64");
- Multilibs.push_back(Default);
- Multilibs.push_back(Alt64);
- Multilibs.push_back(Alt32);
+ Result.Multilibs.push_back(Default);
+ Result.Multilibs.push_back(Alt64);
+ Result.Multilibs.push_back(Alt32);
- Multilibs.FilterOut(NonExistent);
+ Result.Multilibs.FilterOut(NonExistent);
Multilib::flags_list Flags;
addMultilibFlag(TargetTriple.isArch64Bit(), "m64", Flags);
addMultilibFlag(TargetTriple.isArch32Bit(), "m32", Flags);
- if (!Multilibs.select(Flags, SelectedMultilib))
+ if (!Result.Multilibs.select(Flags, Result.SelectedMultilib))
return false;
- if (SelectedMultilib == Alt64 || SelectedMultilib == Alt32) {
- BiarchSibling = Default;
- }
+ if (Result.SelectedMultilib == Alt64 || Result.SelectedMultilib == Alt32)
+ Result.BiarchSibling = Default;
return true;
}
@@ -2018,19 +2034,21 @@
if (CandidateVersion <= Version)
continue;
- Multilibs.clear();
- SelectedMultilib = Multilib();
- BiarchSibling.reset();
+ DetectedMultilibs Detected;
// Debian mips multilibs behave more like the rest of the biarch ones,
// so handle them there
if (isMipsArch(TargetArch)) {
- if (!findMIPSMultilibs(TargetTriple, LI->path(), Args))
+ if (!findMIPSMultilibs(TargetTriple, LI->path(), Args, Detected))
continue;
} else if (!findBiarchMultilibs(TargetTriple, LI->path(), Args,
- NeedsBiarchSuffix))
+ NeedsBiarchSuffix, Detected)) {
continue;
+ }
+ Multilibs = Detected.Multilibs;
+ SelectedMultilib = Detected.SelectedMultilib;
+ BiarchSibling = Detected.BiarchSibling;
Version = CandidateVersion;
GCCTriple.setTriple(CandidateTriple);
// FIXME: We hack together the directory name here instead of
@@ -2104,6 +2122,7 @@
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::arm64_be ||
getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::armeb ||
getTriple().getArch() == llvm::Triple::thumb ||
@@ -2117,6 +2136,7 @@
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::arm64_be ||
(getTriple().getOS() == llvm::Triple::Linux &&
(!V.isOlderThan(4, 7, 0) ||
getTriple().getEnvironment() == llvm::Triple::Android));
@@ -2403,6 +2423,21 @@
return new tools::bitrig::Link(*this);
}
+ToolChain::CXXStdlibType
+Bitrig::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+ return ToolChain::CST_Libcxx;
+}
+
void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
@@ -2412,7 +2447,7 @@
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx:
addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/");
+ getDriver().SysRoot + "/usr/include/c++/v1");
break;
case ToolChain::CST_Libstdcxx:
addSystemInclude(DriverArgs, CC1Args,
@@ -2438,9 +2473,8 @@
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
- CmdArgs.push_back("-lcxxrt");
- // Include supc++ to provide Unwind until provided by libcxx.
- CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lc++abi");
+ CmdArgs.push_back("-lpthread");
break;
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back("-lstdc++");
@@ -2546,7 +2580,9 @@
getFilePaths().push_back("=/usr/lib/i386");
break;
case llvm::Triple::arm:
+ case llvm::Triple::armeb:
case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
switch (Triple.getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::EABIHF:
@@ -2566,6 +2602,9 @@
else if (tools::mips::hasMipsAbiArg(Args, "64"))
getFilePaths().push_back("=/usr/lib/64");
break;
+ case llvm::Triple::sparc:
+ getFilePaths().push_back("=/usr/lib/sparc");
+ break;
default:
break;
}
@@ -2597,8 +2636,12 @@
unsigned Major, Minor, Micro;
getTriple().getOSVersion(Major, Minor, Micro);
- if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) {
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) {
switch (getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return ToolChain::CST_Libcxx;
@@ -2770,17 +2813,15 @@
StringRef Data = File.get()->getBuffer();
if (Data.startswith("Fedora release"))
return Fedora;
- else if (Data.startswith("Red Hat Enterprise Linux") &&
- Data.find("release 6") != StringRef::npos)
- return RHEL6;
- else if ((Data.startswith("Red Hat Enterprise Linux") ||
- Data.startswith("CentOS")) &&
- Data.find("release 5") != StringRef::npos)
- return RHEL5;
- else if ((Data.startswith("Red Hat Enterprise Linux") ||
- Data.startswith("CentOS")) &&
- Data.find("release 4") != StringRef::npos)
- return RHEL4;
+ if (Data.startswith("Red Hat Enterprise Linux") ||
+ Data.startswith("CentOS")) {
+ if (Data.find("release 6") != StringRef::npos)
+ return RHEL6;
+ else if (Data.find("release 5") != StringRef::npos)
+ return RHEL5;
+ else if (Data.find("release 4") != StringRef::npos)
+ return RHEL4;
+ }
return UnknownDistro;
}
@@ -2860,6 +2901,7 @@
if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64-linux-gnu"))
return "aarch64-linux-gnu";
return TargetTriple.str();
+ case llvm::Triple::arm64_be:
case llvm::Triple::aarch64_be:
if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
return "aarch64_be-linux-gnu";
@@ -3161,10 +3203,9 @@
if (CIncludeDirs != "") {
SmallVector<StringRef, 5> dirs;
CIncludeDirs.split(dirs, ":");
- for (SmallVectorImpl<StringRef>::iterator I = dirs.begin(), E = dirs.end();
- I != E; ++I) {
- StringRef Prefix = llvm::sys::path::is_absolute(*I) ? SysRoot : "";
- addExternCSystemInclude(DriverArgs, CC1Args, Prefix + *I);
+ for (StringRef dir : dirs) {
+ StringRef Prefix = llvm::sys::path::is_absolute(dir) ? SysRoot : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
}
return;
}
@@ -3234,7 +3275,8 @@
MultiarchIncludeDirs = X86MultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
- getTriple().getArch() == llvm::Triple::arm64) {
+ getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::arm64_be) {
MultiarchIncludeDirs = AArch64MultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::arm) {
if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
@@ -3250,11 +3292,9 @@
} else if (getTriple().getArch() == llvm::Triple::ppc64) {
MultiarchIncludeDirs = PPC64MultiarchIncludeDirs;
}
- for (ArrayRef<StringRef>::iterator I = MultiarchIncludeDirs.begin(),
- E = MultiarchIncludeDirs.end();
- I != E; ++I) {
- if (llvm::sys::fs::exists(SysRoot + *I)) {
- addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + *I);
+ for (StringRef Dir : MultiarchIncludeDirs) {
+ if (llvm::sys::fs::exists(SysRoot + Dir)) {
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir);
break;
}
}
@@ -3317,12 +3357,11 @@
// FIXME: We should really remove this. It doesn't make any sense.
getDriver().SysRoot + "/usr/include/c++/v1"
};
- for (unsigned i = 0; i < llvm::array_lengthof(LibCXXIncludePathCandidates);
- ++i) {
- if (!llvm::sys::fs::exists(LibCXXIncludePathCandidates[i]))
+ for (const auto &IncludePath : LibCXXIncludePathCandidates) {
+ if (!llvm::sys::fs::exists(IncludePath))
continue;
// Add the first candidate that exists.
- addSystemInclude(DriverArgs, CC1Args, LibCXXIncludePathCandidates[i]);
+ addSystemInclude(DriverArgs, CC1Args, IncludePath);
break;
}
return;
@@ -3360,9 +3399,8 @@
LibDir.str() + "/../include/c++",
};
- for (unsigned i = 0; i < llvm::array_lengthof(LibStdCXXIncludePathCandidates);
- ++i) {
- if (addLibStdCXXIncludePaths(LibStdCXXIncludePathCandidates[i],
+ for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
+ if (addLibStdCXXIncludePaths(IncludePath,
TripleStr + Multilib.includeSuffix(),
DriverArgs, CC1Args))
break;
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index ad4d4c1..13e9d67 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -145,13 +145,6 @@
const std::string &LibDir,
StringRef CandidateTriple,
bool NeedsBiarchSuffix = false);
-
- bool findMIPSMultilibs(const llvm::Triple &TargetArch, StringRef Path,
- const llvm::opt::ArgList &Args);
-
- bool findBiarchMultilibs(const llvm::Triple &TargetArch, StringRef Path,
- const llvm::opt::ArgList &Args,
- bool NeedsBiarchSuffix);
};
GCCInstallationDetector GCCInstallation;
@@ -541,7 +534,7 @@
bool isPIEDefault() const override { return true; }
unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
- return 1;
+ return 2;
}
protected:
@@ -557,6 +550,7 @@
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
void
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 6acc3d5..76b7962 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -444,26 +444,6 @@
getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs);
}
-/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are targeting.
-//
-// FIXME: tblgen this.
-static std::string getAArch64TargetCPU(const ArgList &Args,
- const llvm::Triple &Triple) {
- // FIXME: Warn on inconsistent use of -mcpu and -march.
-
- // If we have -mcpu=, use that.
- if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
- StringRef MCPU = A->getValue();
- // Handle -mcpu=native.
- if (MCPU == "native")
- return llvm::sys::getHostCPUName();
- else
- return MCPU;
- }
-
- return "generic";
-}
-
// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
@@ -473,8 +453,13 @@
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
case llvm::Triple::arm:
case llvm::Triple::armeb:
+ if (Triple.isOSDarwin() || Triple.isOSWindows())
+ return true;
+ return false;
+
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
if (Triple.isOSDarwin())
@@ -645,6 +630,11 @@
break;
}
+ // FIXME: this is invalid for WindowsCE
+ case llvm::Triple::Win32:
+ FloatABI = "hard";
+ break;
+
case llvm::Triple::FreeBSD:
switch(Triple.getEnvironment()) {
case llvm::Triple::GNUEABIHF:
@@ -758,10 +748,10 @@
// Select the ABI to use.
//
// FIXME: Support -meabi.
- const char *ABIName = 0;
+ const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
- } else if (Triple.isOSDarwin()) {
+ } else if (Triple.isOSBinFormatMachO()) {
// The backend is hardwired to assume AAPCS for M-class processors, ensure
// the frontend matches that.
if (Triple.getEnvironment() == llvm::Triple::EABI ||
@@ -772,6 +762,9 @@
} else {
ABIName = "apcs-gnu";
}
+ } else if (Triple.isOSWindows()) {
+ // FIXME: this is invalid for WindowsCE
+ ABIName = "aapcs";
} else {
// Select the default based on the platform.
switch(Triple.getEnvironment()) {
@@ -848,8 +841,9 @@
}
}
-/// getARM64TargetCPU - Get the (LLVM) name of the ARM64 cpu we are targeting.
-static std::string getARM64TargetCPU(const ArgList &Args) {
+/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
+/// targeting.
+static std::string getAArch64TargetCPU(const ArgList &Args) {
// If we have -mcpu=, use that.
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
StringRef MCPU = A->getValue();
@@ -863,12 +857,16 @@
// At some point, we may need to check -march here, but for now we only
// one arm64 architecture.
- // Default to "cyclone" CPU.
- return "cyclone";
+ // Make sure we pick "cyclone" if -arch is used.
+ // FIXME: Should this be picked by checking the target triple instead?
+ if (Args.getLastArg(options::OPT_arch))
+ return "cyclone";
+
+ return "generic";
}
-void Clang::AddARM64TargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+void Clang::AddAArch64TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
llvm::Triple Triple(TripleStr);
@@ -881,7 +879,7 @@
options::OPT_mno_implicit_float, true))
CmdArgs.push_back("-no-implicit-float");
- const char *ABIName = 0;
+ const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
ABIName = A->getValue();
else if (Triple.isOSDarwin())
@@ -893,11 +891,11 @@
CmdArgs.push_back(ABIName);
CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(getARM64TargetCPU(Args)));
+ CmdArgs.push_back(Args.MakeArgString(getAArch64TargetCPU(Args)));
if (Args.hasArg(options::OPT_mstrict_align)) {
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm64-strict-align");
+ CmdArgs.push_back("-aarch64-strict-align");
}
}
@@ -1020,8 +1018,14 @@
}
if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
- if (StringRef(A->getValue()) == "2008")
+ StringRef Val = StringRef(A->getValue());
+ if (Val == "2008")
Features.push_back("+nan2008");
+ else if (Val == "legacy")
+ Features.push_back("-nan2008");
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
}
AddTargetFeature(Args, Features, options::OPT_msingle_float,
@@ -1281,7 +1285,7 @@
if (Triple.getArch() != llvm::Triple::x86_64 &&
Triple.getArch() != llvm::Triple::x86)
- return 0; // This routine is only handling x86 targets.
+ return nullptr; // This routine is only handling x86 targets.
bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
@@ -1322,7 +1326,9 @@
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- return getAArch64TargetCPU(Args, T);
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
+ return getAArch64TargetCPU(Args);
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -1459,6 +1465,17 @@
}
if (NoImplicitFloat)
CmdArgs.push_back("-no-implicit-float");
+
+ if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "intel" || Value == "att") {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
+ } else {
+ getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
}
static inline bool HasPICArg(const ArgList &Args) {
@@ -1519,6 +1536,15 @@
Features.push_back("-crypto");
Features.push_back("-neon");
}
+
+ // En/disable crc
+ if (Arg *A = Args.getLastArg(options::OPT_mcrc,
+ options::OPT_mnocrc)) {
+ if (A->getOption().matches(options::OPT_mcrc))
+ Features.push_back("+crc");
+ else
+ Features.push_back("-crc");
+ }
}
static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
@@ -1552,6 +1578,8 @@
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
getAArch64TargetFeatures(D, Args, Features);
break;
case llvm::Triple::x86:
@@ -1608,7 +1636,8 @@
};
} // end anonymous namespace.
-// exceptionSettings() exists to share the logic between -cc1 and linker invocations.
+// exceptionSettings() exists to share the logic between -cc1 and linker
+// invocations.
static ExceptionSettings exceptionSettings(const ArgList &Args,
const llvm::Triple &Triple) {
ExceptionSettings ES;
@@ -1710,19 +1739,6 @@
Default);
}
-static bool ShouldDisableCFI(const ArgList &Args,
- const ToolChain &TC) {
- bool Default = true;
- if (TC.getTriple().isOSDarwin()) {
- // The native darwin assembler doesn't support cfi directives, so
- // we disable them if we think the .s file will be passed to it.
- Default = TC.useIntegratedAs();
- }
- return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm,
- options::OPT_fno_dwarf2_cfi_asm,
- Default);
-}
-
static bool ShouldDisableDwarfDirectory(const ArgList &Args,
const ToolChain &TC) {
bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
@@ -1818,6 +1834,8 @@
// -I. The next arg will be the include directory.
if (Value == "-I")
TakeNextArg = true;
+ } else if (Value.startswith("-gdwarf-")) {
+ CmdArgs.push_back(Value.data());
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
@@ -1852,14 +1870,15 @@
return Res;
}
-// This adds the static libclang_rt.arch.a directly to the command line
+// This adds the static libclang_rt.builtins-arch.a directly to the command line
// FIXME: Make sure we can also emit shared objects if they're requested
// and available, check for possible errors, etc.
static void addClangRTLinux(
const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
SmallString<128> LibClangRT = getCompilerRTLibDir(TC);
- llvm::sys::path::append(LibClangRT,
- Twine("libclang_rt.") + getArchNameForCompilerRTLib(TC) + ".a");
+ llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") +
+ getArchNameForCompilerRTLib(TC) +
+ ".a");
CmdArgs.push_back(Args.MakeArgString(LibClangRT));
CmdArgs.push_back("-lgcc_s");
@@ -1876,9 +1895,16 @@
Args.hasArg(options::OPT_coverage)))
return;
+ // -fprofile-instr-generate requires position-independent code to build with
+ // shared objects. Link against the right archive.
+ const char *Lib = "libclang_rt.profile-";
+ if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
+ Args.hasArg(options::OPT_shared))
+ Lib = "libclang_rt.profile-pic-";
+
SmallString<128> LibProfile = getCompilerRTLibDir(TC);
llvm::sys::path::append(LibProfile,
- Twine("libclang_rt.profile-") + getArchNameForCompilerRTLib(TC) + ".a");
+ Twine(Lib) + getArchNameForCompilerRTLib(TC) + ".a");
CmdArgs.push_back(Args.MakeArgString(LibProfile));
}
@@ -1946,7 +1972,7 @@
/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addAsanRT(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs, bool Shared) {
+ ArgStringList &CmdArgs, bool Shared, bool IsCXX) {
if (Shared) {
// Link dynamic runtime if necessary.
SmallString<128> LibSanitizer =
@@ -1959,10 +1985,15 @@
(TC.getTriple().getEnvironment() == llvm::Triple::Android))
return;
- const char *LibAsanStaticPart = Shared ? "asan-preinit" : "asan";
- addSanitizerRTLinkFlags(TC, Args, CmdArgs, LibAsanStaticPart,
- /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ !Shared,
- /*LinkDeps*/ !Shared);
+ if (Shared) {
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit",
+ /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false,
+ /*LinkDeps*/ false);
+ } else {
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
+ if (IsCXX)
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true);
+ }
}
/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux).
@@ -2023,7 +2054,7 @@
Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
if (Sanitize.needsAsanRt())
- addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt());
+ addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(), D.CCCIsCXX());
if (Sanitize.needsTsanRt())
addTsanRT(TC, Args, CmdArgs);
if (Sanitize.needsMsanRt())
@@ -2093,7 +2124,8 @@
return Args.MakeArgString(T);
} else {
// Use the compilation dir.
- SmallString<128> T(Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
+ SmallString<128> T(
+ Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput()));
llvm::sys::path::replace_extension(F, "dwo");
T += F;
@@ -2127,7 +2159,8 @@
}
/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
-static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
+/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
+static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().matches(options::OPT_O4) ||
A->getOption().matches(options::OPT_Ofast))
@@ -2143,9 +2176,9 @@
if (S == "s")
return true;
- // Don't vectorize -Oz.
+ // Don't vectorize -Oz, unless it's the slp vectorizer.
if (S == "z")
- return false;
+ return isSlpVec;
unsigned OptLevel = 0;
if (S.getAsInteger(10, OptLevel))
@@ -2183,7 +2216,8 @@
ArgStringList CmdArgs;
bool IsWindowsGNU = getToolChain().getTriple().isWindowsGNUEnvironment();
- bool IsWindowsCygnus = getToolChain().getTriple().isWindowsCygwinEnvironment();
+ bool IsWindowsCygnus =
+ getToolChain().getTriple().isWindowsCygwinEnvironment();
bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();
assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
@@ -2198,6 +2232,17 @@
std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
CmdArgs.push_back(Args.MakeArgString(TripleStr));
+ const llvm::Triple TT(TripleStr);
+ if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
+ TT.getArch() == llvm::Triple::thumb)) {
+ unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6;
+ unsigned Version;
+ TT.getArchName().substr(Offset).getAsInteger(10, Version);
+ if (Version < 7)
+ D.Diag(diag::err_target_unsupported_arch) << TT.getArchName()
+ << TripleStr;
+ }
+
// Push all default warning arguments that are specific to
// the given target. These come before user provided warning options
// are provided.
@@ -2310,8 +2355,9 @@
if (types::isCXX(Inputs[0].getType()))
CmdArgs.push_back("-analyzer-checker=cplusplus");
- // Enable the following experimental checkers for testing.
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
+ // Enable the following experimental checkers for testing.
+ CmdArgs.push_back(
+ "-analyzer-checker=security.insecureAPI.UncheckedReturn");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
@@ -2349,6 +2395,8 @@
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm64:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -2408,7 +2456,8 @@
// PIC or PIE options above, if these show up, PIC is disabled.
llvm::Triple Triple(TripleStr);
if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6) ||
- Triple.getArch() == llvm::Triple::arm64))
+ Triple.getArch() == llvm::Triple::arm64 ||
+ Triple.getArch() == llvm::Triple::aarch64))
PIC = PIE = false;
if (Args.hasArg(options::OPT_static))
PIC = PIE = false;
@@ -2486,8 +2535,11 @@
// enabled. This alias option is being used to simplify the hasFlag logic.
OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
options::OPT_fstrict_aliasing;
+ // We turn strict aliasing off by default if we're in CL mode, since MSVC
+ // doesn't do any TBAA.
+ bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode();
if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
- options::OPT_fno_strict_aliasing, true))
+ options::OPT_fno_strict_aliasing, TBAAOnByDefault))
CmdArgs.push_back("-relaxed-aliasing");
if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
options::OPT_fno_struct_path_tbaa))
@@ -2634,7 +2686,8 @@
options::OPT_fno_fast_math))
if (!A->getOption().matches(options::OPT_fno_fast_math))
CmdArgs.push_back("-ffast-math");
- if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math))
+ if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only,
+ options::OPT_fno_fast_math))
if (A->getOption().matches(options::OPT_ffinite_math_only))
CmdArgs.push_back("-ffinite-math-only");
@@ -2731,8 +2784,11 @@
AddARMTargetArgs(Args, CmdArgs, KernelOrKext);
break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
case llvm::Triple::arm64:
- AddARM64TargetArgs(Args, CmdArgs);
+ case llvm::Triple::arm64_be:
+ AddAArch64TargetArgs(Args, CmdArgs);
break;
case llvm::Triple::mips:
@@ -3100,9 +3156,6 @@
CmdArgs.push_back("-fno-gnu-keywords");
}
- if (ShouldDisableCFI(Args, getToolChain()))
- CmdArgs.push_back("-fno-dwarf2-cfi-asm");
-
if (ShouldDisableDwarfDirectory(Args, getToolChain()))
CmdArgs.push_back("-fno-dwarf-directory-asm");
@@ -3308,9 +3361,10 @@
options::OPT_fstack_protector_all,
options::OPT_fstack_protector_strong,
options::OPT_fstack_protector)) {
- if (A->getOption().matches(options::OPT_fstack_protector))
- StackProtectorLevel = LangOptions::SSPOn;
- else if (A->getOption().matches(options::OPT_fstack_protector_strong))
+ if (A->getOption().matches(options::OPT_fstack_protector)) {
+ StackProtectorLevel = std::max<unsigned>(LangOptions::SSPOn,
+ getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
+ } else if (A->getOption().matches(options::OPT_fstack_protector_strong))
StackProtectorLevel = LangOptions::SSPStrong;
else if (A->getOption().matches(options::OPT_fstack_protector_all))
StackProtectorLevel = LangOptions::SSPReq;
@@ -3358,10 +3412,22 @@
options::OPT_munaligned_access)) {
if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-strict-align");
+ if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
+ CmdArgs.push_back("-aarch64-strict-align");
+ else
+ CmdArgs.push_back("-arm-strict-align");
} else {
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-no-strict-align");
+ if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
+ CmdArgs.push_back("-aarch64-no-strict-align");
+ else
+ CmdArgs.push_back("-arm-no-strict-align");
}
}
}
@@ -3375,6 +3441,11 @@
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-arm-no-restrict-it");
}
+ } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
+ TT.getArch() == llvm::Triple::thumb)) {
+ // Windows on ARM expects restricted IT blocks
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-restrict-it");
}
// Forward -f options with positive and negative forms; we translate
@@ -3387,6 +3458,9 @@
A->render(Args, CmdArgs);
}
+ if (Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
+ A->render(Args, CmdArgs);
+
if (Args.hasArg(options::OPT_mkernel)) {
if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
CmdArgs.push_back("-fapple-kext");
@@ -3444,6 +3518,14 @@
CmdArgs.push_back("-fmodules-decluse");
}
+ // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
+ // all #included headers are part of modules.
+ if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
+ options::OPT_fno_modules_strict_decluse,
+ false)) {
+ CmdArgs.push_back("-fmodules-strict-decluse");
+ }
+
// -fmodule-name specifies the module that is currently being built (or
// used for header checking by -fmodule-maps).
if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) {
@@ -3857,16 +3939,19 @@
// Enable vectorization per default according to the optimization level
// selected. For optimization levels that want vectorization we use the alias
// option to simplify the hasFlag logic.
- bool EnableVec = shouldEnableVectorizerAtOLevel(Args);
+ bool EnableVec = shouldEnableVectorizerAtOLevel(Args, false);
OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
options::OPT_fvectorize;
if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
options::OPT_fno_vectorize, EnableVec))
CmdArgs.push_back("-vectorize-loops");
- // -fslp-vectorize is default.
- if (Args.hasFlag(options::OPT_fslp_vectorize,
- options::OPT_fno_slp_vectorize, true))
+ // -fslp-vectorize is enabled based on the optimization level selected.
+ bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true);
+ OptSpecifier SLPVectAliasOption = EnableSLPVec ? options::OPT_O_Group :
+ options::OPT_fslp_vectorize;
+ if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption,
+ options::OPT_fno_slp_vectorize, EnableSLPVec))
CmdArgs.push_back("-vectorize-slp");
// -fno-slp-vectorize-aggressive is default.
@@ -4018,11 +4103,20 @@
// Finally add the compile command to the compilation.
if (Args.hasArg(options::OPT__SLASH_fallback) &&
- Output.getType() == types::TY_Object) {
+ Output.getType() == types::TY_Object &&
+ (InputType == types::TY_C || InputType == types::TY_CXX)) {
tools::visualstudio::Compile CL(getToolChain());
Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args,
LinkingOutput);
- C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
+ // RTTI support in clang-cl is a work in progress. Fall back to MSVC early
+ // if we are using 'clang-cl /fallback /GR'.
+ // FIXME: Remove this when RTTI is finished.
+ if (Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti, false)) {
+ D.Diag(diag::warn_drv_rtti_fallback) << CLCommand->getExecutable();
+ C.addCommand(CLCommand);
+ } else {
+ C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
+ }
} else {
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -4232,12 +4326,6 @@
if (!Args.hasArg(options::OPT_frtti, options::OPT_fno_rtti))
CmdArgs.push_back("-fno-rtti");
- // Let -ffunction-sections imply -fdata-sections.
- if (Arg * A = Args.getLastArg(options::OPT_ffunction_sections,
- options::OPT_fno_function_sections))
- if (A->getOption().matches(options::OPT_ffunction_sections))
- CmdArgs.push_back("-fdata-sections");
-
const Driver &D = getToolChain().getDriver();
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
@@ -4344,6 +4432,13 @@
if (!A->getOption().matches(options::OPT_g0))
CmdArgs.push_back("-g");
+ if (Args.hasArg(options::OPT_gdwarf_2))
+ CmdArgs.push_back("-gdwarf-2");
+ if (Args.hasArg(options::OPT_gdwarf_3))
+ CmdArgs.push_back("-gdwarf-3");
+ if (Args.hasArg(options::OPT_gdwarf_4))
+ CmdArgs.push_back("-gdwarf-4");
+
// Add the -fdebug-compilation-dir flag if needed.
addDebugCompDirArg(Args, CmdArgs);
@@ -4835,68 +4930,61 @@
}
}
- if (Triple.getOS() == llvm::Triple::NetBSD) {
+ switch (Triple.getOS()) {
+ case llvm::Triple::NetBSD:
if (MArch == "armv6")
return "arm1176jzf-s";
+ break;
+ case llvm::Triple::Win32:
+ // FIXME: this is invalid for WindowsCE
+ return "cortex-a9";
+ default:
+ break;
}
- const char *result = llvm::StringSwitch<const char *>(MArch)
- .Cases("armv2", "armv2a","arm2")
- .Case("armv3", "arm6")
- .Case("armv3m", "arm7m")
- .Case("armv4", "strongarm")
- .Case("armv4t", "arm7tdmi")
- .Case("thumbv4t", "arm7tdmi")
- .Cases("armv5", "armv5t", "arm10tdmi")
- .Cases("thumbv5", "thumbv5t", "arm10tdmi")
- .Cases("armv5e", "armv5te", "arm1022e")
- .Cases("thumbv5e", "thumbv5te", "arm1022e")
- .Case("armv5tej", "arm926ej-s")
- .Case("thumbv5tej", "arm926ej-s")
- .Cases("armv6", "armv6k", "arm1136jf-s")
- .Cases("thumbv6", "thumbv6k", "arm1136jf-s")
- .Case("armv6j", "arm1136j-s")
- .Case("thumbv6j", "arm1136j-s")
- .Cases("armv6z", "armv6zk", "arm1176jzf-s")
- .Cases("thumbv6z", "thumbv6zk", "arm1176jzf-s")
- .Case("armv6t2", "arm1156t2-s")
- .Case("thumbv6t2", "arm1156t2-s")
- .Cases("armv6m", "armv6-m", "cortex-m0")
- .Case("thumbv6m", "cortex-m0")
- .Cases("armv7", "armv7a", "armv7-a", "cortex-a8")
- .Cases("armebv7", "armebv7a", "armebv7-a", "cortex-a8")
- .Cases("thumbv7", "thumbv7a", "cortex-a8")
- .Cases("thumbebv7", "thumbebv7a", "cortex-a8")
- .Cases("armv7l", "armv7-l", "cortex-a8")
- .Cases("armebv7l", "armebv7-l", "cortex-a8")
- .Cases("armv7s", "armv7-s", "swift")
- .Cases("armebv7s", "armebv7-s", "swift")
- .Cases("armv7r", "armv7-r", "cortex-r4")
- .Cases("armebv7r", "armebv7-r", "cortex-r4")
- .Case("thumbv7r", "cortex-r4")
- .Case("thumbebv7r", "cortex-r4")
- .Cases("armv7m", "armv7-m", "cortex-m3")
- .Cases("armebv7m", "armebv7-m", "cortex-m3")
- .Case("thumbv7m", "cortex-m3")
- .Case("thumbebv7m", "cortex-m3")
- .Cases("armv7em", "armv7e-m", "cortex-m4")
- .Cases("armebv7em", "armebv7e-m", "cortex-m4")
- .Cases("thumbv7em", "thumbv7e-m", "cortex-m4")
- .Cases("thumbebv7em", "thumbebv7e-m", "cortex-m4")
- .Cases("armv8", "armv8a", "armv8-a", "cortex-a53")
- .Cases("armebv8", "armebv8a", "armebv8-a", "cortex-a53")
- .Cases("thumbv8", "thumbv8a", "cortex-a53")
- .Cases("thumbebv8", "thumbebv8a", "cortex-a53")
- .Case("ep9312", "ep9312")
- .Case("iwmmxt", "iwmmxt")
- .Case("xscale", "xscale")
- // If all else failed, return the most base CPU with thumb interworking
- // supported by LLVM.
- .Default(0);
+ const char *result = nullptr;
+ size_t offset = StringRef::npos;
+ if (MArch.startswith("arm"))
+ offset = 3;
+ if (MArch.startswith("thumb"))
+ offset = 5;
+ if (offset != StringRef::npos && MArch.substr(offset, 2) == "eb")
+ offset += 2;
+ if (offset != StringRef::npos)
+ result = llvm::StringSwitch<const char *>(MArch.substr(offset))
+ .Cases("v2", "v2a", "arm2")
+ .Case("v3", "arm6")
+ .Case("v3m", "arm7m")
+ .Case("v4", "strongarm")
+ .Case("v4t", "arm7tdmi")
+ .Cases("v5", "v5t", "arm10tdmi")
+ .Cases("v5e", "v5te", "arm1022e")
+ .Case("v5tej", "arm926ej-s")
+ .Cases("v6", "v6k", "arm1136jf-s")
+ .Case("v6j", "arm1136j-s")
+ .Cases("v6z", "v6zk", "arm1176jzf-s")
+ .Case("v6t2", "arm1156t2-s")
+ .Cases("v6m", "v6-m", "cortex-m0")
+ .Cases("v7", "v7a", "v7-a", "v7l", "v7-l", "cortex-a8")
+ .Cases("v7s", "v7-s", "swift")
+ .Cases("v7r", "v7-r", "cortex-r4")
+ .Cases("v7m", "v7-m", "cortex-m3")
+ .Cases("v7em", "v7e-m", "cortex-m4")
+ .Cases("v8", "v8a", "v8-a", "cortex-a53")
+ .Default(nullptr);
+ else
+ result = llvm::StringSwitch<const char *>(MArch)
+ .Case("ep9312", "ep9312")
+ .Case("iwmmxt", "iwmmxt")
+ .Case("xscale", "xscale")
+ .Default(nullptr);
if (result)
return result;
+ // If all else failed, return the most base CPU with thumb interworking
+ // supported by LLVM.
+ // FIXME: Should warn once that we're falling back.
switch (Triple.getOS()) {
case llvm::Triple::NetBSD:
switch (Triple.getEnvironment()) {
@@ -6255,7 +6343,7 @@
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
- const char *crt1 = NULL;
+ const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
crt1 = "gcrt1.o";
@@ -6269,7 +6357,7 @@
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
- const char *crtbegin = NULL;
+ const char *crtbegin = nullptr;
if (Args.hasArg(options::OPT_static))
crtbegin = "crtbeginT.o";
else if (Args.hasArg(options::OPT_shared) || IsPIE)
@@ -6565,8 +6653,12 @@
unsigned Major, Minor, Micro;
getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
bool useLibgcc = true;
- if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) {
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) {
switch(getToolChain().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
useLibgcc = false;
@@ -6802,7 +6894,8 @@
else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
ToolChain.getArch() == llvm::Triple::arm64)
return "/lib/ld-linux-aarch64.so.1";
- else if (ToolChain.getArch() == llvm::Triple::aarch64_be)
+ else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
+ ToolChain.getArch() == llvm::Triple::arm64_be)
return "/lib/ld-linux-aarch64_be.so.1";
else if (ToolChain.getArch() == llvm::Triple::arm ||
ToolChain.getArch() == llvm::Triple::thumb) {
@@ -6864,7 +6957,12 @@
ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
const bool IsPIE =
!Args.hasArg(options::OPT_shared) &&
- (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
+ !Args.hasArg(options::OPT_static) &&
+ (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() ||
+ // On Android every code is PIC so every executable is PIE
+ // Cannot use isPIEDefault here since otherwise
+ // PIE only logic will be enabled during compilation
+ isAndroid);
ArgStringList CmdArgs;
@@ -6903,7 +7001,8 @@
else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
ToolChain.getArch() == llvm::Triple::arm64)
CmdArgs.push_back("aarch64linux");
- else if (ToolChain.getArch() == llvm::Triple::aarch64_be)
+ else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
+ ToolChain.getArch() == llvm::Triple::arm64_be)
CmdArgs.push_back("aarch64_be_linux");
else if (ToolChain.getArch() == llvm::Triple::arm
|| ToolChain.getArch() == llvm::Triple::thumb)
@@ -6974,7 +7073,7 @@
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!isAndroid) {
- const char *crt1 = NULL;
+ const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)){
if (Args.hasArg(options::OPT_pg))
crt1 = "gcrt1.o";
@@ -7362,6 +7461,15 @@
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
+static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const StringRef RTName) {
+ SmallString<128> LibSanitizer(getCompilerRTLibDir(TC));
+ llvm::sys::path::append(LibSanitizer,
+ Twine("clang_rt.") + RTName + ".lib");
+ CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
+}
+
void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -7384,6 +7492,10 @@
CmdArgs.push_back("-nologo");
+ if (Args.hasArg(options::OPT_g_Group)) {
+ CmdArgs.push_back("-debug");
+ }
+
bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);
if (DLL) {
@@ -7398,15 +7510,14 @@
if (getToolChain().getSanitizerArgs().needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
- SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir);
- llvm::sys::path::append(LibSanitizer, "lib", "windows");
- if (DLL) {
- llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib");
- } else {
- llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib");
- }
// FIXME: Handle 64-bit.
- CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
+ if (DLL) {
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs,
+ "asan_dll_thunk-i386");
+ } else {
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386");
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386");
+ }
}
Args.AddAllArgValues(CmdArgs, options::OPT_l);
@@ -7509,6 +7620,10 @@
CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
? "/Gy"
: "/Gy-");
+ if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
+ options::OPT_fno_data_sections))
+ CmdArgs.push_back(
+ A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
if (Args.hasArg(options::OPT_fsyntax_only))
CmdArgs.push_back("/Zs");
if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
@@ -7569,8 +7684,9 @@
if (Args.hasArg(options::OPT_v))
CmdArgs.push_back("-v");
- if (Args.hasArg(options::OPT_g_Group))
- CmdArgs.push_back("-g");
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group))
+ if (!A->getOption().matches(options::OPT_g0))
+ CmdArgs.push_back("-g");
if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
false))
diff --git a/lib/Driver/WindowsToolChain.cpp b/lib/Driver/WindowsToolChain.cpp
index a32a7bf..5d4bbb5 100644
--- a/lib/Driver/WindowsToolChain.cpp
+++ b/lib/Driver/WindowsToolChain.cpp
@@ -46,7 +46,7 @@
if (getTriple().isOSBinFormatMachO())
return new tools::darwin::Assemble(*this);
getDriver().Diag(clang::diag::err_no_external_assembler);
- return NULL;
+ return nullptr;
}
bool Windows::IsIntegratedAssemblerDefault() const {
@@ -297,17 +297,12 @@
// Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
if (const char *cl_include_dir = getenv("INCLUDE")) {
SmallVector<StringRef, 8> Dirs;
- StringRef(cl_include_dir).split(Dirs, ";");
- int n = 0;
- for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end();
- I != E; ++I) {
- StringRef d = *I;
- if (d.size() == 0)
- continue;
- ++n;
- addSystemInclude(DriverArgs, CC1Args, d);
- }
- if (n) return;
+ StringRef(cl_include_dir)
+ .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ for (StringRef Dir : Dirs)
+ addSystemInclude(DriverArgs, CC1Args, Dir);
+ if (!Dirs.empty())
+ return;
}
std::string VSDir;
@@ -316,12 +311,19 @@
// When built with access to the proper Windows APIs, try to actually find
// the correct include paths first.
if (getVisualStudioDir(VSDir)) {
- addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include");
- if (getWindowsSDKDir(WindowsSDKDir))
- addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include");
- else
- addSystemInclude(DriverArgs, CC1Args,
- VSDir + "\\VC\\PlatformSDK\\Include");
+ SmallString<128> P;
+ P = VSDir;
+ llvm::sys::path::append(P, "VC\\include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ if (getWindowsSDKDir(WindowsSDKDir)) {
+ P = WindowsSDKDir;
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ } else {
+ P = VSDir;
+ llvm::sys::path::append(P, "VC\\PlatformSDK\\Include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ }
return;
}
diff --git a/lib/Edit/Commit.cpp b/lib/Edit/Commit.cpp
index 706c732..9c08cc2 100644
--- a/lib/Edit/Commit.cpp
+++ b/lib/Edit/Commit.cpp
@@ -38,9 +38,7 @@
Commit::Commit(EditedSource &Editor)
: SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
PPRec(Editor.getPPCondDirectiveRecord()),
- Editor(&Editor),
- ForceCommitInSystemHeader(Editor.getForceCommitInSystemHeader()),
- IsCommitable(true) { }
+ Editor(&Editor), IsCommitable(true) { }
bool Commit::insert(SourceLocation loc, StringRef text,
bool afterToken, bool beforePreviousInsertions) {
@@ -234,7 +232,7 @@
if (!isAtStartOfMacroExpansion(loc, &loc))
return false;
- if (SM.isInSystemHeader(loc) && ForceCommitInSystemHeader)
+ if (SM.isInSystemHeader(loc))
return false;
std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
@@ -265,7 +263,7 @@
if (!isAtEndOfMacroExpansion(loc, &loc))
return false;
- if (SM.isInSystemHeader(loc) && ForceCommitInSystemHeader)
+ if (SM.isInSystemHeader(loc))
return false;
loc = Lexer::getLocForEndOfToken(loc, 0, SourceMgr, LangOpts);
@@ -303,8 +301,8 @@
if (range.getBegin().isMacroID() || range.getEnd().isMacroID())
return false;
- if ((SM.isInSystemHeader(range.getBegin()) ||
- SM.isInSystemHeader(range.getEnd())) && ForceCommitInSystemHeader)
+ if (SM.isInSystemHeader(range.getBegin()) ||
+ SM.isInSystemHeader(range.getEnd()))
return false;
if (PPRec && PPRec->rangeIntersectsConditionalDirective(range.getAsRange()))
diff --git a/lib/Edit/EditedSource.cpp b/lib/Edit/EditedSource.cpp
index 8fa2ee5..6cf6335 100644
--- a/lib/Edit/EditedSource.cpp
+++ b/lib/Edit/EditedSource.cpp
@@ -158,7 +158,7 @@
}
FileOffset TopBegin, TopEnd;
- FileEdit *TopFA = 0;
+ FileEdit *TopFA = nullptr;
if (I == FileEdits.end()) {
FileEditsTy::iterator
diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp
index 879c17a..666844c 100644
--- a/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ b/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -58,7 +58,7 @@
bool edit::rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit) {
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts()))
return false;
if (Msg->getNumArgs() != 1)
@@ -339,7 +339,7 @@
bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit,
const ParentMap *PMap) {
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts()))
return false;
@@ -447,7 +447,7 @@
return false;
if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) {
- IdentifierInfo *Cls = 0;
+ IdentifierInfo *Cls = nullptr;
if (!checkForLiteralCreation(Msg, Cls, NS.getASTContext().getLangOpts()))
return false;
@@ -606,7 +606,7 @@
if (!Msg)
return false;
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts()))
return false;
diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
index d43a774..1bea0e5 100644
--- a/lib/Format/BreakableToken.cpp
+++ b/lib/Format/BreakableToken.cpp
@@ -13,8 +13,6 @@
///
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "format-token-breaker"
-
#include "BreakableToken.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Format/Format.h"
@@ -22,6 +20,8 @@
#include "llvm/Support/Debug.h"
#include <algorithm>
+#define DEBUG_TYPE "format-token-breaker"
+
namespace clang {
namespace format {
@@ -82,11 +82,9 @@
return BreakableToken::Split(StringRef::npos, 0);
}
-static BreakableToken::Split getStringSplit(StringRef Text,
- unsigned UsedColumns,
- unsigned ColumnLimit,
- unsigned TabWidth,
- encoding::Encoding Encoding) {
+static BreakableToken::Split
+getStringSplit(StringRef Text, unsigned UsedColumns, unsigned ColumnLimit,
+ unsigned TabWidth, encoding::Encoding Encoding) {
// FIXME: Reduce unit test case.
if (Text.empty())
return BreakableToken::Split(StringRef::npos, 0);
@@ -350,10 +348,9 @@
Lines[LineIndex].begin() - Lines[LineIndex - 1].end();
// Adjust the start column uniformly across all lines.
- StartOfLineColumn[LineIndex] = std::max<int>(
- 0,
+ StartOfLineColumn[LineIndex] =
encoding::columnWidthWithTabs(Whitespace, 0, Style.TabWidth, Encoding) +
- IndentDelta);
+ IndentDelta;
}
unsigned BreakableBlockComment::getLineCount() const { return Lines.size(); }
@@ -437,7 +434,6 @@
unsigned WhitespaceOffsetInToken = Lines[LineIndex].data() -
Tok.TokenText.data() -
LeadingWhitespace[LineIndex];
- assert(StartOfLineColumn[LineIndex] >= Prefix.size());
Whitespaces.replaceWhitespaceInToken(
Tok, WhitespaceOffsetInToken, LeadingWhitespace[LineIndex], "", Prefix,
InPPDirective, 1, IndentLevel,
@@ -450,7 +446,7 @@
// If we break, we always break at the predefined indent.
if (TailOffset != 0)
return IndentAtLineBreak;
- return StartOfLineColumn[LineIndex];
+ return std::max(0, StartOfLineColumn[LineIndex]);
}
} // namespace format
diff --git a/lib/Format/BreakableToken.h b/lib/Format/BreakableToken.h
index e294a50..72bb1e4 100644
--- a/lib/Format/BreakableToken.h
+++ b/lib/Format/BreakableToken.h
@@ -212,7 +212,7 @@
// StartOfLineColumn[i] is the target column at which Line[i] should be.
// Note that this excludes a leading "* " or "*" in case all lines have
// a "*" prefix.
- SmallVector<unsigned, 16> StartOfLineColumn;
+ SmallVector<int, 16> StartOfLineColumn;
// The column at which the text of a broken line should start.
// Note that an optional decoration would go before that column.
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 5a3dee6..7485e0d 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -12,8 +12,6 @@
///
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "format-formatter"
-
#include "BreakableToken.h"
#include "ContinuationIndenter.h"
#include "WhitespaceManager.h"
@@ -23,13 +21,15 @@
#include "llvm/Support/Debug.h"
#include <string>
+#define DEBUG_TYPE "format-formatter"
+
namespace clang {
namespace format {
// Returns the length of everything up to the first possible line break after
// the ), ], } or > matching \c Tok.
static unsigned getLengthToMatchingParen(const FormatToken &Tok) {
- if (Tok.MatchingParen == NULL)
+ if (!Tok.MatchingParen)
return 0;
FormatToken *End = Tok.MatchingParen;
while (End->Next && !End->Next->CanBreakBefore) {
@@ -78,10 +78,9 @@
/*AvoidBinPacking=*/false,
/*NoLineBreak=*/false));
State.LineContainsContinuedForLoopSection = false;
- State.ParenLevel = 0;
State.StartOfStringLiteral = 0;
- State.StartOfLineLevel = State.ParenLevel;
- State.LowestLevelOnLine = State.ParenLevel;
+ State.StartOfLineLevel = 0;
+ State.LowestLevelOnLine = 0;
State.IgnoreStackForComparison = false;
// The first token has already been indented and thus consumed.
@@ -99,8 +98,8 @@
// The opening "{" of a braced list has to be on the same line as the first
// element if it is nested in another braced init list or function call.
if (!Current.MustBreakBefore && Previous.is(tok::l_brace) &&
- Previous.Type != TT_DictLiteral &&
- Previous.BlockKind == BK_BracedInit && Previous.Previous &&
+ Previous.Type != TT_DictLiteral && Previous.BlockKind == BK_BracedInit &&
+ Previous.Previous &&
Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma))
return false;
// This prevents breaks like:
@@ -142,10 +141,11 @@
return true;
if (((Previous.Type == TT_DictLiteral && Previous.is(tok::l_brace)) ||
Previous.Type == TT_ArrayInitializerLSquare) &&
+ Style.ColumnLimit > 0 &&
getLengthToMatchingParen(Previous) + State.Column > getColumnLimit(State))
return true;
if (Current.Type == TT_CtorInitializerColon &&
- (!Style.AllowShortFunctionsOnASingleLine ||
+ ((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) ||
Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0))
return true;
@@ -173,8 +173,7 @@
if (Previous.Type == TT_BinaryOperator &&
(!IsComparison || LHSIsBinaryExpr) &&
Current.Type != TT_BinaryOperator && // For >>.
- !Current.isTrailingComment() &&
- !Previous.isOneOf(tok::lessless, tok::question) &&
+ !Current.isTrailingComment() && !Previous.is(tok::lessless) &&
Previous.getPrecedence() != prec::Assignment &&
State.Stack.back().BreakBeforeParameter)
return true;
@@ -190,13 +189,13 @@
State.Stack.back().ObjCSelectorNameFound &&
State.Stack.back().BreakBeforeParameter)
return true;
- if (Previous.ClosesTemplateDeclaration && State.ParenLevel == 0 &&
+ if (Previous.ClosesTemplateDeclaration && Current.NestingLevel == 0 &&
!Current.isTrailingComment())
return true;
if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) &&
State.Line->MightBeFunctionDecl &&
- State.Stack.back().BreakBeforeParameter && State.ParenLevel == 0)
+ State.Stack.back().BreakBeforeParameter && Current.NestingLevel == 0)
return true;
if (startsSegmentOfBuilderTypeCall(Current) &&
(State.Stack.back().CallContinuation != 0 ||
@@ -207,8 +206,8 @@
// The following could be precomputed as they do not depend on the state.
// However, as they should take effect only if the UnwrappedLine does not fit
// into the ColumnLimit, they are checked here in the ContinuationIndenter.
- if (Previous.BlockKind == BK_Block && Previous.is(tok::l_brace) &&
- !Current.isOneOf(tok::r_brace, tok::comment))
+ if (Style.ColumnLimit != 0 && Previous.BlockKind == BK_Block &&
+ Previous.is(tok::l_brace) && !Current.isOneOf(tok::r_brace, tok::comment))
return true;
return false;
@@ -221,7 +220,7 @@
assert(!State.Stack.empty());
if ((Current.Type == TT_ImplicitStringLiteral &&
- (Current.Previous->Tok.getIdentifierInfo() == NULL ||
+ (Current.Previous->Tok.getIdentifierInfo() == nullptr ||
Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() ==
tok::pp_not_keyword))) {
// FIXME: Is this correct?
@@ -248,7 +247,7 @@
FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *State.NextToken->Previous;
if (Current.is(tok::equal) &&
- (State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) &&
+ (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
State.Stack.back().VariablePos == 0) {
State.Stack.back().VariablePos = State.Column;
// Move over * and & if they are bound to the variable name.
@@ -290,10 +289,11 @@
State.Stack.back().ContainsUnwrappedBuilder = true;
State.Column += Spaces;
- if (Current.is(tok::l_paren) && Previous.isOneOf(tok::kw_if, tok::kw_for))
+ if (Current.isNot(tok::comment) && Previous.is(tok::l_paren) &&
+ Previous.Previous && Previous.Previous->isOneOf(tok::kw_if, tok::kw_for))
// Treat the condition inside an if as if it was a second function
// parameter, i.e. let nested calls have a continuation indent.
- State.Stack.back().LastSpace = State.Column + 1; // 1 is length of "(".
+ State.Stack.back().LastSpace = State.Column;
else if (Current.isNot(tok::comment) &&
(Previous.is(tok::comma) ||
(Previous.is(tok::colon) && Previous.Type == TT_ObjCMethodExpr)))
@@ -301,7 +301,9 @@
else if ((Previous.Type == TT_BinaryOperator ||
Previous.Type == TT_ConditionalExpr ||
Previous.Type == TT_CtorInitializerColon) &&
- (Previous.getPrecedence() != prec::Assignment ||
+ ((Previous.getPrecedence() != prec::Assignment &&
+ (Previous.isNot(tok::lessless) || Previous.OperatorIndex != 0 ||
+ !Previous.LastOperator)) ||
Current.StartsBinaryExpression))
// Always indent relative to the RHS of the expression unless this is a
// simple assignment without binary expression on the RHS. Also indent
@@ -340,7 +342,7 @@
const FormatToken *NextNonComment = Previous.getNextNonComment();
if (!NextNonComment)
NextNonComment = &Current;
- // The first line break on any ParenLevel causes an extra penalty in order
+ // The first line break on any NestingLevel causes an extra penalty in order
// prefer similar line breaks.
if (!State.Stack.back().ContainsLineBreak)
Penalty += 15;
@@ -383,7 +385,7 @@
// ^(int *i) {
// // ...
// }];
- // Thus, we set LastSpace of the next higher ParenLevel, to which we move
+ // Thus, we set LastSpace of the next higher NestingLevel, to which we move
// when we consume all of the "}"'s FakeRParens at the "{".
if (State.Stack.size() > 1)
State.Stack[State.Stack.size() - 2].LastSpace =
@@ -395,7 +397,7 @@
!State.Stack.back().AvoidBinPacking) ||
Previous.Type == TT_BinaryOperator)
State.Stack.back().BreakBeforeParameter = false;
- if (Previous.Type == TT_TemplateCloser && State.ParenLevel == 0)
+ if (Previous.Type == TT_TemplateCloser && Current.NestingLevel == 0)
State.Stack.back().BreakBeforeParameter = false;
if (NextNonComment->is(tok::question) ||
(PreviousNonComment && PreviousNonComment->is(tok::question)))
@@ -413,20 +415,26 @@
if (!Current.isTrailingComment())
State.Stack.back().LastSpace = State.Column;
- State.StartOfLineLevel = State.ParenLevel;
- State.LowestLevelOnLine = State.ParenLevel;
+ State.StartOfLineLevel = Current.NestingLevel;
+ State.LowestLevelOnLine = Current.NestingLevel;
// Any break on this level means that the parent level has been broken
// and we need to avoid bin packing there.
- for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
- State.Stack[i].BreakBeforeParameter = true;
+ bool JavaScriptFormat = Style.Language == FormatStyle::LK_JavaScript &&
+ Current.is(tok::r_brace) &&
+ State.Stack.size() > 1 &&
+ State.Stack[State.Stack.size() - 2].JSFunctionInlined;
+ if (!JavaScriptFormat) {
+ for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
+ State.Stack[i].BreakBeforeParameter = true;
+ }
}
+
if (PreviousNonComment &&
!PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
PreviousNonComment->Type != TT_TemplateCloser &&
PreviousNonComment->Type != TT_BinaryOperator &&
- Current.Type != TT_BinaryOperator &&
- !PreviousNonComment->opensScope())
+ Current.Type != TT_BinaryOperator && !PreviousNonComment->opensScope())
State.Stack.back().BreakBeforeParameter = true;
// If we break after { or the [ of an array initializer, we should also break
@@ -436,11 +444,13 @@
if (State.Stack.back().AvoidBinPacking) {
// If we are breaking after '(', '{', '<', this is not bin packing
- // unless AllowAllParametersOfDeclarationOnNextLine is false.
+ // unless AllowAllParametersOfDeclarationOnNextLine is false or this is a
+ // dict/object literal.
if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) ||
Previous.Type == TT_BinaryOperator) ||
(!Style.AllowAllParametersOfDeclarationOnNextLine &&
- State.Line->MustBeDeclaration))
+ State.Line->MustBeDeclaration) ||
+ Previous.Type == TT_DictLiteral)
State.Stack.back().BreakBeforeParameter = true;
}
@@ -460,11 +470,13 @@
const FormatToken *NextNonComment = Previous.getNextNonComment();
if (!NextNonComment)
NextNonComment = &Current;
- if (NextNonComment->is(tok::l_brace) &&
- NextNonComment->BlockKind == BK_Block)
- return State.ParenLevel == 0 ? State.FirstIndent
- : State.Stack.back().Indent;
+ if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block)
+ return Current.NestingLevel == 0 ? State.FirstIndent
+ : State.Stack.back().Indent;
if (Current.isOneOf(tok::r_brace, tok::r_square)) {
+ if (State.Stack.size() > 1 &&
+ State.Stack[State.Stack.size() - 2].JSFunctionInlined)
+ return State.FirstIndent;
if (Current.closesBlockTypeList(Style) ||
(Current.MatchingParen &&
Current.MatchingParen->BlockKind == BK_BracedInit))
@@ -472,6 +484,9 @@
else
return State.FirstIndent;
}
+ if (Current.is(tok::identifier) && Current.Next &&
+ Current.Next->Type == TT_DictLiteral)
+ return State.Stack.back().Indent;
if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
return State.StartOfStringLiteral;
if (NextNonComment->is(tok::lessless) &&
@@ -485,7 +500,8 @@
}
}
if (State.Stack.back().QuestionColumn != 0 &&
- (NextNonComment->Type == TT_ConditionalExpr ||
+ ((NextNonComment->is(tok::colon) &&
+ NextNonComment->Type == TT_ConditionalExpr) ||
Previous.Type == TT_ConditionalExpr))
return State.Stack.back().QuestionColumn;
if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0)
@@ -494,8 +510,9 @@
PreviousNonComment->Type == TT_AttributeParen)) ||
((NextNonComment->Type == TT_StartOfName ||
NextNonComment->is(tok::kw_operator)) &&
- State.ParenLevel == 0 && (!Style.IndentFunctionDeclarationAfterType ||
- State.Line->StartsDefinition)))
+ Current.NestingLevel == 0 &&
+ (!Style.IndentFunctionDeclarationAfterType ||
+ State.Line->StartsDefinition)))
return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent);
if (NextNonComment->Type == TT_ObjCSelectorName) {
if (!State.Stack.back().ObjCSelectorNameFound) {
@@ -542,14 +559,20 @@
unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
bool DryRun, bool Newline) {
- const FormatToken &Current = *State.NextToken;
assert(State.Stack.size());
+ const FormatToken &Current = *State.NextToken;
if (Current.Type == TT_InheritanceColon)
State.Stack.back().AvoidBinPacking = true;
- if (Current.is(tok::lessless) && Current.Type != TT_OverloadedOperator &&
- State.Stack.back().FirstLessLess == 0)
- State.Stack.back().FirstLessLess = State.Column;
+ if (Current.is(tok::lessless) && Current.Type != TT_OverloadedOperator) {
+ if (State.Stack.back().FirstLessLess == 0)
+ State.Stack.back().FirstLessLess = State.Column;
+ else
+ State.Stack.back().LastOperatorWrapped = Newline;
+ }
+ if ((Current.Type == TT_BinaryOperator && Current.isNot(tok::lessless)) ||
+ Current.Type == TT_ConditionalExpr)
+ State.Stack.back().LastOperatorWrapped = Newline;
if (Current.Type == TT_ArraySubscriptLSquare &&
State.Stack.back().StartOfArraySubscripts == 0)
State.Stack.back().StartOfArraySubscripts = State.Column;
@@ -560,12 +583,14 @@
State.Stack.back().QuestionColumn = State.Column;
if (!Current.opensScope() && !Current.closesScope())
State.LowestLevelOnLine =
- std::min(State.LowestLevelOnLine, State.ParenLevel);
+ std::min(State.LowestLevelOnLine, Current.NestingLevel);
if (Current.isMemberAccess())
State.Stack.back().StartOfFunctionCall =
- Current.LastInChainOfCalls ? 0 : State.Column + Current.ColumnWidth;
+ Current.LastOperator ? 0 : State.Column + Current.ColumnWidth;
if (Current.Type == TT_ObjCSelectorName)
State.Stack.back().ObjCSelectorNameFound = true;
+ if (Current.Type == TT_LambdaLSquare)
+ ++State.Stack.back().LambdasFound;
if (Current.Type == TT_CtorInitializerColon) {
// Indent 2 from the column, so:
// SomeClass::SomeClass()
@@ -587,180 +612,31 @@
// Insert scopes created by fake parenthesis.
const FormatToken *Previous = Current.getPreviousNonComment();
- // Don't add extra indentation for the first fake parenthesis after
- // 'return', assignements or opening <({[. The indentation for these cases
- // is special cased.
- bool SkipFirstExtraIndent =
- (Previous && (Previous->opensScope() || Previous->is(tok::kw_return) ||
- Previous->getPrecedence() == prec::Assignment ||
- Previous->Type == TT_ObjCMethodExpr));
- for (SmallVectorImpl<prec::Level>::const_reverse_iterator
- I = Current.FakeLParens.rbegin(),
- E = Current.FakeLParens.rend();
- I != E; ++I) {
- ParenState NewParenState = State.Stack.back();
- NewParenState.ContainsLineBreak = false;
- // Indent from 'LastSpace' unless this the fake parentheses encapsulating a
- // builder type call after 'return'. If such a call is line-wrapped, we
- // commonly just want to indent from the start of the line.
- if (!Previous || Previous->isNot(tok::kw_return) || *I > 0)
- NewParenState.Indent =
- std::max(std::max(State.Column, NewParenState.Indent),
- State.Stack.back().LastSpace);
-
- // Don't allow the RHS of an operator to be split over multiple lines unless
- // there is a line-break right after the operator.
- // Exclude relational operators, as there, it is always more desirable to
- // have the LHS 'left' of the RHS.
- // FIXME: Implement this for '<<' and BreakBeforeBinaryOperators.
- if (!Newline && Previous && Previous->Type == TT_BinaryOperator &&
- !Previous->isOneOf(tok::lessless, tok::question, tok::colon) &&
- Previous->getPrecedence() > prec::Assignment &&
- Previous->getPrecedence() != prec::Relational &&
- !Style.BreakBeforeBinaryOperators)
- NewParenState.NoLineBreak = true;
-
- // Do not indent relative to the fake parentheses inserted for "." or "->".
- // This is a special case to make the following to statements consistent:
- // OuterFunction(InnerFunctionCall( // break
- // ParameterToInnerFunction));
- // OuterFunction(SomeObject.InnerFunctionCall( // break
- // ParameterToInnerFunction));
- if (*I > prec::Unknown)
- NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
- NewParenState.StartOfFunctionCall = State.Column;
-
- // Always indent conditional expressions. Never indent expression where
- // the 'operator' is ',', ';' or an assignment (i.e. *I <=
- // prec::Assignment) as those have different indentation rules. Indent
- // other expression, unless the indentation needs to be skipped.
- if (*I == prec::Conditional ||
- (!SkipFirstExtraIndent && *I > prec::Assignment &&
- !Style.BreakBeforeBinaryOperators))
- NewParenState.Indent += Style.ContinuationIndentWidth;
- if ((Previous && !Previous->opensScope()) || *I > prec::Comma)
- NewParenState.BreakBeforeParameter = false;
- State.Stack.push_back(NewParenState);
- SkipFirstExtraIndent = false;
- }
-
- // If we encounter an opening (, [, { or <, we add a level to our stacks to
- // prepare for the following tokens.
- if (Current.opensScope()) {
- unsigned NewIndent;
- unsigned NewIndentLevel = State.Stack.back().IndentLevel;
- bool AvoidBinPacking;
- bool BreakBeforeParameter = false;
- if (Current.is(tok::l_brace) ||
- Current.Type == TT_ArrayInitializerLSquare) {
- if (Current.MatchingParen && Current.BlockKind == BK_Block) {
- // If this is an l_brace starting a nested block, we pretend (wrt. to
- // indentation) that we already consumed the corresponding r_brace.
- // Thus, we remove all ParenStates caused by fake parentheses that end
- // at the r_brace. The net effect of this is that we don't indent
- // relative to the l_brace, if the nested block is the last parameter of
- // a function. For example, this formats:
- //
- // SomeFunction(a, [] {
- // f(); // break
- // });
- //
- // instead of:
- // SomeFunction(a, [] {
- // f(); // break
- // });
- for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) {
- assert(State.Stack.size() > 1);
- if (State.Stack.size() == 1) {
- // Do not pop the last element.
- break;
- }
- State.Stack.pop_back();
- }
- // For some reason, ObjC blocks are indented like continuations.
- NewIndent =
- State.Stack.back().LastSpace + (Current.Type == TT_ObjCBlockLBrace
- ? Style.ContinuationIndentWidth
- : Style.IndentWidth);
- ++NewIndentLevel;
- BreakBeforeParameter = true;
- } else {
- NewIndent = State.Stack.back().LastSpace;
- if (Current.opensBlockTypeList(Style)) {
- NewIndent += Style.IndentWidth;
- NewIndent = std::min(State.Column + 2, NewIndent);
- ++NewIndentLevel;
- } else {
- NewIndent += Style.ContinuationIndentWidth;
- NewIndent = std::min(State.Column + 1, NewIndent);
+ // Add special behavior to support a format commonly used for JavaScript
+ // closures:
+ // SomeFunction(function() {
+ // foo();
+ // bar();
+ // }, a, b, c);
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (Current.isNot(tok::comment) && Previous && Previous->is(tok::l_brace) &&
+ State.Stack.size() > 1) {
+ if (State.Stack[State.Stack.size() - 2].JSFunctionInlined && Newline) {
+ for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
+ State.Stack[i].NoLineBreak = true;
}
}
- const FormatToken *NextNoComment = Current.getNextNonComment();
- AvoidBinPacking = Current.BlockKind == BK_Block ||
- Current.Type == TT_ArrayInitializerLSquare ||
- Current.Type == TT_DictLiteral ||
- (NextNoComment &&
- NextNoComment->Type == TT_DesignatedInitializerPeriod);
- } else {
- NewIndent = Style.ContinuationIndentWidth +
- std::max(State.Stack.back().LastSpace,
- State.Stack.back().StartOfFunctionCall);
- AvoidBinPacking = !Style.BinPackParameters ||
- (Style.ExperimentalAutoDetectBinPacking &&
- (Current.PackingKind == PPK_OnePerLine ||
- (!BinPackInconclusiveFunctions &&
- Current.PackingKind == PPK_Inconclusive)));
- // If this '[' opens an ObjC call, determine whether all parameters fit
- // into one line and put one per line if they don't.
- if (Current.Type == TT_ObjCMethodExpr &&
- getLengthToMatchingParen(Current) + State.Column >
- getColumnLimit(State))
- BreakBeforeParameter = true;
+ State.Stack[State.Stack.size() - 2].JSFunctionInlined = false;
}
-
- bool NoLineBreak = State.Stack.back().NoLineBreak ||
- (Current.Type == TT_TemplateOpener &&
- State.Stack.back().ContainsUnwrappedBuilder);
- State.Stack.push_back(ParenState(NewIndent, NewIndentLevel,
- State.Stack.back().LastSpace,
- AvoidBinPacking, NoLineBreak));
- State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
- ++State.ParenLevel;
+ if (Current.TokenText == "function")
+ State.Stack.back().JSFunctionInlined = !Newline;
}
- // If we encounter a closing ), ], } or >, we can remove a level from our
- // stacks.
- if (State.Stack.size() > 1 &&
- (Current.isOneOf(tok::r_paren, tok::r_square) ||
- (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
- State.NextToken->Type == TT_TemplateCloser)) {
- State.Stack.pop_back();
- --State.ParenLevel;
- }
- if (Current.is(tok::r_square)) {
- // If this ends the array subscript expr, reset the corresponding value.
- const FormatToken *NextNonComment = Current.getNextNonComment();
- if (NextNonComment && NextNonComment->isNot(tok::l_square))
- State.Stack.back().StartOfArraySubscripts = 0;
- }
-
- // Remove scopes created by fake parenthesis.
- if (Current.isNot(tok::r_brace) ||
- (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) {
- // Don't remove FakeRParens attached to r_braces that surround nested blocks
- // as they will have been removed early (see above).
- for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
- unsigned VariablePos = State.Stack.back().VariablePos;
- assert(State.Stack.size() > 1);
- if (State.Stack.size() == 1) {
- // Do not pop the last element.
- break;
- }
- State.Stack.pop_back();
- State.Stack.back().VariablePos = VariablePos;
- }
- }
+ moveStatePastFakeLParens(State, Newline);
+ moveStatePastScopeOpener(State, Newline);
+ moveStatePastScopeCloser(State);
+ moveStatePastFakeRParens(State);
if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
State.StartOfStringLiteral = State.Column;
@@ -790,6 +666,218 @@
return Penalty;
}
+void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
+ bool Newline) {
+ const FormatToken &Current = *State.NextToken;
+ const FormatToken *Previous = Current.getPreviousNonComment();
+
+ // Don't add extra indentation for the first fake parenthesis after
+ // 'return', assignments or opening <({[. The indentation for these cases
+ // is special cased.
+ bool SkipFirstExtraIndent =
+ (Previous && (Previous->opensScope() || Previous->is(tok::kw_return) ||
+ Previous->getPrecedence() == prec::Assignment ||
+ Previous->Type == TT_ObjCMethodExpr));
+ for (SmallVectorImpl<prec::Level>::const_reverse_iterator
+ I = Current.FakeLParens.rbegin(),
+ E = Current.FakeLParens.rend();
+ I != E; ++I) {
+ ParenState NewParenState = State.Stack.back();
+ NewParenState.ContainsLineBreak = false;
+
+ // Indent from 'LastSpace' unless this the fake parentheses encapsulating a
+ // builder type call after 'return'. If such a call is line-wrapped, we
+ // commonly just want to indent from the start of the line.
+ if (!Previous || Previous->isNot(tok::kw_return) || *I > 0)
+ NewParenState.Indent =
+ std::max(std::max(State.Column, NewParenState.Indent),
+ State.Stack.back().LastSpace);
+
+ // Don't allow the RHS of an operator to be split over multiple lines unless
+ // there is a line-break right after the operator.
+ // Exclude relational operators, as there, it is always more desirable to
+ // have the LHS 'left' of the RHS.
+ if (Previous && Previous->getPrecedence() > prec::Assignment &&
+ (Previous->Type == TT_BinaryOperator ||
+ Previous->Type == TT_ConditionalExpr) &&
+ Previous->getPrecedence() != prec::Relational) {
+ bool BreakBeforeOperator = Previous->is(tok::lessless) ||
+ (Previous->Type == TT_BinaryOperator &&
+ Style.BreakBeforeBinaryOperators) ||
+ (Previous->Type == TT_ConditionalExpr &&
+ Style.BreakBeforeTernaryOperators);
+ if ((!Newline && !BreakBeforeOperator) ||
+ (!State.Stack.back().LastOperatorWrapped && BreakBeforeOperator))
+ NewParenState.NoLineBreak = true;
+ }
+
+ // Do not indent relative to the fake parentheses inserted for "." or "->".
+ // This is a special case to make the following to statements consistent:
+ // OuterFunction(InnerFunctionCall( // break
+ // ParameterToInnerFunction));
+ // OuterFunction(SomeObject.InnerFunctionCall( // break
+ // ParameterToInnerFunction));
+ if (*I > prec::Unknown)
+ NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
+ NewParenState.StartOfFunctionCall = State.Column;
+
+ // Always indent conditional expressions. Never indent expression where
+ // the 'operator' is ',', ';' or an assignment (i.e. *I <=
+ // prec::Assignment) as those have different indentation rules. Indent
+ // other expression, unless the indentation needs to be skipped.
+ if (*I == prec::Conditional ||
+ (!SkipFirstExtraIndent && *I > prec::Assignment &&
+ !Style.BreakBeforeBinaryOperators))
+ NewParenState.Indent += Style.ContinuationIndentWidth;
+ if ((Previous && !Previous->opensScope()) || *I > prec::Comma)
+ NewParenState.BreakBeforeParameter = false;
+ State.Stack.push_back(NewParenState);
+ SkipFirstExtraIndent = false;
+ }
+}
+
+void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
+ const FormatToken &Current = *State.NextToken;
+
+ // Remove scopes created by fake parenthesis.
+ if (Current.isNot(tok::r_brace) ||
+ (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) {
+ // Don't remove FakeRParens attached to r_braces that surround nested blocks
+ // as they will have been removed early (see above).
+ for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
+ unsigned VariablePos = State.Stack.back().VariablePos;
+ assert(State.Stack.size() > 1);
+ if (State.Stack.size() == 1) {
+ // Do not pop the last element.
+ break;
+ }
+ State.Stack.pop_back();
+ State.Stack.back().VariablePos = VariablePos;
+ }
+ }
+}
+
+void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
+ bool Newline) {
+ const FormatToken &Current = *State.NextToken;
+ if (!Current.opensScope())
+ return;
+
+ if (Current.MatchingParen && Current.BlockKind == BK_Block) {
+ moveStateToNewBlock(State);
+ return;
+ }
+
+ unsigned NewIndent;
+ unsigned NewIndentLevel = State.Stack.back().IndentLevel;
+ bool AvoidBinPacking;
+ bool BreakBeforeParameter = false;
+ if (Current.is(tok::l_brace) || Current.Type == TT_ArrayInitializerLSquare) {
+ NewIndent = State.Stack.back().LastSpace;
+ if (Current.opensBlockTypeList(Style)) {
+ NewIndent += Style.IndentWidth;
+ NewIndent = std::min(State.Column + 2, NewIndent);
+ ++NewIndentLevel;
+ } else {
+ NewIndent += Style.ContinuationIndentWidth;
+ NewIndent = std::min(State.Column + 1, NewIndent);
+ }
+ const FormatToken *NextNoComment = Current.getNextNonComment();
+ AvoidBinPacking = Current.Type == TT_ArrayInitializerLSquare ||
+ Current.Type == TT_DictLiteral ||
+ Style.Language == FormatStyle::LK_Proto ||
+ !Style.BinPackParameters ||
+ (NextNoComment &&
+ NextNoComment->Type == TT_DesignatedInitializerPeriod);
+ } else {
+ NewIndent = Style.ContinuationIndentWidth +
+ std::max(State.Stack.back().LastSpace,
+ State.Stack.back().StartOfFunctionCall);
+ AvoidBinPacking = !Style.BinPackParameters ||
+ (Style.ExperimentalAutoDetectBinPacking &&
+ (Current.PackingKind == PPK_OnePerLine ||
+ (!BinPackInconclusiveFunctions &&
+ Current.PackingKind == PPK_Inconclusive)));
+ // If this '[' opens an ObjC call, determine whether all parameters fit
+ // into one line and put one per line if they don't.
+ if (Current.Type == TT_ObjCMethodExpr && Style.ColumnLimit != 0 &&
+ getLengthToMatchingParen(Current) + State.Column >
+ getColumnLimit(State))
+ BreakBeforeParameter = true;
+ }
+ bool NoLineBreak = State.Stack.back().NoLineBreak ||
+ (Current.Type == TT_TemplateOpener &&
+ State.Stack.back().ContainsUnwrappedBuilder);
+ State.Stack.push_back(ParenState(NewIndent, NewIndentLevel,
+ State.Stack.back().LastSpace,
+ AvoidBinPacking, NoLineBreak));
+ State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
+}
+
+void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
+ const FormatToken &Current = *State.NextToken;
+ if (!Current.closesScope())
+ return;
+
+ // If we encounter a closing ), ], } or >, we can remove a level from our
+ // stacks.
+ if (State.Stack.size() > 1 &&
+ (Current.isOneOf(tok::r_paren, tok::r_square) ||
+ (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
+ State.NextToken->Type == TT_TemplateCloser)) {
+ State.Stack.pop_back();
+ }
+ if (Current.is(tok::r_square)) {
+ // If this ends the array subscript expr, reset the corresponding value.
+ const FormatToken *NextNonComment = Current.getNextNonComment();
+ if (NextNonComment && NextNonComment->isNot(tok::l_square))
+ State.Stack.back().StartOfArraySubscripts = 0;
+ }
+}
+
+void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
+ // If this is an l_brace starting a nested block, we pretend (wrt. to
+ // indentation) that we already consumed the corresponding r_brace. Thus, we
+ // remove all ParenStates caused by fake parentheses that end at the r_brace.
+ // The net effect of this is that we don't indent relative to the l_brace, if
+ // the nested block is the last parameter of a function. For example, this
+ // formats:
+ //
+ // SomeFunction(a, [] {
+ // f(); // break
+ // });
+ //
+ // instead of:
+ // SomeFunction(a, [] {
+ // f(); // break
+ // });
+ //
+ // If we have already found more than one lambda introducers on this level, we
+ // opt out of this because similarity between the lambdas is more important.
+ if (State.Stack.back().LambdasFound <= 1) {
+ for (unsigned i = 0; i != State.NextToken->MatchingParen->FakeRParens;
+ ++i) {
+ assert(State.Stack.size() > 1);
+ if (State.Stack.size() == 1) {
+ // Do not pop the last element.
+ break;
+ }
+ State.Stack.pop_back();
+ }
+ }
+
+ // For some reason, ObjC blocks are indented like continuations.
+ unsigned NewIndent = State.Stack.back().LastSpace +
+ (State.NextToken->Type == TT_ObjCBlockLBrace
+ ? Style.ContinuationIndentWidth
+ : Style.IndentWidth);
+ State.Stack.push_back(ParenState(
+ NewIndent, /*NewIndentLevel=*/State.Stack.back().IndentLevel + 1,
+ State.Stack.back().LastSpace, /*AvoidBinPacking=*/true,
+ State.Stack.back().NoLineBreak));
+ State.Stack.back().BreakBeforeParameter = true;
+}
+
unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current,
LineState &State) {
// Break before further function parameters on all levels.
@@ -806,8 +894,7 @@
return 0;
}
-static bool getRawStringLiteralPrefixPostfix(StringRef Text,
- StringRef &Prefix,
+static bool getRawStringLiteralPrefixPostfix(StringRef Text, StringRef &Prefix,
StringRef &Postfix) {
if (Text.startswith(Prefix = "R\"") || Text.startswith(Prefix = "uR\"") ||
Text.startswith(Prefix = "UR\"") || Text.startswith(Prefix = "u8R\"") ||
@@ -890,7 +977,7 @@
Current, State.Line->Level, StartColumn, Current.OriginalColumn,
!Current.Previous, State.Line->InPPDirective, Encoding, Style));
} else if (Current.Type == TT_LineComment &&
- (Current.Previous == NULL ||
+ (Current.Previous == nullptr ||
Current.Previous->Type != TT_ImplicitStringLiteral)) {
if (CommentPragmasRegex.match(Current.TokenText.substr(2)))
return 0;
@@ -938,6 +1025,12 @@
break;
}
+ // When breaking before a tab character, it may be moved by a few columns,
+ // but will still be expanded to the next tab stop, so we don't save any
+ // columns.
+ if (NewRemainingTokenColumns == RemainingTokenColumns)
+ break;
+
assert(NewRemainingTokenColumns < RemainingTokenColumns);
if (!DryRun)
Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces);
@@ -979,7 +1072,7 @@
bool ContinuationIndenter::nextIsMultilineString(const LineState &State) {
const FormatToken &Current = *State.NextToken;
- if (!Current.isStringLiteral())
+ if (!Current.isStringLiteral() || Current.Type == TT_ImplicitStringLiteral)
return false;
// We never consider raw string literals "multiline" for the purpose of
// AlwaysBreakBeforeMultilineStrings implementation as they are special-cased
diff --git a/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h
index 9a3c118..4733bda 100644
--- a/lib/Format/ContinuationIndenter.h
+++ b/lib/Format/ContinuationIndenter.h
@@ -73,6 +73,18 @@
/// accordingly.
unsigned moveStateToNextToken(LineState &State, bool DryRun, bool Newline);
+ /// \brief Update 'State' according to the next token's fake left parentheses.
+ void moveStatePastFakeLParens(LineState &State, bool Newline);
+ /// \brief Update 'State' according to the next token's fake r_parens.
+ void moveStatePastFakeRParens(LineState &State);
+
+ /// \brief Update 'State' according to the next token being one of "(<{[".
+ void moveStatePastScopeOpener(LineState &State, bool Newline);
+ /// \brief Update 'State' according to the next token being one of ")>}]".
+ void moveStatePastScopeCloser(LineState &State);
+ /// \brief Update 'State' with the next token opening a nested block.
+ void moveStateToNewBlock(LineState &State);
+
/// \brief If the current token sticks out over the end of the line, break
/// it if possible.
///
@@ -135,11 +147,12 @@
: Indent(Indent), IndentLevel(IndentLevel), LastSpace(LastSpace),
FirstLessLess(0), BreakBeforeClosingBrace(false), QuestionColumn(0),
AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false),
- NoLineBreak(NoLineBreak), ColonPos(0), StartOfFunctionCall(0),
- StartOfArraySubscripts(0), NestedNameSpecifierContinuation(0),
- CallContinuation(0), VariablePos(0), ContainsLineBreak(false),
- ContainsUnwrappedBuilder(0), AlignColons(true),
- ObjCSelectorNameFound(false) {}
+ NoLineBreak(NoLineBreak), LastOperatorWrapped(true), ColonPos(0),
+ StartOfFunctionCall(0), StartOfArraySubscripts(0),
+ NestedNameSpecifierContinuation(0), CallContinuation(0), VariablePos(0),
+ ContainsLineBreak(false), ContainsUnwrappedBuilder(0),
+ AlignColons(true), ObjCSelectorNameFound(false), LambdasFound(0),
+ JSFunctionInlined(false) {}
/// \brief The position to which a specific parenthesis level needs to be
/// indented.
@@ -182,6 +195,10 @@
/// \brief Line breaking in this context would break a formatting rule.
bool NoLineBreak;
+ /// \brief True if the last binary operator on this level was wrapped to the
+ /// next line.
+ bool LastOperatorWrapped;
+
/// \brief The position of the colon in an ObjC method declaration/call.
unsigned ColonPos;
@@ -230,6 +247,16 @@
/// the same token.
bool ObjCSelectorNameFound;
+ /// \brief Counts the number of lambda introducers found on this level.
+ ///
+ /// Not considered for memoization as it will always have the same value at
+ /// the same token.
+ unsigned LambdasFound;
+
+ // \brief The previous JavaScript 'function' keyword is not wrapped to a new
+ // line.
+ bool JSFunctionInlined;
+
bool operator<(const ParenState &Other) const {
if (Indent != Other.Indent)
return Indent < Other.Indent;
@@ -247,6 +274,8 @@
return BreakBeforeParameter;
if (NoLineBreak != Other.NoLineBreak)
return NoLineBreak;
+ if (LastOperatorWrapped != Other.LastOperatorWrapped)
+ return LastOperatorWrapped;
if (ColonPos != Other.ColonPos)
return ColonPos < Other.ColonPos;
if (StartOfFunctionCall != Other.StartOfFunctionCall)
@@ -261,6 +290,8 @@
return ContainsLineBreak < Other.ContainsLineBreak;
if (ContainsUnwrappedBuilder != Other.ContainsUnwrappedBuilder)
return ContainsUnwrappedBuilder < Other.ContainsUnwrappedBuilder;
+ if (JSFunctionInlined != Other.JSFunctionInlined)
+ return JSFunctionInlined < Other.JSFunctionInlined;
return false;
}
};
@@ -278,13 +309,10 @@
/// \brief \c true if this line contains a continued for-loop section.
bool LineContainsContinuedForLoopSection;
- /// \brief The level of nesting inside (), [], <> and {}.
- unsigned ParenLevel;
-
- /// \brief The \c ParenLevel at the start of this line.
+ /// \brief The \c NestingLevel at the start of this line.
unsigned StartOfLineLevel;
- /// \brief The lowest \c ParenLevel on the current line.
+ /// \brief The lowest \c NestingLevel on the current line.
unsigned LowestLevelOnLine;
/// \brief The start column of the string literal, if we're in a string
@@ -327,8 +355,6 @@
if (LineContainsContinuedForLoopSection !=
Other.LineContainsContinuedForLoopSection)
return LineContainsContinuedForLoopSection;
- if (ParenLevel != Other.ParenLevel)
- return ParenLevel < Other.ParenLevel;
if (StartOfLineLevel != Other.StartOfLineLevel)
return StartOfLineLevel < Other.StartOfLineLevel;
if (LowestLevelOnLine != Other.LowestLevelOnLine)
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index cb07cb5..7d0e102 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -13,13 +13,12 @@
///
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "format-formatter"
-
#include "ContinuationIndenter.h"
#include "TokenAnnotator.h"
#include "UnwrappedLineParser.h"
#include "WhitespaceManager.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
@@ -31,6 +30,8 @@
#include <queue>
#include <string>
+#define DEBUG_TYPE "format-formatter"
+
using clang::format::FormatStyle;
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
@@ -65,6 +66,16 @@
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
+ static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::SFS_None);
+ IO.enumCase(Value, "false", FormatStyle::SFS_None);
+ IO.enumCase(Value, "All", FormatStyle::SFS_All);
+ IO.enumCase(Value, "true", FormatStyle::SFS_All);
+ IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
@@ -140,6 +151,8 @@
IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
Style.AllowAllParametersOfDeclarationOnNextLine);
+ IO.mapOptional("AllowShortBlocksOnASingleLine",
+ Style.AllowShortBlocksOnASingleLine);
IO.mapOptional("AllowShortIfStatementsOnASingleLine",
Style.AllowShortIfStatementsOnASingleLine);
IO.mapOptional("AllowShortLoopsOnASingleLine",
@@ -202,7 +215,7 @@
Style.SpaceBeforeAssignmentOperators);
IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
IO.mapOptional("CommentPragmas", Style.CommentPragmas);
- IO.mapOptional("ForEachMacros", Style.ForEachMacros);
+ IO.mapOptional("ForEachMacros", Style.ForEachMacros);
// For backward compatibility.
if (!IO.outputting()) {
@@ -210,6 +223,7 @@
Style.SpaceBeforeParens);
}
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
+ IO.mapOptional("DisableFormat", Style.DisableFormat);
}
};
@@ -230,7 +244,7 @@
if (Seq.size() > 0 && Seq[0].Language == FormatStyle::LK_None) {
Template = Seq[0];
} else {
- Template = *((const FormatStyle*)IO.getContext());
+ Template = *((const FormatStyle *)IO.getContext());
Template.Language = FormatStyle::LK_None;
}
Seq.resize(Index + 1, Template);
@@ -251,7 +265,8 @@
LLVMStyle.AlignEscapedNewlinesLeft = false;
LLVMStyle.AlignTrailingComments = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
- LLVMStyle.AllowShortFunctionsOnASingleLine = true;
+ LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+ LLVMStyle.AllowShortBlocksOnASingleLine = false;
LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
LLVMStyle.AllowShortLoopsOnASingleLine = false;
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
@@ -300,6 +315,8 @@
LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
+ LLVMStyle.DisableFormat = false;
+
return LLVMStyle;
}
@@ -329,10 +346,11 @@
if (Language == FormatStyle::LK_JavaScript) {
GoogleStyle.BreakBeforeTernaryOperators = false;
- GoogleStyle.MaxEmptyLinesToKeep = 2;
+ GoogleStyle.MaxEmptyLinesToKeep = 3;
GoogleStyle.SpacesInContainerLiterals = false;
} else if (Language == FormatStyle::LK_Proto) {
- GoogleStyle.AllowShortFunctionsOnASingleLine = false;
+ GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ GoogleStyle.SpacesInContainerLiterals = false;
}
return GoogleStyle;
@@ -341,6 +359,7 @@
FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
FormatStyle ChromiumStyle = getGoogleStyle(Language);
ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
+ ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
ChromiumStyle.AllowShortLoopsOnASingleLine = false;
ChromiumStyle.BinPackParameters = false;
@@ -393,6 +412,12 @@
return Style;
}
+FormatStyle getNoStyle() {
+ FormatStyle NoStyle = getLLVMStyle();
+ NoStyle.DisableFormat = true;
+ return NoStyle;
+}
+
bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
FormatStyle *Style) {
if (Name.equals_lower("llvm")) {
@@ -407,6 +432,8 @@
*Style = getWebKitStyle();
} else if (Name.equals_lower("gnu")) {
*Style = getGNUStyle();
+ } else if (Name.equals_lower("none")) {
+ *Style = getNoStyle();
} else {
return false;
}
@@ -455,7 +482,7 @@
Styles[i].Language == FormatStyle::LK_None) {
*Style = Styles[i];
Style->Language = Language;
- return llvm::make_error_code(llvm::errc::success);
+ return llvm::error_code::success();
}
}
return llvm::make_error_code(llvm::errc::not_supported);
@@ -483,7 +510,7 @@
void format(unsigned FirstIndent, const AnnotatedLine *Line) {
LineState State =
Indenter->getInitialState(FirstIndent, Line, /*DryRun=*/false);
- while (State.NextToken != NULL) {
+ while (State.NextToken) {
bool Newline =
Indenter->mustBreak(State) ||
(Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
@@ -520,14 +547,19 @@
? 0
: Limit - TheLine->Last->TotalLength;
- if (I + 1 == E || I[1]->Type == LT_Invalid)
+ if (I + 1 == E || I[1]->Type == LT_Invalid || I[1]->First->MustBreakBefore)
return 0;
+ // FIXME: TheLine->Level != 0 might or might not be the right check to do.
+ // If necessary, change to something smarter.
+ bool MergeShortFunctions =
+ Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All ||
+ (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline &&
+ TheLine->Level != 0);
+
if (TheLine->Last->Type == TT_FunctionLBrace &&
TheLine->First != TheLine->Last) {
- return Style.AllowShortFunctionsOnASingleLine
- ? tryMergeSimpleBlock(I, E, Limit)
- : 0;
+ return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
}
if (TheLine->Last->is(tok::l_brace)) {
return Style.BreakBeforeBraces == FormatStyle::BS_Attach
@@ -542,7 +574,7 @@
Limit -= 2;
unsigned MergedLines = 0;
- if (Style.AllowShortFunctionsOnASingleLine) {
+ if (MergeShortFunctions) {
MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
// If we managed to merge the block, count the function header, which is
// on a separate line.
@@ -591,7 +623,7 @@
return 0;
if ((Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU) &&
- I[1]->First->is(tok::l_brace))
+ (I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine))
return 0;
if (I[1]->InPPDirective != (*I)->InPPDirective ||
(I[1]->InPPDirective && I[1]->First->HasUnescapedNewline))
@@ -617,26 +649,45 @@
tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
SmallVectorImpl<AnnotatedLine *>::const_iterator E,
unsigned Limit) {
- // First, check that the current line allows merging. This is the case if
- // we're not in a control flow statement and the last token is an opening
- // brace.
AnnotatedLine &Line = **I;
- if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,
- tok::kw_else, tok::kw_try, tok::kw_catch,
- tok::kw_for,
- // This gets rid of all ObjC @ keywords and methods.
- tok::at, tok::minus, tok::plus))
+
+ // Don't merge ObjC @ keywords and methods.
+ if (Line.First->isOneOf(tok::at, tok::minus, tok::plus))
return 0;
+ // Check that the current line allows merging. This depends on whether we
+ // are in a control flow statements as well as several style flags.
+ if (Line.First->isOneOf(tok::kw_else, tok::kw_case))
+ return 0;
+ if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
+ tok::kw_catch, tok::kw_for, tok::r_brace)) {
+ if (!Style.AllowShortBlocksOnASingleLine)
+ return 0;
+ if (!Style.AllowShortIfStatementsOnASingleLine &&
+ Line.First->is(tok::kw_if))
+ return 0;
+ if (!Style.AllowShortLoopsOnASingleLine &&
+ Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for))
+ return 0;
+ // FIXME: Consider an option to allow short exception handling clauses on
+ // a single line.
+ if (Line.First->isOneOf(tok::kw_try, tok::kw_catch))
+ return 0;
+ }
+
FormatToken *Tok = I[1]->First;
if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
- (Tok->getNextNonComment() == NULL ||
+ (Tok->getNextNonComment() == nullptr ||
Tok->getNextNonComment()->is(tok::semi))) {
// We merge empty blocks even if the line exceeds the column limit.
Tok->SpacesRequiredBefore = 0;
Tok->CanBreakBefore = true;
return 1;
} else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {
+ // We don't merge short records.
+ if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct))
+ return 0;
+
// Check that we still have three lines and they fit into the limit.
if (I + 2 == E || I[2]->Type == LT_Invalid)
return 0;
@@ -647,18 +698,17 @@
// Second, check that the next line does not contain any braces - if it
// does, readability declines when putting it into a single line.
- if (I[1]->Last->Type == TT_LineComment || Tok->MustBreakBefore)
+ if (I[1]->Last->Type == TT_LineComment)
return 0;
do {
- if (Tok->isOneOf(tok::l_brace, tok::r_brace))
+ if (Tok->is(tok::l_brace) && Tok->BlockKind != BK_BracedInit)
return 0;
Tok = Tok->Next;
- } while (Tok != NULL);
+ } while (Tok);
- // Last, check that the third line contains a single closing brace.
+ // Last, check that the third line starts with a closing brace.
Tok = I[2]->First;
- if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||
- Tok->MustBreakBefore)
+ if (Tok->isNot(tok::r_brace))
return 0;
return 2;
@@ -681,6 +731,8 @@
bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
unsigned Limit) {
+ if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)
+ return false;
return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
}
@@ -705,12 +757,19 @@
unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
int AdditionalIndent = 0, bool FixBadIndentation = false) {
+ // Try to look up already computed penalty in DryRun-mode.
+ std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(
+ &Lines, AdditionalIndent);
+ auto CacheIt = PenaltyCache.find(CacheKey);
+ if (DryRun && CacheIt != PenaltyCache.end())
+ return CacheIt->second;
+
assert(!Lines.empty());
unsigned Penalty = 0;
std::vector<int> IndentForLevel;
for (unsigned i = 0, e = Lines[0]->Level; i != e; ++i)
IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
- const AnnotatedLine *PreviousLine = NULL;
+ const AnnotatedLine *PreviousLine = nullptr;
for (SmallVectorImpl<AnnotatedLine *>::const_iterator I = Lines.begin(),
E = Lines.end();
I != E; ++I) {
@@ -779,8 +838,10 @@
if (TheLine.Last->TotalLength + Indent <= ColumnLimit) {
LineState State = Indenter->getInitialState(Indent, &TheLine, DryRun);
- while (State.NextToken != NULL)
+ while (State.NextToken) {
+ formatChildren(State, /*Newline=*/false, /*DryRun=*/false, Penalty);
Indenter->addTokenToState(State, /*Newline=*/false, DryRun);
+ }
} else if (Style.ColumnLimit == 0) {
// FIXME: Implement nested blocks for ColumnLimit = 0.
NoColumnLimitFormatter Formatter(Indenter);
@@ -797,7 +858,7 @@
} else {
// Format the first token if necessary, and notify the WhitespaceManager
// about the unchanged whitespace.
- for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {
+ for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
if (Tok == TheLine.First &&
(Tok->NewlinesBefore > 0 || Tok->IsFirst)) {
unsigned LevelIndent = Tok->OriginalColumn;
@@ -822,12 +883,13 @@
}
}
if (!DryRun) {
- for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {
+ for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
Tok->Finalized = true;
}
}
PreviousLine = *I;
}
+ PenaltyCache[CacheKey] = Penalty;
return Penalty;
}
@@ -897,6 +959,8 @@
Newlines = std::min(Newlines, 1u);
if (Newlines == 0 && !RootToken.IsFirst)
Newlines = 1;
+ if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)
+ Newlines = 0;
// Remove empty lines after "{".
if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
@@ -951,6 +1015,12 @@
return Style.ColumnLimit - (InPPDirective ? 2 : 0);
}
+ struct CompareLineStatePointers {
+ bool operator()(LineState *obj1, LineState *obj2) const {
+ return *obj1 < *obj2;
+ }
+ };
+
/// \brief Analyze the entire solution space starting from \p InitialState.
///
/// This implements a variant of Dijkstra's algorithm on the graph that spans
@@ -960,7 +1030,7 @@
///
/// If \p DryRun is \c false, directly applies the changes.
unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun = false) {
- std::set<LineState> Seen;
+ std::set<LineState *, CompareLineStatePointers> Seen;
// Increasing count of \c StateNode items we have created. This is used to
// create a deterministic order independent of the container.
@@ -969,7 +1039,7 @@
// Insert start element into queue.
StateNode *Node =
- new (Allocator.Allocate()) StateNode(InitialState, false, NULL);
+ new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
++Count;
@@ -979,7 +1049,7 @@
while (!Queue.empty()) {
Penalty = Queue.top().first.first;
StateNode *Node = Queue.top().second;
- if (Node->State.NextToken == NULL) {
+ if (!Node->State.NextToken) {
DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
break;
}
@@ -990,7 +1060,7 @@
if (Count > 10000)
Node->State.IgnoreStackForComparison = true;
- if (!Seen.insert(Node->State).second)
+ if (!Seen.insert(&Node->State).second)
// State already examined with lower penalty.
continue;
@@ -1094,8 +1164,13 @@
return true;
if (NewLine) {
- int AdditionalIndent = State.Stack.back().Indent -
- Previous.Children[0]->Level * Style.IndentWidth;
+ int AdditionalIndent = 0;
+ if (State.Stack.size() < 2 ||
+ !State.Stack[State.Stack.size() - 2].JSFunctionInlined) {
+ AdditionalIndent = State.Stack.back().Indent -
+ Previous.Children[0]->Level * Style.IndentWidth;
+ }
+
Penalty += format(Previous.Children, DryRun, AdditionalIndent,
/*FixBadIndentation=*/true);
return true;
@@ -1105,10 +1180,21 @@
if (Previous.Children.size() > 1)
return false;
+ // Cannot merge into one line if this line ends on a comment.
+ if (Previous.is(tok::comment))
+ return false;
+
// We can't put the closing "}" on a line with a trailing comment.
if (Previous.Children[0]->Last->isTrailingComment())
return false;
+ // If the child line exceeds the column limit, we wouldn't want to merge it.
+ // We add +2 for the trailing " }".
+ if (Style.ColumnLimit > 0 &&
+ Previous.Children[0]->Last->TotalLength + State.Column + 2 >
+ Style.ColumnLimit)
+ return false;
+
if (!DryRun) {
Whitespaces->replaceWhitespace(
*Previous.Children[0]->First,
@@ -1127,27 +1213,37 @@
LineJoiner Joiner;
llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
+
+ // Cache to store the penalty of formatting a vector of AnnotatedLines
+ // starting from a specific additional offset. Improves performance if there
+ // are many nested blocks.
+ std::map<std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned>,
+ unsigned> PenaltyCache;
};
class FormatTokenLexer {
public:
FormatTokenLexer(Lexer &Lex, SourceManager &SourceMgr, FormatStyle &Style,
encoding::Encoding Encoding)
- : FormatTok(NULL), IsFirstToken(true), GreaterStashed(false), Column(0),
- TrailingWhitespace(0), Lex(Lex), SourceMgr(SourceMgr), Style(Style),
- IdentTable(getFormattingLangOpts()), Encoding(Encoding) {
+ : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
+ Column(0), TrailingWhitespace(0), Lex(Lex), SourceMgr(SourceMgr),
+ Style(Style), IdentTable(getFormattingLangOpts()), Encoding(Encoding),
+ FirstInLineIndex(0) {
Lex.SetKeepWhitespaceMode(true);
- for (const std::string& ForEachMacro : Style.ForEachMacros)
+ for (const std::string &ForEachMacro : Style.ForEachMacros)
ForEachMacros.push_back(&IdentTable.get(ForEachMacro));
std::sort(ForEachMacros.begin(), ForEachMacros.end());
}
ArrayRef<FormatToken *> lex() {
assert(Tokens.empty());
+ assert(FirstInLineIndex == 0);
do {
Tokens.push_back(getNextToken());
tryMergePreviousTokens();
+ if (Tokens.back()->NewlinesBefore > 0)
+ FirstInLineIndex = Tokens.size() - 1;
} while (Tokens.back()->Tok.isNot(tok::eof));
return Tokens;
}
@@ -1158,12 +1254,20 @@
void tryMergePreviousTokens() {
if (tryMerge_TMacro())
return;
+ if (tryMergeConflictMarkers())
+ return;
if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (tryMergeEscapeSequence())
+ return;
+ if (tryMergeJSRegexLiteral())
+ return;
+
static tok::TokenKind JSIdentity[] = { tok::equalequal, tok::equal };
static tok::TokenKind JSNotIdentity[] = { tok::exclaimequal, tok::equal };
static tok::TokenKind JSShiftEqual[] = { tok::greater, tok::greater,
tok::greaterequal };
+ static tok::TokenKind JSRightArrow[] = { tok::equal, tok::greater };
// FIXME: We probably need to change token type to mimic operator with the
// correct priority.
if (tryMergeTokens(JSIdentity))
@@ -1172,6 +1276,8 @@
return;
if (tryMergeTokens(JSShiftEqual))
return;
+ if (tryMergeTokens(JSRightArrow))
+ return;
}
}
@@ -1197,6 +1303,56 @@
return true;
}
+ // Tries to merge an escape sequence, i.e. a "\\" and the following
+ // character. Use e.g. inside JavaScript regex literals.
+ bool tryMergeEscapeSequence() {
+ if (Tokens.size() < 2)
+ return false;
+ FormatToken *Previous = Tokens[Tokens.size() - 2];
+ if (Previous->isNot(tok::unknown) || Previous->TokenText != "\\" ||
+ Tokens.back()->NewlinesBefore != 0)
+ return false;
+ Previous->ColumnWidth += Tokens.back()->ColumnWidth;
+ StringRef Text = Previous->TokenText;
+ Previous->TokenText =
+ StringRef(Text.data(), Text.size() + Tokens.back()->TokenText.size());
+ Tokens.resize(Tokens.size() - 1);
+ return true;
+ }
+
+ // Try to determine whether the current token ends a JavaScript regex literal.
+ // We heuristically assume that this is a regex literal if we find two
+ // unescaped slashes on a line and the token before the first slash is one of
+ // "(;,{}![:?", a binary operator or 'return', as those cannot be followed by
+ // a division.
+ bool tryMergeJSRegexLiteral() {
+ if (Tokens.size() < 2 || Tokens.back()->isNot(tok::slash) ||
+ (Tokens[Tokens.size() - 2]->is(tok::unknown) &&
+ Tokens[Tokens.size() - 2]->TokenText == "\\"))
+ return false;
+ unsigned TokenCount = 0;
+ unsigned LastColumn = Tokens.back()->OriginalColumn;
+ for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) {
+ ++TokenCount;
+ if (I[0]->is(tok::slash) && I + 1 != E &&
+ (I[1]->isOneOf(tok::l_paren, tok::semi, tok::l_brace, tok::r_brace,
+ tok::exclaim, tok::l_square, tok::colon, tok::comma,
+ tok::question, tok::kw_return) ||
+ I[1]->isBinaryOperator())) {
+ Tokens.resize(Tokens.size() - TokenCount);
+ Tokens.back()->Tok.setKind(tok::unknown);
+ Tokens.back()->Type = TT_RegexLiteral;
+ Tokens.back()->ColumnWidth += LastColumn - I[0]->OriginalColumn;
+ return true;
+ }
+
+ // There can't be a newline inside a regex literal.
+ if (I[0]->NewlinesBefore > 0)
+ return false;
+ }
+ return false;
+ }
+
bool tryMerge_TMacro() {
if (Tokens.size() < 4)
return false;
@@ -1232,6 +1388,68 @@
return true;
}
+ bool tryMergeConflictMarkers() {
+ if (Tokens.back()->NewlinesBefore == 0 && Tokens.back()->isNot(tok::eof))
+ return false;
+
+ // Conflict lines look like:
+ // <marker> <text from the vcs>
+ // For example:
+ // >>>>>>> /file/in/file/system at revision 1234
+ //
+ // We merge all tokens in a line that starts with a conflict marker
+ // into a single token with a special token type that the unwrapped line
+ // parser will use to correctly rebuild the underlying code.
+
+ FileID ID;
+ // Get the position of the first token in the line.
+ unsigned FirstInLineOffset;
+ std::tie(ID, FirstInLineOffset) = SourceMgr.getDecomposedLoc(
+ Tokens[FirstInLineIndex]->getStartOfNonWhitespace());
+ StringRef Buffer = SourceMgr.getBuffer(ID)->getBuffer();
+ // Calculate the offset of the start of the current line.
+ auto LineOffset = Buffer.rfind('\n', FirstInLineOffset);
+ if (LineOffset == StringRef::npos) {
+ LineOffset = 0;
+ } else {
+ ++LineOffset;
+ }
+
+ auto FirstSpace = Buffer.find_first_of(" \n", LineOffset);
+ StringRef LineStart;
+ if (FirstSpace == StringRef::npos) {
+ LineStart = Buffer.substr(LineOffset);
+ } else {
+ LineStart = Buffer.substr(LineOffset, FirstSpace - LineOffset);
+ }
+
+ TokenType Type = TT_Unknown;
+ if (LineStart == "<<<<<<<" || LineStart == ">>>>") {
+ Type = TT_ConflictStart;
+ } else if (LineStart == "|||||||" || LineStart == "=======" ||
+ LineStart == "====") {
+ Type = TT_ConflictAlternative;
+ } else if (LineStart == ">>>>>>>" || LineStart == "<<<<") {
+ Type = TT_ConflictEnd;
+ }
+
+ if (Type != TT_Unknown) {
+ FormatToken *Next = Tokens.back();
+
+ Tokens.resize(FirstInLineIndex + 1);
+ // We do not need to build a complete token here, as we will skip it
+ // during parsing anyway (as we must not touch whitespace around conflict
+ // markers).
+ Tokens.back()->Type = Type;
+ Tokens.back()->Tok.setKind(tok::kw___unknown_anytype);
+
+ Tokens.push_back(Next);
+ return true;
+ }
+
+ return false;
+ }
+
FormatToken *getNextToken() {
if (GreaterStashed) {
// Create a synthesized second '>' token.
@@ -1309,7 +1527,7 @@
// FIXME: Add a more explicit test.
while (FormatTok->TokenText.size() > 1 && FormatTok->TokenText[0] == '\\' &&
FormatTok->TokenText[1] == '\n') {
- // FIXME: ++FormatTok->NewlinesBefore is missing...
+ ++FormatTok->NewlinesBefore;
WhitespaceLength += 2;
Column = 0;
FormatTok->TokenText = FormatTok->TokenText.substr(2);
@@ -1379,8 +1597,10 @@
IdentifierTable IdentTable;
encoding::Encoding Encoding;
llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
+ // Index (in 'Tokens') of the last token that starts a new line.
+ unsigned FirstInLineIndex;
SmallVector<FormatToken *, 16> Tokens;
- SmallVector<IdentifierInfo*, 8> ForEachMacros;
+ SmallVector<IdentifierInfo *, 8> ForEachMacros;
void readRawToken(FormatToken &Tok) {
Lex.LexFromRawLexer(Tok.Tok);
@@ -1489,7 +1709,7 @@
bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *>::iterator I,
SmallVectorImpl<AnnotatedLine *>::iterator E) {
bool SomeLineAffected = false;
- const AnnotatedLine *PreviousLine = NULL;
+ const AnnotatedLine *PreviousLine = nullptr;
while (I != E) {
AnnotatedLine *Line = *I;
Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);
@@ -1559,11 +1779,10 @@
bool LineMoved = PreviousLine && PreviousLine->Affected &&
Line->First->NewlinesBefore == 0;
- bool IsContinuedComment = Line->First->is(tok::comment) &&
- Line->First->Next == NULL &&
- Line->First->NewlinesBefore < 2 && PreviousLine &&
- PreviousLine->Affected &&
- PreviousLine->Last->is(tok::comment);
+ bool IsContinuedComment =
+ Line->First->is(tok::comment) && Line->First->Next == nullptr &&
+ Line->First->NewlinesBefore < 2 && PreviousLine &&
+ PreviousLine->Affected && PreviousLine->Last->is(tok::comment);
if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
IsContinuedComment) {
@@ -1701,6 +1920,11 @@
tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
SourceManager &SourceMgr,
std::vector<CharSourceRange> Ranges) {
+ if (Style.DisableFormat) {
+ tooling::Replacements EmptyResult;
+ return EmptyResult;
+ }
+
Formatter formatter(Style, Lex, SourceMgr, Ranges);
return formatter.format();
}
@@ -1735,7 +1959,9 @@
LangOptions LangOpts;
LangOpts.CPlusPlus = 1;
LangOpts.CPlusPlus11 = Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
+ LangOpts.CPlusPlus1y = Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
LangOpts.LineComment = 1;
+ LangOpts.CXXOperatorNames = 1;
LangOpts.Bool = 1;
LangOpts.ObjC1 = 1;
LangOpts.ObjC2 = 1;
diff --git a/lib/Format/FormatToken.cpp b/lib/Format/FormatToken.cpp
index c147dbb..c91d25f 100644
--- a/lib/Format/FormatToken.cpp
+++ b/lib/Format/FormatToken.cpp
@@ -64,16 +64,15 @@
// Ensure that we start on the opening brace.
const FormatToken *LBrace = State.NextToken->Previous->Previous;
- if (LBrace->isNot(tok::l_brace) ||
- LBrace->BlockKind == BK_Block ||
+ if (LBrace->isNot(tok::l_brace) || LBrace->BlockKind == BK_Block ||
LBrace->Type == TT_DictLiteral ||
LBrace->Next->Type == TT_DesignatedInitializerPeriod)
return 0;
// Calculate the number of code points we have to format this list. As the
// first token is already placed, we have to subtract it.
- unsigned RemainingCodePoints = Style.ColumnLimit - State.Column +
- State.NextToken->Previous->ColumnWidth;
+ unsigned RemainingCodePoints =
+ Style.ColumnLimit - State.Column + State.NextToken->Previous->ColumnWidth;
// Find the best ColumnFormat, i.e. the best number of columns to use.
const ColumnFormat *Format = getColumnFormat(RemainingCodePoints);
@@ -132,6 +131,11 @@
if (!Token->MatchingParen || Token->isNot(tok::l_brace))
return;
+ // In C++11 braced list style, we should not format in columns unless we allow
+ // bin-packing of function parameters.
+ if (Style.Cpp11BracedListStyle && !Style.BinPackParameters)
+ return;
+
FormatToken *ItemBegin = Token->Next;
SmallVector<bool, 8> MustBreakBeforeItem;
@@ -147,7 +151,7 @@
MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore);
if (ItemBegin->is(tok::l_brace))
HasNestedBracedList = true;
- const FormatToken *ItemEnd = NULL;
+ const FormatToken *ItemEnd = nullptr;
if (i == Commas.size()) {
ItemEnd = Token->MatchingParen;
const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment();
@@ -181,8 +185,7 @@
// If this doesn't have a nested list, we require at least 6 elements in order
// create a column layout. If it has a nested list, column layout ensures one
// list element per line.
- if (HasNestedBracedList || Commas.size() < 5 ||
- Token->NestingLevel != 0)
+ if (HasNestedBracedList || Commas.size() < 5 || Token->NestingLevel != 0)
return;
// We can never place more than ColumnLimit / 3 items in a row (because of the
@@ -204,8 +207,7 @@
HasRowWithSufficientColumns = true;
unsigned length =
(Column == Columns - 1) ? EndOfLineItemLength[i] : ItemLengths[i];
- Format.ColumnSizes[Column] =
- std::max(Format.ColumnSizes[Column], length);
+ Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], length);
++Column;
}
// If all rows are terminated early (e.g. by trailing comments), we don't
@@ -227,7 +229,7 @@
const CommaSeparatedList::ColumnFormat *
CommaSeparatedList::getColumnFormat(unsigned RemainingCharacters) const {
- const ColumnFormat *BestFormat = NULL;
+ const ColumnFormat *BestFormat = nullptr;
for (SmallVector<ColumnFormat, 4>::const_reverse_iterator
I = Formats.rbegin(),
E = Formats.rend();
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index a5aaa6f..f2bba32 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -33,19 +33,22 @@
TT_BlockComment,
TT_CastRParen,
TT_ConditionalExpr,
+ TT_ConflictAlternative,
+ TT_ConflictEnd,
+ TT_ConflictStart,
TT_CtorInitializerColon,
TT_CtorInitializerComma,
TT_DesignatedInitializerPeriod,
TT_DictLiteral,
- TT_ImplicitStringLiteral,
- TT_InlineASMColon,
- TT_InheritanceColon,
TT_FunctionLBrace,
TT_FunctionTypeLParen,
+ TT_ImplicitStringLiteral,
+ TT_InheritanceColon,
+ TT_InlineASMColon,
TT_LambdaLSquare,
TT_LineComment,
- TT_ObjCBlockLParen,
TT_ObjCBlockLBrace,
+ TT_ObjCBlockLParen,
TT_ObjCDecl,
TT_ObjCForIn,
TT_ObjCMethodExpr,
@@ -57,6 +60,7 @@
TT_PointerOrReference,
TT_PureVirtualSpecifier,
TT_RangeBasedForLoopColon,
+ TT_RegexLiteral,
TT_StartOfName,
TT_TemplateCloser,
TT_TemplateOpener,
@@ -103,8 +107,9 @@
UnbreakableTailLength(0), BindingStrength(0), NestingLevel(0),
SplitPenalty(0), LongestObjCSelectorName(0), FakeRParens(0),
StartsBinaryExpression(false), EndsBinaryExpression(false),
- LastInChainOfCalls(false), PartOfMultiVariableDeclStmt(false),
- IsForEachMacro(false), MatchingParen(NULL), Previous(NULL), Next(NULL),
+ OperatorIndex(0), LastOperator(false),
+ PartOfMultiVariableDeclStmt(false), IsForEachMacro(false),
+ MatchingParen(nullptr), Previous(nullptr), Next(nullptr),
Decision(FD_Unformatted), Finalized(false) {}
/// \brief The \c Token.
@@ -239,8 +244,13 @@
/// \brief \c true if this token ends a binary expression.
bool EndsBinaryExpression;
- /// \brief Is this the last "." or "->" in a builder-type call?
- bool LastInChainOfCalls;
+ /// \brief Is this is an operator (or "."/"->") in a sequence of operators
+ /// with the same precedence, contains the 0-based operator index.
+ unsigned OperatorIndex;
+
+ /// \brief Is this the last operator (or "."/"->") in a sequence of operators
+ /// with the same precedence?
+ bool LastOperator;
/// \brief Is this token part of a \c DeclStmt defining multiple variables?
///
@@ -344,7 +354,7 @@
/// \brief Returns the previous token ignoring comments.
FormatToken *getPreviousNonComment() const {
FormatToken *Tok = Previous;
- while (Tok != NULL && Tok->is(tok::comment))
+ while (Tok && Tok->is(tok::comment))
Tok = Tok->Previous;
return Tok;
}
@@ -352,7 +362,7 @@
/// \brief Returns the next token ignoring comments.
const FormatToken *getNextNonComment() const {
const FormatToken *Tok = Next;
- while (Tok != NULL && Tok->is(tok::comment))
+ while (Tok && Tok->is(tok::comment))
Tok = Tok->Next;
return Tok;
}
@@ -445,7 +455,9 @@
bool DryRun) override;
/// \brief Adds \p Token as the next comma to the \c CommaSeparated list.
- void CommaFound(const FormatToken *Token) override { Commas.push_back(Token);}
+ void CommaFound(const FormatToken *Token) override {
+ Commas.push_back(Token);
+ }
private:
/// \brief A struct that holds information on how to format a given list with
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 0034235..3fea52b 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -17,6 +17,8 @@
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Debug.h"
+#define DEBUG_TYPE "format-token-annotator"
+
namespace clang {
namespace format {
@@ -39,7 +41,7 @@
private:
bool parseAngle() {
- if (CurrentToken == NULL)
+ if (!CurrentToken)
return false;
ScopedContextCreator ContextCreator(*this, tok::less, 10);
FormatToken *Left = CurrentToken->Previous;
@@ -47,9 +49,9 @@
// If there's a template keyword before the opening angle bracket, this is a
// template parameter, not an argument.
Contexts.back().InTemplateArgument =
- Left->Previous != NULL && Left->Previous->Tok.isNot(tok::kw_template);
+ Left->Previous && Left->Previous->Tok.isNot(tok::kw_template);
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
if (CurrentToken->is(tok::greater)) {
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
@@ -83,7 +85,7 @@
}
bool parseParens(bool LookForDecls = false) {
- if (CurrentToken == NULL)
+ if (!CurrentToken)
return false;
ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);
@@ -110,6 +112,11 @@
Left->Previous->Type == TT_BinaryOperator)) {
// static_assert, if and while usually contain expressions.
Contexts.back().IsExpression = true;
+ } else if (Line.InPPDirective &&
+ (!Left->Previous ||
+ (Left->Previous->isNot(tok::identifier) &&
+ Left->Previous->Type != TT_OverloadedOperator))) {
+ Contexts.back().IsExpression = true;
} else if (Left->Previous && Left->Previous->is(tok::r_square) &&
Left->Previous->MatchingParen &&
Left->Previous->MatchingParen->Type == TT_LambdaLSquare) {
@@ -134,7 +141,7 @@
bool MightBeFunctionType = CurrentToken->is(tok::star);
bool HasMultipleLines = false;
bool HasMultipleParametersOnALine = false;
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
// LookForDecls is set when "if (" has been seen. Check for
// 'identifier' '*' 'identifier' followed by not '=' -- this
// '*' has to be a binary operator but determineStarAmpUsage() will
@@ -168,7 +175,7 @@
if (StartsObjCMethodExpr) {
CurrentToken->Type = TT_ObjCMethodExpr;
- if (Contexts.back().FirstObjCSelectorName != NULL) {
+ if (Contexts.back().FirstObjCSelectorName) {
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
}
@@ -218,6 +225,7 @@
FormatToken *Parent = Left->getPreviousNonComment();
bool StartsObjCMethodExpr =
Contexts.back().CanBeExpression && Left->Type != TT_LambdaLSquare &&
+ CurrentToken->isNot(tok::l_brace) &&
(!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
tok::kw_return, tok::kw_throw) ||
Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn ||
@@ -236,7 +244,7 @@
Left->Type = TT_ArraySubscriptLSquare;
}
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
if (CurrentToken->is(tok::r_square)) {
if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
Left->Type == TT_ObjCMethodExpr) {
@@ -245,17 +253,17 @@
StartsObjCMethodExpr = false;
Left->Type = TT_Unknown;
}
- if (StartsObjCMethodExpr) {
+ if (StartsObjCMethodExpr && CurrentToken->Previous != Left) {
CurrentToken->Type = TT_ObjCMethodExpr;
// determineStarAmpUsage() thinks that '*' '[' is allocating an
// array of pointers, but if '[' starts a selector then '*' is a
// binary operator.
- if (Parent != NULL && Parent->Type == TT_PointerOrReference)
+ if (Parent && Parent->Type == TT_PointerOrReference)
Parent->Type = TT_BinaryOperator;
}
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
- if (Contexts.back().FirstObjCSelectorName != NULL) {
+ if (Contexts.back().FirstObjCSelectorName) {
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
if (Contexts.back().NumBlockParameters > 1)
@@ -281,7 +289,7 @@
}
bool parseBrace() {
- if (CurrentToken != NULL) {
+ if (CurrentToken) {
FormatToken *Left = CurrentToken->Previous;
if (Contexts.back().CaretFound)
@@ -290,8 +298,10 @@
ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
Contexts.back().ColonIsDictLiteral = true;
+ if (Left->BlockKind == BK_BracedInit)
+ Contexts.back().IsExpression = true;
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
if (CurrentToken->is(tok::r_brace)) {
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
@@ -325,7 +335,7 @@
}
bool parseConditional() {
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
if (CurrentToken->is(tok::colon)) {
CurrentToken->Type = TT_ConditionalExpr;
next();
@@ -338,12 +348,12 @@
}
bool parseTemplateDeclaration() {
- if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
+ if (CurrentToken && CurrentToken->is(tok::less)) {
CurrentToken->Type = TT_TemplateOpener;
next();
if (!parseAngle())
return false;
- if (CurrentToken != NULL)
+ if (CurrentToken)
CurrentToken->Previous->ClosesTemplateDeclaration = true;
return true;
}
@@ -356,14 +366,15 @@
switch (Tok->Tok.getKind()) {
case tok::plus:
case tok::minus:
- if (Tok->Previous == NULL && Line.MustBeDeclaration)
+ if (!Tok->Previous && Line.MustBeDeclaration)
Tok->Type = TT_ObjCMethodSpecifier;
break;
case tok::colon:
- if (Tok->Previous == NULL)
+ if (!Tok->Previous)
return false;
// Colons from ?: are handled in parseConditional().
- if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1) {
+ if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1 &&
+ Line.First->isNot(tok::kw_case)) {
Tok->Type = TT_CtorInitializerColon;
} else if (Contexts.back().ColonIsDictLiteral) {
Tok->Type = TT_DictLiteral;
@@ -375,12 +386,11 @@
Contexts.back().LongestObjCSelectorName) {
Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth;
}
- if (Contexts.back().FirstObjCSelectorName == NULL)
+ if (!Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName = Tok->Previous;
} else if (Contexts.back().ColonIsForRangeExpr) {
Tok->Type = TT_RangeBasedForLoopColon;
- } else if (CurrentToken != NULL &&
- CurrentToken->is(tok::numeric_constant)) {
+ } else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
Tok->Type = TT_BitFieldColon;
} else if (Contexts.size() == 1 && Line.First->isNot(tok::kw_enum)) {
Tok->Type = TT_InheritanceColon;
@@ -390,7 +400,7 @@
break;
case tok::kw_if:
case tok::kw_while:
- if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) {
+ if (CurrentToken && CurrentToken->is(tok::l_paren)) {
next();
if (!parseParens(/*LookForDecls=*/true))
return false;
@@ -406,7 +416,9 @@
if (!parseParens())
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
- !Contexts.back().IsExpression && Line.First->Type != TT_ObjCProperty)
+ !Contexts.back().IsExpression &&
+ Line.First->Type != TT_ObjCProperty &&
+ (!Tok->Previous || Tok->Previous->isNot(tok::kw_decltype)))
Line.MightBeFunctionDecl = true;
break;
case tok::l_square:
@@ -431,7 +443,7 @@
return false;
case tok::r_brace:
// Lines can start with '}'.
- if (Tok->Previous != NULL)
+ if (Tok->Previous)
return false;
break;
case tok::greater:
@@ -479,15 +491,15 @@
void parseIncludeDirective() {
next();
- if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
+ if (CurrentToken && CurrentToken->is(tok::less)) {
next();
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
if (CurrentToken->isNot(tok::comment) || CurrentToken->Next)
CurrentToken->Type = TT_ImplicitStringLiteral;
next();
}
} else {
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
if (CurrentToken->is(tok::string_literal))
// Mark these string literals as "implicit" literals, too, so that
// they are not split or line-wrapped.
@@ -502,7 +514,7 @@
// We still want to format the whitespace left of the first token of the
// warning or error.
next();
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
CurrentToken->Type = TT_ImplicitStringLiteral;
next();
}
@@ -513,7 +525,7 @@
if (CurrentToken && CurrentToken->TokenText == "mark") {
next(); // Consume "mark".
next(); // Consume first token (so we fix leading whitespace).
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
CurrentToken->Type = TT_ImplicitStringLiteral;
next();
}
@@ -522,7 +534,7 @@
void parsePreprocessorDirective() {
next();
- if (CurrentToken == NULL)
+ if (!CurrentToken)
return;
if (CurrentToken->Tok.is(tok::numeric_constant)) {
CurrentToken->SpacesRequiredBefore = 1;
@@ -530,7 +542,7 @@
}
// Hashes in the middle of a line can lead to any strange token
// sequence.
- if (CurrentToken->Tok.getIdentifierInfo() == NULL)
+ if (!CurrentToken->Tok.getIdentifierInfo())
return;
switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
@@ -552,7 +564,7 @@
default:
break;
}
- while (CurrentToken != NULL)
+ while (CurrentToken)
next();
}
@@ -571,7 +583,7 @@
CurrentToken->Next && CurrentToken->Next->is(tok::string_literal))
parseIncludeDirective();
- while (CurrentToken != NULL) {
+ while (CurrentToken) {
if (CurrentToken->is(tok::kw_virtual))
KeywordVirtualFound = true;
if (!consumeToken())
@@ -581,7 +593,7 @@
return LT_VirtualFunctionDecl;
if (Line.First->Type == TT_ObjCMethodSpecifier) {
- if (Contexts.back().FirstObjCSelectorName != NULL)
+ if (Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
return LT_ObjCMethodDecl;
@@ -592,30 +604,30 @@
private:
void resetTokenMetadata(FormatToken *Token) {
- if (Token == nullptr) return;
+ if (!Token)
+ return;
// Reset token type in case we have already looked at it and then
// recovered from an error (e.g. failure to find the matching >).
if (CurrentToken->Type != TT_LambdaLSquare &&
CurrentToken->Type != TT_FunctionLBrace &&
CurrentToken->Type != TT_ImplicitStringLiteral &&
+ CurrentToken->Type != TT_RegexLiteral &&
CurrentToken->Type != TT_TrailingReturnArrow)
CurrentToken->Type = TT_Unknown;
if (CurrentToken->Role)
- CurrentToken->Role.reset(NULL);
+ CurrentToken->Role.reset(nullptr);
CurrentToken->FakeLParens.clear();
CurrentToken->FakeRParens = 0;
}
void next() {
- if (CurrentToken != NULL) {
+ if (CurrentToken) {
determineTokenType(*CurrentToken);
CurrentToken->BindingStrength = Contexts.back().BindingStrength;
CurrentToken->NestingLevel = Contexts.size() - 1;
- }
-
- if (CurrentToken != NULL)
CurrentToken = CurrentToken->Next;
+ }
resetTokenMetadata(CurrentToken);
}
@@ -628,8 +640,8 @@
: ContextKind(ContextKind), BindingStrength(BindingStrength),
LongestObjCSelectorName(0), NumBlockParameters(0),
ColonIsForRangeExpr(false), ColonIsDictLiteral(false),
- ColonIsObjCMethodExpr(false), FirstObjCSelectorName(NULL),
- FirstStartOfName(NULL), IsExpression(IsExpression),
+ ColonIsObjCMethodExpr(false), FirstObjCSelectorName(nullptr),
+ FirstStartOfName(nullptr), IsExpression(IsExpression),
CanBeExpression(true), InTemplateArgument(false),
InCtorInitializer(false), CaretFound(false), IsForEachMacro(false) {}
@@ -674,7 +686,7 @@
for (FormatToken *Previous = Current.Previous;
Previous && !Previous->isOneOf(tok::comma, tok::semi);
Previous = Previous->Previous) {
- if (Previous->is(tok::r_square))
+ if (Previous->isOneOf(tok::r_square, tok::r_paren))
Previous = Previous->MatchingParen;
if (Previous->Type == TT_BinaryOperator &&
Previous->isOneOf(tok::star, tok::amp)) {
@@ -684,7 +696,9 @@
} else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) {
Contexts.back().IsExpression = true;
} else if (Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
- !Line.InPPDirective) {
+ !Line.InPPDirective &&
+ (!Current.Previous ||
+ Current.Previous->isNot(tok::kw_decltype))) {
bool ParametersOfFunctionType =
Current.Previous && Current.Previous->is(tok::r_paren) &&
Current.Previous->MatchingParen &&
@@ -727,15 +741,16 @@
Contexts.back().InTemplateArgument);
} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
Current.Type = determinePlusMinusCaretUsage(Current);
- if (Current.Type == TT_UnaryOperator) {
+ if (Current.Type == TT_UnaryOperator && Current.is(tok::caret)) {
++Contexts.back().NumBlockParameters;
- if (Current.is(tok::caret))
- Contexts.back().CaretFound = true;
+ Contexts.back().CaretFound = true;
}
} else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
Current.Type = determineIncrementUsage(Current);
} else if (Current.is(tok::exclaim)) {
Current.Type = TT_UnaryOperator;
+ } else if (Current.is(tok::question)) {
+ Current.Type = TT_ConditionalExpr;
} else if (Current.isBinaryOperator() &&
(!Current.Previous ||
Current.Previous->isNot(tok::l_square))) {
@@ -746,40 +761,7 @@
else
Current.Type = TT_BlockComment;
} else if (Current.is(tok::r_paren)) {
- FormatToken *LeftOfParens = NULL;
- if (Current.MatchingParen)
- LeftOfParens = Current.MatchingParen->getPreviousNonComment();
- bool IsCast = false;
- bool ParensAreEmpty = Current.Previous == Current.MatchingParen;
- bool ParensAreType = !Current.Previous ||
- Current.Previous->Type == TT_PointerOrReference ||
- Current.Previous->Type == TT_TemplateCloser ||
- Current.Previous->isSimpleTypeSpecifier();
- bool ParensCouldEndDecl =
- Current.Next &&
- Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
- bool IsSizeOfOrAlignOf =
- LeftOfParens &&
- LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
- if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
- ((Contexts.size() > 1 &&
- Contexts[Contexts.size() - 2].IsExpression) ||
- (Current.Next && Current.Next->isBinaryOperator())))
- IsCast = true;
- if (Current.Next && Current.Next->isNot(tok::string_literal) &&
- (Current.Next->Tok.isLiteral() ||
- Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
- IsCast = true;
- // If there is an identifier after the (), it is likely a cast, unless
- // there is also an identifier before the ().
- if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
- LeftOfParens->is(tok::kw_return)) &&
- LeftOfParens->Type != TT_OverloadedOperator &&
- LeftOfParens->isNot(tok::at) &&
- LeftOfParens->Type != TT_TemplateCloser && Current.Next &&
- Current.Next->is(tok::identifier))
- IsCast = true;
- if (IsCast && !ParensAreEmpty)
+ if (rParenEndsCast(Current))
Current.Type = TT_CastRParen;
} else if (Current.is(tok::at) && Current.Next) {
switch (Current.Next->Tok.getObjCKeywordID()) {
@@ -800,6 +782,7 @@
PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
Current.Type = TT_DesignatedInitializerPeriod;
} else if (Current.isOneOf(tok::identifier, tok::kw_const) &&
+ Current.Previous && Current.Previous->isNot(tok::equal) &&
Line.MightBeFunctionDecl && Contexts.size() == 1) {
// Line.MightBeFunctionDecl can only be true after the parentheses of a
// function declaration have been found.
@@ -814,15 +797,15 @@
/// This is a heuristic based on whether \p Tok is an identifier following
/// something that is likely a type.
bool isStartOfName(const FormatToken &Tok) {
- if (Tok.isNot(tok::identifier) || Tok.Previous == NULL)
+ if (Tok.isNot(tok::identifier) || !Tok.Previous)
return false;
// Skip "const" as it does not have an influence on whether this is a name.
FormatToken *PreviousNotConst = Tok.Previous;
- while (PreviousNotConst != NULL && PreviousNotConst->is(tok::kw_const))
+ while (PreviousNotConst && PreviousNotConst->is(tok::kw_const))
PreviousNotConst = PreviousNotConst->Previous;
- if (PreviousNotConst == NULL)
+ if (!PreviousNotConst)
return false;
bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
@@ -834,20 +817,81 @@
PreviousNotConst->MatchingParen->Previous &&
PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
+ if (PreviousNotConst->is(tok::r_paren) && PreviousNotConst->MatchingParen &&
+ PreviousNotConst->MatchingParen->Previous &&
+ PreviousNotConst->MatchingParen->Previous->is(tok::kw_decltype))
+ return true;
+
return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) ||
PreviousNotConst->Type == TT_PointerOrReference ||
PreviousNotConst->isSimpleTypeSpecifier();
}
+ /// \brief Determine whether ')' is ending a cast.
+ bool rParenEndsCast(const FormatToken &Tok) {
+ FormatToken *LeftOfParens = NULL;
+ if (Tok.MatchingParen)
+ LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
+ bool IsCast = false;
+ bool ParensAreEmpty = Tok.Previous == Tok.MatchingParen;
+ bool ParensAreType = !Tok.Previous ||
+ Tok.Previous->Type == TT_PointerOrReference ||
+ Tok.Previous->Type == TT_TemplateCloser ||
+ Tok.Previous->isSimpleTypeSpecifier();
+ bool ParensCouldEndDecl =
+ Tok.Next && Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
+ bool IsSizeOfOrAlignOf =
+ LeftOfParens && LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
+ if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
+ ((Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression) ||
+ (Tok.Next && Tok.Next->isBinaryOperator())))
+ IsCast = true;
+ else if (Tok.Next && Tok.Next->isNot(tok::string_literal) &&
+ (Tok.Next->Tok.isLiteral() ||
+ Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
+ IsCast = true;
+ // If there is an identifier after the (), it is likely a cast, unless
+ // there is also an identifier before the ().
+ else if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
+ LeftOfParens->is(tok::kw_return)) &&
+ LeftOfParens->Type != TT_OverloadedOperator &&
+ LeftOfParens->isNot(tok::at) &&
+ LeftOfParens->Type != TT_TemplateCloser && Tok.Next) {
+ if (Tok.Next->isOneOf(tok::identifier, tok::numeric_constant)) {
+ IsCast = true;
+ } else {
+ // Use heuristics to recognize c style casting.
+ FormatToken *Prev = Tok.Previous;
+ if (Prev && Prev->isOneOf(tok::amp, tok::star))
+ Prev = Prev->Previous;
+
+ if (Prev && Tok.Next && Tok.Next->Next) {
+ bool NextIsUnary = Tok.Next->isUnaryOperator() ||
+ Tok.Next->isOneOf(tok::amp, tok::star);
+ IsCast = NextIsUnary && Tok.Next->Next->isOneOf(
+ tok::identifier, tok::numeric_constant);
+ }
+
+ for (; Prev != Tok.MatchingParen; Prev = Prev->Previous) {
+ if (!Prev || !Prev->isOneOf(tok::kw_const, tok::identifier)) {
+ IsCast = false;
+ break;
+ }
+ }
+ }
+ }
+ return IsCast && !ParensAreEmpty;
+ }
+
/// \brief Return the type of the given token assuming it is * or &.
TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,
bool InTemplateArgument) {
const FormatToken *PrevToken = Tok.getPreviousNonComment();
- if (PrevToken == NULL)
+ if (!PrevToken)
return TT_UnaryOperator;
const FormatToken *NextToken = Tok.getNextNonComment();
- if (NextToken == NULL)
+ if (!NextToken)
return TT_Unknown;
if (PrevToken->is(tok::coloncolon) ||
@@ -858,10 +902,11 @@
tok::comma, tok::semi, tok::kw_return, tok::colon,
tok::equal, tok::kw_delete, tok::kw_sizeof) ||
PrevToken->Type == TT_BinaryOperator ||
+ PrevToken->Type == TT_ConditionalExpr ||
PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen)
return TT_UnaryOperator;
- if (NextToken->is(tok::l_square))
+ if (NextToken->is(tok::l_square) && NextToken->Type != TT_LambdaLSquare)
return TT_PointerOrReference;
if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
@@ -891,7 +936,7 @@
TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
const FormatToken *PrevToken = Tok.getPreviousNonComment();
- if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
+ if (!PrevToken || PrevToken->Type == TT_CastRParen)
return TT_UnaryOperator;
// Use heuristics to recognize unary operators.
@@ -911,7 +956,7 @@
/// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
TokenType determineIncrementUsage(const FormatToken &Tok) {
const FormatToken *PrevToken = Tok.getPreviousNonComment();
- if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
+ if (!PrevToken || PrevToken->Type == TT_CastRParen)
return TT_UnaryOperator;
if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
return TT_TrailingUnaryOperator;
@@ -919,7 +964,6 @@
return TT_UnaryOperator;
}
-
SmallVector<Context, 8> Contexts;
const FormatStyle &Style;
@@ -952,7 +996,7 @@
(Current->is(tok::colon) && Current->Type == TT_ObjCMethodExpr)))
next();
- if (Current == NULL || Precedence > PrecedenceArrowAndPeriod)
+ if (!Current || Precedence > PrecedenceArrowAndPeriod)
return;
// Conditional expressions need to be parsed separately for proper nesting.
@@ -969,7 +1013,8 @@
}
FormatToken *Start = Current;
- FormatToken *LatestOperator = NULL;
+ FormatToken *LatestOperator = nullptr;
+ unsigned OperatorIndex = 0;
while (Current) {
// Consume operators with higher precedence.
@@ -986,11 +1031,11 @@
// At the end of the line or when an operator with higher precedence is
// found, insert fake parenthesis and return.
- if (Current == NULL || Current->closesScope() ||
+ if (!Current || Current->closesScope() ||
(CurrentPrecedence != -1 && CurrentPrecedence < Precedence)) {
if (LatestOperator) {
+ LatestOperator->LastOperator = true;
if (Precedence == PrecedenceArrowAndPeriod) {
- LatestOperator->LastInChainOfCalls = true;
// Call expressions don't have a binary operator precedence.
addFakeParenthesis(Start, prec::Unknown);
} else {
@@ -1009,8 +1054,11 @@
next();
} else {
// Operator found.
- if (CurrentPrecedence == Precedence)
+ if (CurrentPrecedence == Precedence) {
LatestOperator = Current;
+ Current->OperatorIndex = OperatorIndex;
+ ++OperatorIndex;
+ }
next();
}
@@ -1051,7 +1099,7 @@
/// \brief Parse unary operator expressions and surround them with fake
/// parentheses if appropriate.
void parseUnaryOperator() {
- if (Current == NULL || Current->Type != TT_UnaryOperator) {
+ if (!Current || Current->Type != TT_UnaryOperator) {
parse(PrecedenceArrowAndPeriod);
return;
}
@@ -1092,15 +1140,15 @@
void
TokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) {
- const AnnotatedLine *NextNonCommentLine = NULL;
+ const AnnotatedLine *NextNonCommentLine = nullptr;
for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),
E = Lines.rend();
I != E; ++I) {
if (NextNonCommentLine && (*I)->First->is(tok::comment) &&
- (*I)->First->Next == NULL)
+ (*I)->First->Next == nullptr)
(*I)->Level = NextNonCommentLine->Level;
else
- NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : NULL;
+ NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : nullptr;
setCommentLineLevels((*I)->Children);
}
@@ -1132,13 +1180,19 @@
}
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
+ for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
+ E = Line.Children.end();
+ I != E; ++I) {
+ calculateFormattingInformation(**I);
+ }
+
Line.First->TotalLength =
Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth;
if (!Line.First->Next)
return;
FormatToken *Current = Line.First->Next;
bool InFunctionDecl = Line.MightBeFunctionDecl;
- while (Current != NULL) {
+ while (Current) {
if (Current->Type == TT_LineComment) {
if (Current->Previous->BlockKind == BK_BracedInit &&
Current->Previous->opensScope())
@@ -1167,7 +1221,7 @@
}
}
} else if (Current->SpacesRequiredBefore == 0 &&
- spaceRequiredBefore(Line, *Current)) {
+ spaceRequiredBefore(Line, *Current)) {
Current->SpacesRequiredBefore = 1;
}
@@ -1176,12 +1230,18 @@
Current->CanBreakBefore =
Current->MustBreakBefore || canBreakBefore(Line, *Current);
- if (Current->MustBreakBefore || !Current->Children.empty() ||
+ unsigned ChildSize = 0;
+ if (Current->Previous->Children.size() == 1) {
+ FormatToken &LastOfChild = *Current->Previous->Children[0]->Last;
+ ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit
+ : LastOfChild.TotalLength + 1;
+ }
+ if (Current->MustBreakBefore || Current->Previous->Children.size() > 1 ||
Current->IsMultiline)
Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;
else
Current->TotalLength = Current->Previous->TotalLength +
- Current->ColumnWidth +
+ Current->ColumnWidth + ChildSize +
Current->SpacesRequiredBefore;
if (Current->Type == TT_CtorInitializerColon)
@@ -1197,24 +1257,18 @@
}
calculateUnbreakableTailLengths(Line);
- for (Current = Line.First; Current != NULL; Current = Current->Next) {
+ for (Current = Line.First; Current != nullptr; Current = Current->Next) {
if (Current->Role)
Current->Role->precomputeFormattingInfos(Current);
}
DEBUG({ printDebugInfo(Line); });
-
- for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
- E = Line.Children.end();
- I != E; ++I) {
- calculateFormattingInformation(**I);
- }
}
void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
unsigned UnbreakableTailLength = 0;
FormatToken *Current = Line.Last;
- while (Current != NULL) {
+ while (Current) {
Current->UnbreakableTailLength = UnbreakableTailLength;
if (Current->CanBreakBefore ||
Current->isOneOf(tok::comment, tok::string_literal)) {
@@ -1235,7 +1289,8 @@
if (Left.is(tok::semi))
return 0;
- if (Left.is(tok::comma))
+ if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
+ Right.Next->Type == TT_DictLiteral))
return 1;
if (Right.is(tok::l_square)) {
if (Style.Language == FormatStyle::LK_Proto)
@@ -1280,11 +1335,8 @@
// annotations (i.e. "const", "final" and "override") on the same line.
// Use a slightly higher penalty after ")" so that annotations like
// "const override" are kept together.
- bool is_standard_annotation = Right.is(tok::kw_const) ||
- Right.TokenText == "override" ||
- Right.TokenText == "final";
- return (Left.is(tok::r_paren) ? 100 : 120) +
- (is_standard_annotation ? 50 : 0);
+ bool is_short_annotation = Right.TokenText.size() < 10;
+ return (Left.is(tok::r_paren) ? 100 : 120) + (is_short_annotation ? 50 : 0);
}
// In for-loops, prefer breaking at ',' and ';'.
@@ -1337,7 +1389,12 @@
if (Right.is(tok::l_paren) &&
(Left.TokenText == "returns" || Left.TokenText == "option"))
return true;
+ } else if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (Left.TokenText == "var")
+ return true;
}
+ if (Left.is(tok::kw_return) && Right.isNot(tok::semi))
+ return true;
if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty &&
Left.Tok.getObjCKeywordID() == tok::objc_property)
return true;
@@ -1404,19 +1461,21 @@
return Right.MatchingParen && Style.SpacesInContainerLiterals &&
Right.MatchingParen->Type == TT_ArrayInitializerLSquare;
if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&
- Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant))
+ Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant) &&
+ Left.Type != TT_DictLiteral)
return false;
if (Left.is(tok::colon))
return Left.Type != TT_ObjCMethodExpr;
+ if (Left.Type == TT_BlockComment)
+ return !Left.TokenText.endswith("=*/");
if (Right.is(tok::l_paren)) {
if (Left.is(tok::r_paren) && Left.Type == TT_AttributeParen)
return true;
return Line.Type == LT_ObjCDecl ||
- Left.isOneOf(tok::kw_return, tok::kw_new, tok::kw_delete,
- tok::semi) ||
+ Left.isOneOf(tok::kw_new, tok::kw_delete, tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
(Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while,
- tok::kw_switch, tok::kw_catch) ||
+ tok::kw_switch, tok::kw_catch, tok::kw_case) ||
Left.IsForEachMacro)) ||
(Style.SpaceBeforeParens == FormatStyle::SBPO_Always &&
Left.isOneOf(tok::identifier, tok::kw___attribute) &&
@@ -1430,12 +1489,11 @@
(Right.is(tok::r_brace) && Right.MatchingParen &&
Right.MatchingParen->BlockKind != BK_Block))
return !Style.Cpp11BracedListStyle;
- if (Left.Type == TT_BlockComment && Left.TokenText.endswith("=*/"))
- return false;
if (Right.Type == TT_UnaryOperator)
return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
(Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr);
- if (Left.isOneOf(tok::identifier, tok::greater, tok::r_square) &&
+ if ((Left.isOneOf(tok::identifier, tok::greater, tok::r_square) ||
+ Left.isSimpleTypeSpecifier()) &&
Right.is(tok::l_brace) && Right.getNextNonComment() &&
Right.BlockKind != BK_Block)
return false;
@@ -1478,7 +1536,7 @@
return false;
if (Tok.is(tok::colon))
return !Line.First->isOneOf(tok::kw_case, tok::kw_default) &&
- Tok.getNextNonComment() != NULL && Tok.Type != TT_ObjCMethodExpr &&
+ Tok.getNextNonComment() && Tok.Type != TT_ObjCMethodExpr &&
!Tok.Previous->is(tok::question) &&
(Tok.Type != TT_DictLiteral || Style.SpacesInContainerLiterals);
if (Tok.Previous->Type == TT_UnaryOperator ||
@@ -1496,7 +1554,8 @@
Tok.getPrecedence() == prec::Assignment)
return false;
if ((Tok.Type == TT_BinaryOperator && !Tok.Previous->is(tok::l_paren)) ||
- Tok.Previous->Type == TT_BinaryOperator)
+ Tok.Previous->Type == TT_BinaryOperator ||
+ Tok.Previous->Type == TT_ConditionalExpr)
return true;
if (Tok.Previous->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
return false;
@@ -1505,6 +1564,8 @@
return true;
if (Tok.Type == TT_TrailingUnaryOperator)
return false;
+ if (Tok.Previous->Type == TT_RegexLiteral)
+ return false;
return spaceRequiredBetween(Line, *Tok.Previous, Tok);
}
@@ -1514,7 +1575,7 @@
if (Right.is(tok::comment)) {
return Right.Previous->BlockKind != BK_BracedInit &&
Right.Previous->Type != TT_CtorInitializerColon &&
- Right.NewlinesBefore > 0;
+ (Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);
} else if (Right.Previous->isTrailingComment() ||
(Right.isStringLiteral() && Right.Previous->isStringLiteral())) {
return true;
@@ -1534,7 +1595,8 @@
Style.BreakConstructorInitializersBeforeComma &&
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine) {
return true;
- } else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) {
+ } else if (Right.is(tok::l_brace) && Right.BlockKind == BK_Block &&
+ Right.Type != TT_ObjCBlockLBrace && Right.Type != TT_DictLiteral) {
return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU;
} else if (Right.is(tok::string_literal) &&
@@ -1547,14 +1609,27 @@
Style.Language == FormatStyle::LK_Proto) {
// Don't enums onto single lines in protocol buffers.
return true;
- } else if ((Left.is(tok::l_brace) && Left.MatchingParen &&
- Left.MatchingParen->Previous &&
- Left.MatchingParen->Previous->is(tok::comma)) ||
- (Right.is(tok::r_brace) && Left.is(tok::comma))) {
- // If the last token before a '}' is a comma, the intention is to insert a
- // line break after it in order to make shuffling around entries easier.
- return true;
}
+
+ // If the last token before a '}' is a comma or a comment, the intention is to
+ // insert a line break after it in order to make shuffling around entries
+ // easier.
+ const FormatToken *BeforeClosingBrace = nullptr;
+ if (Left.is(tok::l_brace) && Left.MatchingParen)
+ BeforeClosingBrace = Left.MatchingParen->Previous;
+ else if (Right.is(tok::r_brace))
+ BeforeClosingBrace = Right.Previous;
+ if (BeforeClosingBrace &&
+ BeforeClosingBrace->isOneOf(tok::comma, tok::comment))
+ return true;
+
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ // FIXME: This might apply to other languages and token kinds.
+ if (Right.is(tok::char_constant) && Left.is(tok::plus) && Left.Previous &&
+ Left.Previous->is(tok::char_constant))
+ return true;
+ }
+
return false;
}
@@ -1563,6 +1638,8 @@
const FormatToken &Left = *Right.Previous;
if (Left.is(tok::at))
return false;
+ if (Left.Tok.getObjCKeywordID() == tok::objc_interface)
+ return false;
if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator))
return true;
if (Right.isTrailingComment())
@@ -1609,7 +1686,7 @@
return false;
if (Left.is(tok::l_paren) && Left.Previous &&
(Left.Previous->Type == TT_BinaryOperator ||
- Left.Previous->Type == TT_CastRParen))
+ Left.Previous->Type == TT_CastRParen || Left.Previous->is(tok::kw_if)))
return false;
if (Right.Type == TT_ImplicitStringLiteral)
return false;
@@ -1622,11 +1699,11 @@
if (Right.is(tok::r_brace))
return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block;
- // Allow breaking after a trailing 'const', e.g. after a method declaration,
- // unless it is follow by ';', '{' or '='.
- if (Left.is(tok::kw_const) && Left.Previous != NULL &&
- Left.Previous->is(tok::r_paren))
- return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal);
+ // Allow breaking after a trailing annotation, e.g. after a method
+ // declaration.
+ if (Left.Type == TT_TrailingAnnotation)
+ return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren,
+ tok::less, tok::coloncolon);
if (Right.is(tok::kw___attribute))
return true;
@@ -1634,17 +1711,21 @@
if (Left.is(tok::identifier) && Right.is(tok::string_literal))
return true;
+ if (Right.is(tok::identifier) && Right.Next &&
+ Right.Next->Type == TT_DictLiteral)
+ return true;
+
if (Left.Type == TT_CtorInitializerComma &&
Style.BreakConstructorInitializersBeforeComma)
return false;
if (Right.Type == TT_CtorInitializerComma &&
Style.BreakConstructorInitializersBeforeComma)
return true;
- if (Right.Type == TT_BinaryOperator && Style.BreakBeforeBinaryOperators)
- return true;
if (Left.is(tok::greater) && Right.is(tok::greater) &&
Left.Type != TT_TemplateCloser)
return false;
+ if (Right.Type == TT_BinaryOperator && Style.BreakBeforeBinaryOperators)
+ return true;
if (Left.Type == TT_ArrayInitializerLSquare)
return true;
return (Left.isBinaryOperator() && Left.isNot(tok::lessless) &&
@@ -1671,7 +1752,7 @@
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
llvm::errs() << Tok->FakeLParens[i] << "/";
llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n";
- if (Tok->Next == NULL)
+ if (!Tok->Next)
assert(Tok == Line.Last);
Tok = Tok->Next;
}
diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index bd91980..0df70a0 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/lib/Format/TokenAnnotator.h
@@ -48,7 +48,7 @@
// Calculate Next and Previous for all tokens. Note that we must overwrite
// Next and Previous for every token, as previous formatting runs might have
// left them in a different state.
- First->Previous = NULL;
+ First->Previous = nullptr;
FormatToken *Current = First;
for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
E = Line.Tokens.end();
@@ -67,7 +67,7 @@
}
}
Last = Current;
- Last->Next = NULL;
+ Last->Next = nullptr;
}
~AnnotatedLine() {
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 96d8155..d0750af 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -13,11 +13,11 @@
///
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "format-parser"
-
#include "UnwrappedLineParser.h"
#include "llvm/Support/Debug.h"
+#define DEBUG_TYPE "format-parser"
+
namespace clang {
namespace format {
@@ -60,7 +60,7 @@
: Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource),
StructuralError(StructuralError),
- PreviousStructuralError(StructuralError), Token(NULL) {
+ PreviousStructuralError(StructuralError), Token(nullptr) {
TokenSource = this;
Line.Level = 0;
Line.InPPDirective = true;
@@ -164,9 +164,7 @@
++LineLevel;
}
}
- ~CompoundStatementIndenter() {
- LineLevel = OldLineLevel;
- }
+ ~CompoundStatementIndenter() { LineLevel = OldLineLevel; }
private:
unsigned &LineLevel;
@@ -208,14 +206,15 @@
ArrayRef<FormatToken *> Tokens,
UnwrappedLineConsumer &Callback)
: Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
- CurrentLines(&Lines), StructuralError(false), Style(Style), Tokens(NULL),
- Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1) {}
+ CurrentLines(&Lines), StructuralError(false), Style(Style),
+ Tokens(nullptr), Callback(Callback), AllTokens(Tokens),
+ PPBranchLevel(-1) {}
void UnwrappedLineParser::reset() {
PPBranchLevel = -1;
Line.reset(new UnwrappedLine);
CommentsBeforeNextToken.clear();
- FormatTok = NULL;
+ FormatTok = nullptr;
MustBreakBeforeNextToken = false;
PreprocessorDirectives.clear();
CurrentLines = &Lines;
@@ -335,18 +334,30 @@
case tok::r_brace:
if (!LBraceStack.empty()) {
if (LBraceStack.back()->BlockKind == BK_Unknown) {
- // If there is a comma, semicolon or right paren after the closing
- // brace, we assume this is a braced initializer list. Note that
- // regardless how we mark inner braces here, we will overwrite the
- // BlockKind later if we parse a braced list (where all blocks inside
- // are by default braced lists), or when we explicitly detect blocks
- // (for example while parsing lambdas).
- //
- // We exclude + and - as they can be ObjC visibility modifiers.
- if (NextTok->isOneOf(tok::comma, tok::semi, tok::r_paren, tok::period,
- tok::r_square, tok::l_brace, tok::colon) ||
- (NextTok->isBinaryOperator() &&
- !NextTok->isOneOf(tok::plus, tok::minus))) {
+ bool ProbablyBracedList = false;
+ if (Style.Language == FormatStyle::LK_Proto) {
+ ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
+ } else {
+ // Using OriginalColumn to distinguish between ObjC methods and
+ // binary operators is a bit hacky.
+ bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
+ NextTok->OriginalColumn == 0;
+
+ // If there is a comma, semicolon or right paren after the closing
+ // brace, we assume this is a braced initializer list. Note that
+ // regardless how we mark inner braces here, we will overwrite the
+ // BlockKind later if we parse a braced list (where all blocks
+ // inside are by default braced lists), or when we explicitly detect
+ // blocks (for example while parsing lambdas).
+ //
+ // We exclude + and - as they can be ObjC visibility modifiers.
+ ProbablyBracedList =
+ NextTok->isOneOf(tok::comma, tok::semi, tok::period, tok::colon,
+ tok::r_paren, tok::r_square, tok::l_brace,
+ tok::l_paren) ||
+ (NextTok->isBinaryOperator() && !NextIsObjCMethod);
+ }
+ if (ProbablyBracedList) {
Tok->BlockKind = BK_BracedInit;
LBraceStack.back()->BlockKind = BK_BracedInit;
} else {
@@ -408,16 +419,34 @@
Line->Level = InitialLevel;
}
+static bool IsGoogScope(const UnwrappedLine &Line) {
+ if (Line.Tokens.size() < 4)
+ return false;
+ auto I = Line.Tokens.begin();
+ if (I->Tok->TokenText != "goog")
+ return false;
+ ++I;
+ if (I->Tok->isNot(tok::period))
+ return false;
+ ++I;
+ if (I->Tok->TokenText != "scope")
+ return false;
+ ++I;
+ return I->Tok->is(tok::l_paren);
+}
+
void UnwrappedLineParser::parseChildBlock() {
FormatTok->BlockKind = BK_Block;
nextToken();
{
+ bool GoogScope =
+ Style.Language == FormatStyle::LK_JavaScript && IsGoogScope(*Line);
ScopedLineState LineState(*this);
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
/*MustBeDeclaration=*/false);
- Line->Level += 1;
+ Line->Level += GoogScope ? 0 : 1;
parseLevel(/*HasOpeningBrace=*/true);
- Line->Level -= 1;
+ Line->Level -= GoogScope ? 0 : 1;
}
nextToken();
}
@@ -427,7 +456,7 @@
ScopedMacroState MacroState(*Line, Tokens, FormatTok, StructuralError);
nextToken();
- if (FormatTok->Tok.getIdentifierInfo() == NULL) {
+ if (!FormatTok->Tok.getIdentifierInfo()) {
parsePPUnknown();
return;
}
@@ -458,14 +487,14 @@
}
}
-void UnwrappedLineParser::pushPPConditional() {
- if (!PPStack.empty() && PPStack.back() == PP_Unreachable)
+void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {
+ if (Unreachable || (!PPStack.empty() && PPStack.back() == PP_Unreachable))
PPStack.push_back(PP_Unreachable);
else
PPStack.push_back(PP_Conditional);
}
-void UnwrappedLineParser::parsePPIf(bool IfDef) {
+void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {
++PPBranchLevel;
assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());
if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {
@@ -473,37 +502,22 @@
PPLevelBranchCount.push_back(0);
}
PPChainBranchIndex.push(0);
- nextToken();
- bool IsLiteralFalse = (FormatTok->Tok.isLiteral() &&
- StringRef(FormatTok->Tok.getLiteralData(),
- FormatTok->Tok.getLength()) == "0") ||
- FormatTok->Tok.is(tok::kw_false);
- if ((!IfDef && IsLiteralFalse) || PPLevelBranchIndex[PPBranchLevel] > 0) {
- PPStack.push_back(PP_Unreachable);
- } else {
- pushPPConditional();
- }
- parsePPUnknown();
+ bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
+ conditionalCompilationCondition(Unreachable || Skip);
}
-void UnwrappedLineParser::parsePPElse() {
+void UnwrappedLineParser::conditionalCompilationAlternative() {
if (!PPStack.empty())
PPStack.pop_back();
assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
if (!PPChainBranchIndex.empty())
++PPChainBranchIndex.top();
- if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
- PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top()) {
- PPStack.push_back(PP_Unreachable);
- } else {
- pushPPConditional();
- }
- parsePPUnknown();
+ conditionalCompilationCondition(
+ PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
+ PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());
}
-void UnwrappedLineParser::parsePPElIf() { parsePPElse(); }
-
-void UnwrappedLineParser::parsePPEndIf() {
+void UnwrappedLineParser::conditionalCompilationEnd() {
assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {
if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel]) {
@@ -517,6 +531,27 @@
PPChainBranchIndex.pop();
if (!PPStack.empty())
PPStack.pop_back();
+}
+
+void UnwrappedLineParser::parsePPIf(bool IfDef) {
+ nextToken();
+ bool IsLiteralFalse = (FormatTok->Tok.isLiteral() &&
+ StringRef(FormatTok->Tok.getLiteralData(),
+ FormatTok->Tok.getLength()) == "0") ||
+ FormatTok->Tok.is(tok::kw_false);
+ conditionalCompilationStart(!IfDef && IsLiteralFalse);
+ parsePPUnknown();
+}
+
+void UnwrappedLineParser::parsePPElse() {
+ conditionalCompilationAlternative();
+ parsePPUnknown();
+}
+
+void UnwrappedLineParser::parsePPElIf() { parsePPElse(); }
+
+void UnwrappedLineParser::parsePPEndIf() {
+ conditionalCompilationEnd();
parsePPUnknown();
}
@@ -575,7 +610,9 @@
// Colon is used in labels, base class lists, initializer lists,
// range-based for loops, ternary operator, but should never be the
// first token in an unwrapped line.
- Tok.isNot(tok::colon);
+ Tok.isNot(tok::colon) &&
+ // 'noexcept' is a trailing annotation.
+ Tok.isNot(tok::kw_noexcept);
}
void UnwrappedLineParser::parseStructuralElement() {
@@ -644,6 +681,9 @@
case tok::kw_case:
parseCaseLabel();
return;
+ case tok::kw_try:
+ parseTryCatch();
+ return;
case tok::kw_extern:
nextToken();
if (FormatTok->Tok.is(tok::string_literal)) {
@@ -724,8 +764,16 @@
// Otherwise this was a braced init list, and the structural
// element continues.
break;
+ case tok::kw_try:
+ // We arrive here when parsing function-try blocks.
+ parseTryCatch();
+ return;
case tok::identifier: {
StringRef Text = FormatTok->TokenText;
+ if (Style.Language == FormatStyle::LK_JavaScript && Text == "function") {
+ tryToParseJSFunction();
+ break;
+ }
nextToken();
if (Line->Tokens.size() == 1) {
if (FormatTok->Tok.is(tok::colon)) {
@@ -855,6 +903,22 @@
return false;
}
+void UnwrappedLineParser::tryToParseJSFunction() {
+ nextToken();
+ if (FormatTok->isNot(tok::l_paren))
+ return;
+ nextToken();
+ while (FormatTok->isNot(tok::l_brace)) {
+ // Err on the side of caution in order to avoid consuming the full file in
+ // case of incomplete code.
+ if (!FormatTok->isOneOf(tok::identifier, tok::comma, tok::r_paren,
+ tok::comment))
+ return;
+ nextToken();
+ }
+ parseChildBlock();
+}
+
bool UnwrappedLineParser::tryToParseBracedList() {
if (FormatTok->BlockKind == BK_Unknown)
calculateBraceTypes();
@@ -872,9 +936,11 @@
// FIXME: Once we have an expression parser in the UnwrappedLineParser,
// replace this by using parseAssigmentExpression() inside.
do {
- // FIXME: When we start to support lambdas, we'll want to parse them away
- // here, otherwise our bail-out scenarios below break. The better solution
- // might be to just implement a more or less complete expression parser.
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ FormatTok->TokenText == "function") {
+ tryToParseJSFunction();
+ continue;
+ }
switch (FormatTok->Tok.getKind()) {
case tok::caret:
nextToken();
@@ -1022,6 +1088,72 @@
}
}
+void UnwrappedLineParser::parseTryCatch() {
+ assert(FormatTok->is(tok::kw_try) && "'try' expected");
+ nextToken();
+ bool NeedsUnwrappedLine = false;
+ if (FormatTok->is(tok::colon)) {
+ // We are in a function try block, what comes is an initializer list.
+ nextToken();
+ while (FormatTok->is(tok::identifier)) {
+ nextToken();
+ if (FormatTok->is(tok::l_paren))
+ parseParens();
+ else
+ StructuralError = true;
+ if (FormatTok->is(tok::comma))
+ nextToken();
+ }
+ }
+ if (FormatTok->is(tok::l_brace)) {
+ CompoundStatementIndenter Indenter(this, Style, Line->Level);
+ parseBlock(/*MustBeDeclaration=*/false);
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
+ Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
+ Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) {
+ addUnwrappedLine();
+ } else {
+ NeedsUnwrappedLine = true;
+ }
+ } else if (!FormatTok->is(tok::kw_catch)) {
+ // The C++ standard requires a compound-statement after a try.
+ // If there's none, we try to assume there's a structuralElement
+ // and try to continue.
+ StructuralError = true;
+ addUnwrappedLine();
+ ++Line->Level;
+ parseStructuralElement();
+ --Line->Level;
+ }
+ while (FormatTok->is(tok::kw_catch) ||
+ (Style.Language == FormatStyle::LK_JavaScript &&
+ FormatTok->TokenText == "finally")) {
+ nextToken();
+ while (FormatTok->isNot(tok::l_brace)) {
+ if (FormatTok->is(tok::l_paren)) {
+ parseParens();
+ continue;
+ }
+ if (FormatTok->isOneOf(tok::semi, tok::r_brace))
+ return;
+ nextToken();
+ }
+ NeedsUnwrappedLine = false;
+ CompoundStatementIndenter Indenter(this, Style, Line->Level);
+ parseBlock(/*MustBeDeclaration=*/false);
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
+ Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
+ Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) {
+ addUnwrappedLine();
+ } else {
+ NeedsUnwrappedLine = true;
+ }
+ }
+ if (NeedsUnwrappedLine) {
+ addUnwrappedLine();
+ }
+}
+
void UnwrappedLineParser::parseNamespace() {
assert(FormatTok->Tok.is(tok::kw_namespace) && "'namespace' expected");
nextToken();
@@ -1157,9 +1289,8 @@
nextToken();
}
// Eat up enum class ...
- if (FormatTok->Tok.is(tok::kw_class) ||
- FormatTok->Tok.is(tok::kw_struct))
- nextToken();
+ if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct))
+ nextToken();
while (FormatTok->Tok.getIdentifierInfo() ||
FormatTok->isOneOf(tok::colon, tok::coloncolon)) {
nextToken();
@@ -1278,9 +1409,12 @@
if (FormatTok->Tok.is(tok::less))
parseObjCProtocolList();
- // If instance variables are present, keep the '{' on the first line too.
- if (FormatTok->Tok.is(tok::l_brace))
+ if (FormatTok->Tok.is(tok::l_brace)) {
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
+ Style.BreakBeforeBraces == FormatStyle::BS_GNU)
+ addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/true);
+ }
// With instance variables, this puts '}' on its own line. Without instance
// variables, this ends the @interface line.
@@ -1351,13 +1485,18 @@
bool UnwrappedLineParser::eof() const { return FormatTok->Tok.is(tok::eof); }
+bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
+ return (Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
+ FormatTok.NewlinesBefore > 0;
+}
+
void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
bool JustComments = Line->Tokens.empty();
for (SmallVectorImpl<FormatToken *>::const_iterator
I = CommentsBeforeNextToken.begin(),
E = CommentsBeforeNextToken.end();
I != E; ++I) {
- if ((*I)->NewlinesBefore && JustComments) {
+ if (isOnNewLine(**I) && JustComments) {
addUnwrappedLine();
}
pushToken(*I);
@@ -1371,7 +1510,7 @@
void UnwrappedLineParser::nextToken() {
if (eof())
return;
- flushComments(FormatTok->NewlinesBefore > 0);
+ flushComments(isOnNewLine(*FormatTok));
pushToken(FormatTok);
readToken();
}
@@ -1391,9 +1530,22 @@
// Comments stored before the preprocessor directive need to be output
// before the preprocessor directive, at the same level as the
// preprocessor directive, as we consider them to apply to the directive.
- flushComments(FormatTok->NewlinesBefore > 0);
+ flushComments(isOnNewLine(*FormatTok));
parsePPDirective();
}
+ while (FormatTok->Type == TT_ConflictStart ||
+ FormatTok->Type == TT_ConflictEnd ||
+ FormatTok->Type == TT_ConflictAlternative) {
+ if (FormatTok->Type == TT_ConflictStart) {
+ conditionalCompilationStart(/*Unreachable=*/false);
+ } else if (FormatTok->Type == TT_ConflictAlternative) {
+ conditionalCompilationAlternative();
+ } else if (FormatTok->Type == TT_ConflictEnd) {
+ conditionalCompilationEnd();
+ }
+ FormatTok = Tokens->getNextToken();
+ FormatTok->MustBreakBefore = true;
+ }
if (!PPStack.empty() && (PPStack.back() == PP_Unreachable) &&
!Line->InPPDirective) {
@@ -1402,7 +1554,7 @@
if (!FormatTok->Tok.is(tok::comment))
return;
- if (FormatTok->NewlinesBefore > 0 || FormatTok->IsFirst) {
+ if (isOnNewLine(*FormatTok) || FormatTok->IsFirst) {
CommentsInCurrentLine = false;
}
if (CommentsInCurrentLine) {
diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h
index 62e0b58..c9182e9 100644
--- a/lib/Format/UnwrappedLineParser.h
+++ b/lib/Format/UnwrappedLineParser.h
@@ -85,6 +85,7 @@
void parseParens();
void parseSquare();
void parseIfThenElse();
+ void parseTryCatch();
void parseForOrWhileLoop();
void parseDoWhile();
void parseLabel();
@@ -100,6 +101,7 @@
void parseObjCProtocol();
bool tryToParseLambda();
bool tryToParseLambdaIntroducer();
+ void tryToParseJSFunction();
void addUnwrappedLine();
bool eof() const;
void nextToken();
@@ -107,7 +109,17 @@
void flushComments(bool NewlineBeforeNext);
void pushToken(FormatToken *Tok);
void calculateBraceTypes();
- void pushPPConditional();
+
+ // Marks a conditional compilation edge (for example, an '#if', '#ifdef',
+ // '#else' or merge conflict marker). If 'Unreachable' is true, assumes
+ // this branch either cannot be taken (for example '#if false'), or should
+ // not be taken in this round.
+ void conditionalCompilationCondition(bool Unreachable);
+ void conditionalCompilationStart(bool Unreachable);
+ void conditionalCompilationAlternative();
+ void conditionalCompilationEnd();
+
+ bool isOnNewLine(const FormatToken &FormatTok);
// FIXME: We are constantly running into bugs where Line.Level is incorrectly
// subtracted from beyond 0. Introduce a method to subtract from Line.Level
@@ -189,7 +201,7 @@
};
struct UnwrappedLineNode {
- UnwrappedLineNode() : Tok(NULL) {}
+ UnwrappedLineNode() : Tok(nullptr) {}
UnwrappedLineNode(FormatToken *Tok) : Tok(Tok) {}
FormatToken *Tok;
diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
index 4c393ed..47b94de 100644
--- a/lib/Format/WhitespaceManager.cpp
+++ b/lib/Format/WhitespaceManager.cpp
@@ -18,9 +18,8 @@
namespace clang {
namespace format {
-bool
-WhitespaceManager::Change::IsBeforeInFile::operator()(const Change &C1,
- const Change &C2) const {
+bool WhitespaceManager::Change::IsBeforeInFile::
+operator()(const Change &C1, const Change &C2) const {
return SourceMgr.isBeforeInTranslationUnit(
C1.OriginalWhitespaceRange.getBegin(),
C2.OriginalWhitespaceRange.getBegin());
@@ -28,7 +27,7 @@
WhitespaceManager::Change::Change(
bool CreateReplacement, const SourceRange &OriginalWhitespaceRange,
- unsigned IndentLevel, unsigned Spaces, unsigned StartOfTokenColumn,
+ unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective)
: CreateReplacement(CreateReplacement),
@@ -69,14 +68,14 @@
void WhitespaceManager::replaceWhitespaceInToken(
const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,
StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,
- unsigned Newlines, unsigned IndentLevel, unsigned Spaces) {
+ unsigned Newlines, unsigned IndentLevel, int Spaces) {
if (Tok.Finalized)
return;
+ SourceLocation Start = Tok.getStartOfNonWhitespace().getLocWithOffset(Offset);
Changes.push_back(Change(
- true, SourceRange(Tok.getStartOfNonWhitespace().getLocWithOffset(Offset),
- Tok.getStartOfNonWhitespace().getLocWithOffset(
- Offset + ReplaceChars)),
- IndentLevel, Spaces, Spaces, Newlines, PreviousPostfix, CurrentPrefix,
+ true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)),
+ IndentLevel, Spaces, std::max(0, Spaces), Newlines, PreviousPostfix,
+ CurrentPrefix,
// If we don't add a newline this change doesn't start a comment. Thus,
// when we align line comments, we don't need to treat this change as one.
// FIXME: We still need to take this change in account to properly
@@ -122,6 +121,22 @@
// cases, setting TokenLength of the last token to 0 is wrong.
Changes.back().TokenLength = 0;
Changes.back().IsTrailingComment = Changes.back().Kind == tok::comment;
+
+ const WhitespaceManager::Change *LastBlockComment = nullptr;
+ for (auto &Change : Changes) {
+ Change.StartOfBlockComment = nullptr;
+ Change.IndentationOffset = 0;
+ if (Change.Kind == tok::comment) {
+ LastBlockComment = &Change;
+ } else if (Change.Kind == tok::unknown) {
+ if ((Change.StartOfBlockComment = LastBlockComment))
+ Change.IndentationOffset =
+ Change.StartOfTokenColumn -
+ Change.StartOfBlockComment->StartOfTokenColumn;
+ } else {
+ LastBlockComment = nullptr;
+ }
+ }
}
void WhitespaceManager::alignTrailingComments() {
@@ -131,58 +146,62 @@
bool BreakBeforeNext = false;
unsigned Newlines = 0;
for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
- unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
- // FIXME: Correctly handle ChangeMaxColumn in PP directives.
- unsigned ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
+ if (Changes[i].StartOfBlockComment)
+ continue;
Newlines += Changes[i].NewlinesBefore;
- if (Changes[i].IsTrailingComment) {
- // If this comment follows an } in column 0, it probably documents the
- // closing of a namespace and we don't want to align it.
- bool FollowsRBraceInColumn0 = i > 0 && Changes[i].NewlinesBefore == 0 &&
- Changes[i - 1].Kind == tok::r_brace &&
- Changes[i - 1].StartOfTokenColumn == 0;
- bool WasAlignedWithStartOfNextLine = false;
- if (Changes[i].NewlinesBefore == 1) { // A comment on its own line.
- for (unsigned j = i + 1; j != e; ++j) {
- if (Changes[j].Kind != tok::comment) { // Skip over comments.
- // The start of the next token was previously aligned with the
- // start of this comment.
- WasAlignedWithStartOfNextLine =
- (SourceMgr.getSpellingColumnNumber(
- Changes[i].OriginalWhitespaceRange.getEnd()) ==
- SourceMgr.getSpellingColumnNumber(
- Changes[j].OriginalWhitespaceRange.getEnd()));
- break;
- }
+ if (!Changes[i].IsTrailingComment)
+ continue;
+
+ unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
+ unsigned ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
+ if (i + 1 != e && Changes[i + 1].ContinuesPPDirective)
+ ChangeMaxColumn -= 2;
+ // If this comment follows an } in column 0, it probably documents the
+ // closing of a namespace and we don't want to align it.
+ bool FollowsRBraceInColumn0 = i > 0 && Changes[i].NewlinesBefore == 0 &&
+ Changes[i - 1].Kind == tok::r_brace &&
+ Changes[i - 1].StartOfTokenColumn == 0;
+ bool WasAlignedWithStartOfNextLine = false;
+ if (Changes[i].NewlinesBefore == 1) { // A comment on its own line.
+ for (unsigned j = i + 1; j != e; ++j) {
+ if (Changes[j].Kind != tok::comment) { // Skip over comments.
+ // The start of the next token was previously aligned with the
+ // start of this comment.
+ WasAlignedWithStartOfNextLine =
+ (SourceMgr.getSpellingColumnNumber(
+ Changes[i].OriginalWhitespaceRange.getEnd()) ==
+ SourceMgr.getSpellingColumnNumber(
+ Changes[j].OriginalWhitespaceRange.getEnd()));
+ break;
}
}
- if (!Style.AlignTrailingComments || FollowsRBraceInColumn0) {
- alignTrailingComments(StartOfSequence, i, MinColumn);
- MinColumn = ChangeMinColumn;
- MaxColumn = ChangeMinColumn;
- StartOfSequence = i;
- } else if (BreakBeforeNext || Newlines > 1 ||
- (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
- // Break the comment sequence if the previous line did not end
- // in a trailing comment.
- (Changes[i].NewlinesBefore == 1 && i > 0 &&
- !Changes[i - 1].IsTrailingComment) ||
- WasAlignedWithStartOfNextLine) {
- alignTrailingComments(StartOfSequence, i, MinColumn);
- MinColumn = ChangeMinColumn;
- MaxColumn = ChangeMaxColumn;
- StartOfSequence = i;
- } else {
- MinColumn = std::max(MinColumn, ChangeMinColumn);
- MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
- }
- BreakBeforeNext =
- (i == 0) || (Changes[i].NewlinesBefore > 1) ||
- // Never start a sequence with a comment at the beginning of
- // the line.
- (Changes[i].NewlinesBefore == 1 && StartOfSequence == i);
- Newlines = 0;
}
+ if (!Style.AlignTrailingComments || FollowsRBraceInColumn0) {
+ alignTrailingComments(StartOfSequence, i, MinColumn);
+ MinColumn = ChangeMinColumn;
+ MaxColumn = ChangeMinColumn;
+ StartOfSequence = i;
+ } else if (BreakBeforeNext || Newlines > 1 ||
+ (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
+ // Break the comment sequence if the previous line did not end
+ // in a trailing comment.
+ (Changes[i].NewlinesBefore == 1 && i > 0 &&
+ !Changes[i - 1].IsTrailingComment) ||
+ WasAlignedWithStartOfNextLine) {
+ alignTrailingComments(StartOfSequence, i, MinColumn);
+ MinColumn = ChangeMinColumn;
+ MaxColumn = ChangeMaxColumn;
+ StartOfSequence = i;
+ } else {
+ MinColumn = std::max(MinColumn, ChangeMinColumn);
+ MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
+ }
+ BreakBeforeNext =
+ (i == 0) || (Changes[i].NewlinesBefore > 1) ||
+ // Never start a sequence with a comment at the beginning of
+ // the line.
+ (Changes[i].NewlinesBefore == 1 && StartOfSequence == i);
+ Newlines = 0;
}
alignTrailingComments(StartOfSequence, Changes.size(), MinColumn);
}
@@ -190,15 +209,20 @@
void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
unsigned Column) {
for (unsigned i = Start; i != End; ++i) {
+ int Shift = 0;
if (Changes[i].IsTrailingComment) {
- assert(Column >= Changes[i].StartOfTokenColumn);
- Changes[i].Spaces += Column - Changes[i].StartOfTokenColumn;
- if (i + 1 != End) {
- Changes[i + 1].PreviousEndOfTokenColumn +=
- Column - Changes[i].StartOfTokenColumn;
- }
- Changes[i].StartOfTokenColumn = Column;
+ Shift = Column - Changes[i].StartOfTokenColumn;
}
+ if (Changes[i].StartOfBlockComment) {
+ Shift = Changes[i].IndentationOffset +
+ Changes[i].StartOfBlockComment->StartOfTokenColumn -
+ Changes[i].StartOfTokenColumn;
+ }
+ assert(Shift >= 0);
+ Changes[i].Spaces += Shift;
+ if (i + 1 != End)
+ Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+ Changes[i].StartOfTokenColumn += Shift;
}
}
@@ -245,8 +269,8 @@
C.PreviousEndOfTokenColumn, C.EscapedNewlineColumn);
else
appendNewlineText(ReplacementText, C.NewlinesBefore);
- appendIndentText(ReplacementText, C.IndentLevel, C.Spaces,
- C.StartOfTokenColumn - C.Spaces);
+ appendIndentText(ReplacementText, C.IndentLevel, std::max(0, C.Spaces),
+ C.StartOfTokenColumn - std::max(0, C.Spaces));
ReplacementText.append(C.CurrentLinePrefix);
storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
}
diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h
index f94464f..189b1ae 100644
--- a/lib/Format/WhitespaceManager.h
+++ b/lib/Format/WhitespaceManager.h
@@ -63,6 +63,12 @@
/// (in this order) at \p Offset inside \p Tok, replacing \p ReplaceChars
/// characters.
///
+ /// Note: \p Spaces can be negative to retain information about initial
+ /// relative column offset between a line of a block comment and the start of
+ /// the comment. This negative offset may be compensated by trailing comment
+ /// alignment here. In all other cases negative \p Spaces will be truncated to
+ /// 0.
+ ///
/// When \p InPPDirective is true, escaped newlines are inserted. \p Spaces is
/// used to align backslashes correctly.
void replaceWhitespaceInToken(const FormatToken &Tok, unsigned Offset,
@@ -70,7 +76,7 @@
StringRef PreviousPostfix,
StringRef CurrentPrefix, bool InPPDirective,
unsigned Newlines, unsigned IndentLevel,
- unsigned Spaces);
+ int Spaces);
/// \brief Returns all the \c Replacements created during formatting.
const tooling::Replacements &generateReplacements();
@@ -101,7 +107,7 @@
/// \p StartOfTokenColumn and \p InPPDirective will be used to lay out
/// trailing comments and escaped newlines.
Change(bool CreateReplacement, const SourceRange &OriginalWhitespaceRange,
- unsigned IndentLevel, unsigned Spaces, unsigned StartOfTokenColumn,
+ unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, tok::TokenKind Kind,
bool ContinuesPPDirective);
@@ -128,7 +134,10 @@
// The number of spaces in front of the token or broken part of the token.
// This will be adapted when aligning tokens.
- unsigned Spaces;
+ // Can be negative to retain information about the initial relative offset
+ // of the lines in a block comment. This is used when aligning trailing
+ // comments. Uncompensated negative offset is truncated to 0.
+ int Spaces;
// \c IsTrailingComment, \c TokenLength, \c PreviousEndOfTokenColumn and
// \c EscapedNewlineColumn will be calculated in
@@ -137,6 +146,17 @@
unsigned TokenLength;
unsigned PreviousEndOfTokenColumn;
unsigned EscapedNewlineColumn;
+
+ // These fields are used to retain correct relative line indentation in a
+ // block comment when aligning trailing comments.
+ //
+ // If this Change represents a continuation of a block comment,
+ // \c StartOfBlockComment is pointer to the first Change in the block
+ // comment. \c IndentationOffset is a relative column offset to this
+ // change, so that the correct column can be reconstructed at the end of
+ // the alignment process.
+ const Change *StartOfBlockComment;
+ int IndentationOffset;
};
/// \brief Calculate \c IsTrailingComment, \c TokenLength for the last tokens
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index f90c0a9..54a6d47 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -36,7 +36,7 @@
typedef RecursiveASTVisitor<ASTPrinter> base;
public:
- ASTPrinter(raw_ostream *Out = NULL, bool Dump = false,
+ ASTPrinter(raw_ostream *Out = nullptr, bool Dump = false,
StringRef FilterString = "", bool DumpLookups = false)
: Out(Out ? *Out : llvm::outs()), Dump(Dump),
FilterString(FilterString), DumpLookups(DumpLookups) {}
@@ -53,7 +53,7 @@
bool shouldWalkTypesOfTypeLocs() const { return false; }
bool TraverseDecl(Decl *D) {
- if (D != NULL && filterMatches(D)) {
+ if (D && filterMatches(D)) {
bool ShowColors = Out.has_colors();
if (ShowColors)
Out.changeColor(raw_ostream::BLUE);
@@ -98,7 +98,7 @@
class ASTDeclNodeLister : public ASTConsumer,
public RecursiveASTVisitor<ASTDeclNodeLister> {
public:
- ASTDeclNodeLister(raw_ostream *Out = NULL)
+ ASTDeclNodeLister(raw_ostream *Out = nullptr)
: Out(Out ? *Out : llvm::outs()) {}
void HandleTranslationUnit(ASTContext &Context) override {
@@ -124,11 +124,11 @@
}
ASTConsumer *clang::CreateASTDumper(StringRef FilterString, bool DumpLookups) {
- return new ASTPrinter(0, /*Dump=*/ true, FilterString, DumpLookups);
+ return new ASTPrinter(nullptr, /*Dump=*/true, FilterString, DumpLookups);
}
ASTConsumer *clang::CreateASTDeclNodeLister() {
- return new ASTDeclNodeLister(0);
+ return new ASTDeclNodeLister(nullptr);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index c4f7596..49487d9 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -214,14 +214,14 @@
static std::atomic<unsigned> ActiveASTUnitObjects;
ASTUnit::ASTUnit(bool _MainFileIsAST)
- : Reader(0), HadModuleLoaderFatalFailure(false),
+ : Reader(nullptr), HadModuleLoaderFatalFailure(false),
OnlyLocalDecls(false), CaptureDiagnostics(false),
MainFileIsAST(_MainFileIsAST),
TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
OwnsRemappedFileBuffers(true),
NumStoredDiagnosticsFromDriver(0),
- PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
- NumWarningsInPreamble(0),
+ PreambleRebuildCounter(0), SavedMainFileBuffer(nullptr),
+ PreambleBuffer(nullptr), NumWarningsInPreamble(0),
ShouldCacheCodeCompletionResults(false),
IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
CompletionCacheTopLevelHashValue(0),
@@ -493,7 +493,7 @@
void ASTUnit::ClearCachedCompletionResults() {
CachedCompletionResults.clear();
CachedCompletionTypes.clear();
- CachedCompletionAllocator = 0;
+ CachedCompletionAllocator = nullptr;
}
namespace {
@@ -582,10 +582,10 @@
public:
explicit StoredDiagnosticConsumer(
SmallVectorImpl<StoredDiagnostic> &StoredDiags)
- : StoredDiags(StoredDiags), SourceMgr(0) { }
+ : StoredDiags(StoredDiags), SourceMgr(nullptr) {}
void BeginSourceFile(const LangOptions &LangOpts,
- const Preprocessor *PP = 0) override {
+ const Preprocessor *PP = nullptr) override {
if (PP)
SourceMgr = &PP->getSourceManager();
}
@@ -604,9 +604,9 @@
public:
CaptureDroppedDiagnostics(bool RequestCapture, DiagnosticsEngine &Diags,
SmallVectorImpl<StoredDiagnostic> &StoredDiags)
- : Diags(Diags), Client(StoredDiags), PreviousClient(0)
+ : Diags(Diags), Client(StoredDiags), PreviousClient(nullptr)
{
- if (RequestCapture || Diags.getClient() == 0) {
+ if (RequestCapture || Diags.getClient() == nullptr) {
PreviousClient = Diags.takeClient();
Diags.setClient(&Client);
}
@@ -637,13 +637,13 @@
ASTMutationListener *ASTUnit::getASTMutationListener() {
if (WriterData)
return &WriterData->Writer;
- return 0;
+ return nullptr;
}
ASTDeserializationListener *ASTUnit::getDeserializationListener() {
if (WriterData)
return &WriterData->Writer;
- return 0;
+ return nullptr;
}
llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename,
@@ -659,7 +659,7 @@
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
- DiagnosticConsumer *Client = 0;
+ DiagnosticConsumer *Client = nullptr;
if (CaptureDiagnostics)
Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics);
Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions(),
@@ -687,23 +687,24 @@
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
DiagCleanup(Diags.getPtr());
- ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
+ ConfigureDiags(Diags, nullptr, nullptr, *AST, CaptureDiagnostics);
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->Diagnostics = Diags;
- AST->FileMgr = new FileManager(FileSystemOpts);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
+ AST->FileMgr = new FileManager(FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
AST->getFileManager(),
UserFilesAreVolatile);
AST->HSOpts = new HeaderSearchOptions();
-
+
AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,
AST->getSourceManager(),
AST->getDiagnostics(),
AST->ASTFileLangOpts,
- /*Target=*/0));
+ /*Target=*/nullptr));
PreprocessorOptions *PPOpts = new PreprocessorOptions();
@@ -715,23 +716,16 @@
HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
unsigned Counter;
- AST->PP = new Preprocessor(PPOpts,
- AST->getDiagnostics(), AST->ASTFileLangOpts,
- /*Target=*/0, AST->getSourceManager(), HeaderInfo,
- *AST,
- /*IILookup=*/0,
- /*OwnsHeaderSearch=*/false,
- /*DelayInitialization=*/true);
+ AST->PP =
+ new Preprocessor(PPOpts, AST->getDiagnostics(), AST->ASTFileLangOpts,
+ AST->getSourceManager(), HeaderInfo, *AST,
+ /*IILookup=*/nullptr,
+ /*OwnsHeaderSearch=*/false);
Preprocessor &PP = *AST->PP;
- AST->Ctx = new ASTContext(AST->ASTFileLangOpts,
- AST->getSourceManager(),
- /*Target=*/0,
- PP.getIdentifierTable(),
- PP.getSelectorTable(),
- PP.getBuiltinInfo(),
- /* size_reserve = */0,
- /*DelayInitialization=*/true);
+ AST->Ctx = new ASTContext(AST->ASTFileLangOpts, AST->getSourceManager(),
+ PP.getIdentifierTable(), PP.getSelectorTable(),
+ PP.getBuiltinInfo());
ASTContext &Context = *AST->Ctx;
bool disableValid = false;
@@ -759,7 +753,7 @@
case ASTReader::ConfigurationMismatch:
case ASTReader::HadErrors:
AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
- return NULL;
+ return nullptr;
}
AST->OriginalSourceFile = AST->Reader->getOriginalSourceFile();
@@ -951,7 +945,7 @@
PrecompilePreambleConsumer(ASTUnit &Unit, PrecompilePreambleAction *Action,
const Preprocessor &PP, StringRef isysroot,
raw_ostream *Out)
- : PCHGenerator(PP, "", 0, isysroot, Out, /*AllowASTWithErrors=*/true),
+ : PCHGenerator(PP, "", nullptr, isysroot, Out, /*AllowASTWithErrors=*/true),
Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action) {
Hash = 0;
}
@@ -997,10 +991,10 @@
StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = 0;
+ raw_ostream *OS = nullptr;
if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
OutputFile, OS))
- return 0;
+ return nullptr;
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
@@ -1047,8 +1041,8 @@
/// contain any translation-unit information, false otherwise.
bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
delete SavedMainFileBuffer;
- SavedMainFileBuffer = 0;
-
+ SavedMainFileBuffer = nullptr;
+
if (!Invocation) {
delete OverrideMainBuffer;
return true;
@@ -1093,17 +1087,16 @@
"IR inputs not support here!");
// Configure the various subsystems.
- // FIXME: Should we retain the previous file manager?
LangOpts = &Clang->getLangOpts();
FileSystemOpts = Clang->getFileSystemOpts();
- FileMgr = new FileManager(FileSystemOpts);
+ // Re-use the existing FileManager
SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
UserFilesAreVolatile);
TheSema.reset();
- Ctx = 0;
- PP = 0;
- Reader = 0;
-
+ Ctx = nullptr;
+ PP = nullptr;
+ Reader = nullptr;
+
// Clear out old caches and data.
TopLevelDecls.clear();
clearFileLevelDecls();
@@ -1173,7 +1166,7 @@
// Remove the overridden buffer we used for the preamble.
if (OverrideMainBuffer) {
delete OverrideMainBuffer;
- SavedMainFileBuffer = 0;
+ SavedMainFileBuffer = nullptr;
}
// Keep the ownership of the data in the ASTUnit because the client may
@@ -1213,7 +1206,7 @@
// Try to determine if the main file has been remapped, either from the
// command line (to another file) or directly through the compiler invocation
// (to a memory buffer).
- llvm::MemoryBuffer *Buffer = 0;
+ llvm::MemoryBuffer *Buffer = nullptr;
std::string MainFilePath(FrontendOpts.Inputs[0].getFile());
llvm::sys::fs::UniqueID MainFileID;
if (!llvm::sys::fs::getUniqueID(MainFilePath, MainFileID)) {
@@ -1235,8 +1228,7 @@
Buffer = getBufferForFile(M->second);
if (!Buffer)
- return std::make_pair((llvm::MemoryBuffer*)0,
- std::make_pair(0, true));
+ return std::make_pair(nullptr, std::make_pair(0, true));
CreatedBuffer = true;
}
}
@@ -1269,8 +1261,8 @@
if (!Buffer) {
Buffer = getBufferForFile(FrontendOpts.Inputs[0].getFile());
if (!Buffer)
- return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
-
+ return std::make_pair(nullptr, std::make_pair(0, true));
+
CreatedBuffer = true;
}
@@ -1404,7 +1396,7 @@
// The next time we actually see a preamble, precompile it.
PreambleRebuildCounter = 1;
- return 0;
+ return nullptr;
}
if (!Preamble.empty()) {
@@ -1494,7 +1486,7 @@
// If we aren't allowed to rebuild the precompiled preamble, just
// return now.
if (!AllowRebuild)
- return 0;
+ return nullptr;
// We can't reuse the previously-computed preamble. Build a new one.
Preamble.clear();
@@ -1504,7 +1496,7 @@
} else if (!AllowRebuild) {
// We aren't allowed to rebuild the precompiled preamble; just
// return now.
- return 0;
+ return nullptr;
}
// If the preamble rebuild counter > 1, it's because we previously
@@ -1512,7 +1504,7 @@
// again. Decrement the counter and return a failure.
if (PreambleRebuildCounter > 1) {
--PreambleRebuildCounter;
- return 0;
+ return nullptr;
}
// Create a temporary file for the precompiled preamble. In rare
@@ -1521,7 +1513,7 @@
if (PreamblePCHPath.empty()) {
// Try again next time.
PreambleRebuildCounter = 1;
- return 0;
+ return nullptr;
}
// We did not previously compute a preamble, or it can't be reused anyway.
@@ -1575,7 +1567,7 @@
PreambleRebuildCounter = DefaultPreambleRebuildInterval;
PreprocessorOpts.eraseRemappedFile(
PreprocessorOpts.remapped_file_buffer_end() - 1);
- return 0;
+ return nullptr;
}
// Inform the target of the language options.
@@ -1598,9 +1590,14 @@
TopLevelDecls.clear();
TopLevelDeclsInPreamble.clear();
PreambleDiagnostics.clear();
-
+
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(Clang->getInvocation(), getDiagnostics());
+ if (!VFS)
+ return nullptr;
+
// Create a file manager object to provide access to and cache the filesystem.
- Clang->setFileManager(new FileManager(Clang->getFileSystemOpts()));
+ Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
// Create the source manager.
Clang->setSourceManager(new SourceManager(getDiagnostics(),
@@ -1614,7 +1611,7 @@
PreambleRebuildCounter = DefaultPreambleRebuildInterval;
PreprocessorOpts.eraseRemappedFile(
PreprocessorOpts.remapped_file_buffer_end() - 1);
- return 0;
+ return nullptr;
}
Act->Execute();
@@ -1643,7 +1640,7 @@
PreambleRebuildCounter = DefaultPreambleRebuildInterval;
PreprocessorOpts.eraseRemappedFile(
PreprocessorOpts.remapped_file_buffer_end() - 1);
- return 0;
+ return nullptr;
}
// Keep track of the preamble we precompiled.
@@ -1709,14 +1706,20 @@
}
void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
- // Steal the created target, context, and preprocessor.
+ // Steal the created target, context, and preprocessor if they have been
+ // created.
+ assert(CI.hasInvocation() && "missing invocation");
+ LangOpts = CI.getInvocation().getLangOpts();
TheSema.reset(CI.takeSema());
Consumer.reset(CI.takeASTConsumer());
- Ctx = &CI.getASTContext();
- PP = &CI.getPreprocessor();
- CI.setSourceManager(0);
- CI.setFileManager(0);
- Target = &CI.getTarget();
+ if (CI.hasASTContext())
+ Ctx = &CI.getASTContext();
+ if (CI.hasPreprocessor())
+ PP = &CI.getPreprocessor();
+ CI.setSourceManager(nullptr);
+ CI.setFileManager(nullptr);
+ if (CI.hasTarget())
+ Target = &CI.getTarget();
Reader = CI.getModuleManager();
HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();
}
@@ -1754,11 +1757,15 @@
bool UserFilesAreVolatile) {
std::unique_ptr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
- ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
+ ConfigureDiags(Diags, nullptr, nullptr, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
AST->Invocation = CI;
AST->FileSystemOpts = CI->getFileSystemOpts();
- AST->FileMgr = new FileManager(AST->FileSystemOpts);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(*CI, *Diags);
+ if (!VFS)
+ return nullptr;
+ AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
UserFilesAreVolatile);
@@ -1781,6 +1788,8 @@
// Create the AST unit.
OwnAST.reset(create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile));
AST = OwnAST.get();
+ if (!AST)
+ return nullptr;
}
if (!ResourceFilesPath.empty()) {
@@ -1826,7 +1835,7 @@
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
&Clang->getTargetOpts()));
if (!Clang->hasTarget())
- return 0;
+ return nullptr;
// Inform the target of the language options.
//
@@ -1843,10 +1852,10 @@
// Configure the various subsystems.
AST->TheSema.reset();
- AST->Ctx = 0;
- AST->PP = 0;
- AST->Reader = 0;
-
+ AST->Ctx = nullptr;
+ AST->PP = nullptr;
+ AST->Reader = nullptr;
+
// Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(&AST->getFileManager());
@@ -1870,7 +1879,7 @@
if (OwnAST && ErrAST)
ErrAST->swap(OwnAST);
- return 0;
+ return nullptr;
}
if (Persistent && !TrackerAct) {
@@ -1888,7 +1897,7 @@
if (OwnAST && ErrAST)
ErrAST->swap(OwnAST);
- return 0;
+ return nullptr;
}
// Steal the created target, context, and preprocessor.
@@ -1911,7 +1920,7 @@
Invocation->getFrontendOpts().DisableFree = false;
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
- llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ llvm::MemoryBuffer *OverrideMainBuffer = nullptr;
if (PrecompilePreamble) {
PreambleRebuildCounter = 2;
OverrideMainBuffer
@@ -1928,19 +1937,14 @@
return Parse(OverrideMainBuffer);
}
-ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- bool OnlyLocalDecls,
- bool CaptureDiagnostics,
- bool PrecompilePreamble,
- TranslationUnitKind TUKind,
- bool CacheCodeCompletionResults,
- bool IncludeBriefCommentsInCodeCompletion,
- bool UserFilesAreVolatile) {
+std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
+ CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble,
+ TranslationUnitKind TUKind, bool CacheCodeCompletionResults,
+ bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile) {
// Create the AST unit.
- std::unique_ptr<ASTUnit> AST;
- AST.reset(new ASTUnit(false));
- ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
+ std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
+ ConfigureDiags(Diags, nullptr, nullptr, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
@@ -1950,7 +1954,11 @@
= IncludeBriefCommentsInCodeCompletion;
AST->Invocation = CI;
AST->FileSystemOpts = CI->getFileSystemOpts();
- AST->FileMgr = new FileManager(AST->FileSystemOpts);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(*CI, *Diags);
+ if (!VFS)
+ return nullptr;
+ AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
// Recover resources if we crash before exiting this method.
@@ -1960,8 +1968,9 @@
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
DiagCleanup(Diags.getPtr());
- return AST->LoadFromCompilerInvocation(PrecompilePreamble) ? 0
- : AST.release();
+ if (AST->LoadFromCompilerInvocation(PrecompilePreamble))
+ return nullptr;
+ return AST;
}
ASTUnit *ASTUnit::LoadFromCommandLine(
@@ -1993,7 +2002,7 @@
llvm::makeArrayRef(ArgBegin, ArgEnd),
Diags);
if (!CI)
- return 0;
+ return nullptr;
}
// Override any files that need remapping
@@ -2015,9 +2024,13 @@
AST.reset(new ASTUnit(false));
ConfigureDiags(Diags, ArgBegin, ArgEnd, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
- Diags = 0; // Zero out now to ease cleanup during crash recovery.
+ Diags = nullptr; // Zero out now to ease cleanup during crash recovery.
AST->FileSystemOpts = CI->getFileSystemOpts();
- AST->FileMgr = new FileManager(AST->FileSystemOpts);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(*CI, *Diags);
+ if (!VFS)
+ return nullptr;
+ AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->TUKind = TUKind;
@@ -2030,8 +2043,8 @@
AST->Invocation = CI;
if (ForSerialization)
AST->WriterData.reset(new ASTWriterData());
- CI = 0; // Zero out now to ease cleanup during crash recovery.
-
+ CI = nullptr; // Zero out now to ease cleanup during crash recovery.
+
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get());
@@ -2043,7 +2056,7 @@
AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);
ErrAST->swap(AST);
}
- return 0;
+ return nullptr;
}
return AST.release();
@@ -2075,7 +2088,7 @@
// If we have a preamble file lying around, or if we might try to
// build a precompiled preamble, do so now.
- llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ llvm::MemoryBuffer *OverrideMainBuffer = nullptr;
if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0)
OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
@@ -2399,7 +2412,7 @@
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
&Clang->getTargetOpts()));
if (!Clang->hasTarget()) {
- Clang->setInvocation(0);
+ Clang->setInvocation(nullptr);
return;
}
@@ -2440,7 +2453,7 @@
// the use of the precompiled preamble if we're if the completion
// point is within the main file, after the end of the precompiled
// preamble.
- llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ llvm::MemoryBuffer *OverrideMainBuffer = nullptr;
if (!getPreambleFile(this).empty()) {
std::string CompleteFilePath(File);
llvm::sys::fs::UniqueID CompleteFileID;
@@ -2522,7 +2535,7 @@
Sema &S,
bool hasErrors,
raw_ostream &OS) {
- Writer.WriteAST(S, std::string(), 0, "", hasErrors);
+ Writer.WriteAST(S, std::string(), nullptr, "", hasErrors);
// Write the generated bitstream to "Out".
if (!Buffer.empty())
@@ -2663,7 +2676,8 @@
LocDeclsTy::iterator BeginIt =
std::lower_bound(LocDecls.begin(), LocDecls.end(),
- std::make_pair(Offset, (Decl *)0), llvm::less_first());
+ std::make_pair(Offset, (Decl *)nullptr),
+ llvm::less_first());
if (BeginIt != LocDecls.begin())
--BeginIt;
@@ -2676,7 +2690,7 @@
LocDeclsTy::iterator EndIt = std::upper_bound(
LocDecls.begin(), LocDecls.end(),
- std::make_pair(Offset + Length, (Decl *)0), llvm::less_first());
+ std::make_pair(Offset + Length, (Decl *)nullptr), llvm::less_first());
if (EndIt != LocDecls.end())
++EndIt;
@@ -2826,7 +2840,7 @@
namespace {
struct PCHLocatorInfo {
serialization::ModuleFile *Mod;
- PCHLocatorInfo() : Mod(0) {}
+ PCHLocatorInfo() : Mod(nullptr) {}
};
}
@@ -2849,14 +2863,14 @@
const FileEntry *ASTUnit::getPCHFile() {
if (!Reader)
- return 0;
+ return nullptr;
PCHLocatorInfo Info;
Reader->getModuleManager().visit(PCHLocator, &Info);
if (Info.Mod)
return Info.Mod->File;
- return 0;
+ return nullptr;
}
bool ASTUnit::isModuleFile() {
diff --git a/lib/Frontend/Android.mk b/lib/Frontend/Android.mk
index c3c42c3..ec6489a 100644
--- a/lib/Frontend/Android.mk
+++ b/lib/Frontend/Android.mk
@@ -50,7 +50,6 @@
TextDiagnostic.cpp \
TextDiagnosticBuffer.cpp \
TextDiagnosticPrinter.cpp \
- Warnings.cpp \
VerifyDiagnosticConsumer.cpp
LOCAL_SRC_FILES := $(clang_frontend_SRC_FILES)
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index f1c7897..b67e0ae 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -32,7 +32,6 @@
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
VerifyDiagnosticConsumer.cpp
- Warnings.cpp
DEPENDS
ClangDriverOptions
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index 2cb6582..d30196d 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -17,7 +17,6 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
@@ -26,6 +25,7 @@
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -35,12 +35,13 @@
#endif
using namespace clang;
-using namespace clang::io;
//===----------------------------------------------------------------------===//
// PTH-specific stuff.
//===----------------------------------------------------------------------===//
+typedef uint32_t Offset;
+
namespace {
class PTHEntry {
Offset TokenData, PPCondData;
@@ -62,13 +63,13 @@
FileData *Data;
public:
- PTHEntryKeyVariant(const FileEntry *fe) : FE(fe), Kind(IsFE), Data(0) {}
+ PTHEntryKeyVariant(const FileEntry *fe) : FE(fe), Kind(IsFE), Data(nullptr) {}
PTHEntryKeyVariant(FileData *Data, const char *path)
: Path(path), Kind(IsDE), Data(new FileData(*Data)) {}
explicit PTHEntryKeyVariant(const char *path)
- : Path(path), Kind(IsNoExist), Data(0) {}
+ : Path(path), Kind(IsNoExist), Data(nullptr) {}
bool isFile() const { return Kind == IsFE; }
@@ -116,7 +117,10 @@
typedef PTHEntry data_type;
typedef const PTHEntry& data_type_ref;
- static unsigned ComputeHash(PTHEntryKeyVariant V) {
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
+
+ static hash_value_type ComputeHash(PTHEntryKeyVariant V) {
return llvm::HashString(V.getString());
}
@@ -171,7 +175,7 @@
};
} // end anonymous namespace
-typedef OnDiskChainedHashTableGenerator<FileEntryPTHEntryInfo> PTHMap;
+typedef llvm::OnDiskChainedHashTableGenerator<FileEntryPTHEntryInfo> PTHMap;
namespace {
class PTHWriter {
@@ -287,8 +291,11 @@
PTHEntry PTHWriter::LexTokens(Lexer& L) {
// Pad 0's so that we emit tokens to a 4-byte alignment.
// This speed up reading them back in.
- Pad(Out, 4);
- Offset TokenOff = (Offset) Out.tell();
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+ uint32_t TokenOff = Out.tell();
+ for (uint64_t N = llvm::OffsetToAlignment(TokenOff, 4); N; --N, ++TokenOff)
+ LE.write<uint8_t>(0);
// Keep track of matching '#if' ... '#endif'.
typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
@@ -310,7 +317,7 @@
Token Tmp = Tok;
Tmp.setKind(tok::eod);
Tmp.clearFlag(Token::StartOfLine);
- Tmp.setIdentifierInfo(0);
+ Tmp.setIdentifierInfo(nullptr);
EmitToken(Tmp);
ParsingPreprocessorDirective = false;
}
@@ -595,7 +602,10 @@
typedef uint32_t data_type;
typedef data_type data_type_ref;
- static unsigned ComputeHash(PTHIdKey* key) {
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
+
+ static hash_value_type ComputeHash(PTHIdKey* key) {
return llvm::HashString(key->II->getName());
}
@@ -636,7 +646,7 @@
PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey));
// Create the hashtable.
- OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap;
+ llvm::OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap;
// Generate mapping from persistent IDs -> IdentifierInfo*.
for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) {
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index 6741160..6dc3fd4 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -25,11 +25,11 @@
using namespace clang;
-static ASTReader *createASTReader(CompilerInstance &CI,
- StringRef pchFile,
- SmallVectorImpl<llvm::MemoryBuffer *> &memBufs,
- SmallVectorImpl<std::string> &bufNames,
- ASTDeserializationListener *deserialListener = 0) {
+static ASTReader *
+createASTReader(CompilerInstance &CI, StringRef pchFile,
+ SmallVectorImpl<llvm::MemoryBuffer *> &memBufs,
+ SmallVectorImpl<std::string> &bufNames,
+ ASTDeserializationListener *deserialListener = nullptr) {
Preprocessor &PP = CI.getPreprocessor();
std::unique_ptr<ASTReader> Reader;
Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"",
@@ -54,7 +54,7 @@
case ASTReader::HadErrors:
break;
}
- return 0;
+ return nullptr;
}
ChainedIncludesSource::~ChainedIncludesSource() {
@@ -112,12 +112,12 @@
SmallVector<char, 256> serialAST;
llvm::raw_svector_ostream OS(serialAST);
std::unique_ptr<ASTConsumer> consumer;
- consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", 0,
+ consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", nullptr,
/*isysroot=*/"", &OS));
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
Clang->setASTConsumer(consumer.release());
- Clang->createSema(TU_Prefix, 0);
+ Clang->createSema(TU_Prefix, nullptr);
if (firstInclude) {
Preprocessor &PP = Clang->getPreprocessor();
@@ -142,13 +142,13 @@
Reader = createASTReader(*Clang, pchName, bufs, serialBufNames,
Clang->getASTConsumer().GetASTDeserializationListener());
if (!Reader)
- return 0;
+ return nullptr;
Clang->setModuleManager(Reader);
Clang->getASTContext().setExternalSource(Reader);
}
if (!Clang->InitializeSourceManager(InputFile))
- return 0;
+ return nullptr;
ParseAST(Clang->getSema());
OS.flush();
@@ -165,7 +165,7 @@
IntrusiveRefCntPtr<ASTReader> Reader;
Reader = createASTReader(CI, pchName, serialBufs, serialBufNames);
if (!Reader)
- return 0;
+ return nullptr;
source->FinalReader = Reader;
return source;
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index ce47674..c65d34b 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -31,6 +31,7 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/GlobalModuleIndex.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Config/config.h"
#include "llvm/Support/CrashRecoveryContext.h"
@@ -49,9 +50,11 @@
using namespace clang;
-CompilerInstance::CompilerInstance()
- : Invocation(new CompilerInvocation()), ModuleManager(0),
- BuildGlobalModuleIndex(false), ModuleBuildFailed(false) {
+CompilerInstance::CompilerInstance(bool BuildingModule)
+ : ModuleLoader(BuildingModule),
+ Invocation(new CompilerInvocation()), ModuleManager(nullptr),
+ BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false),
+ ModuleBuildFailed(false) {
}
CompilerInstance::~CompilerInstance() {
@@ -226,7 +229,7 @@
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
// Create a PTH manager if we are using some form of a token cache.
- PTHManager *PTHMgr = 0;
+ PTHManager *PTHMgr = nullptr;
if (!PPOpts.TokenCache.empty())
PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
@@ -236,13 +239,10 @@
getDiagnostics(),
getLangOpts(),
&getTarget());
- PP = new Preprocessor(&getPreprocessorOpts(),
- getDiagnostics(), getLangOpts(), &getTarget(),
+ PP = new Preprocessor(&getPreprocessorOpts(), getDiagnostics(), getLangOpts(),
getSourceManager(), *HeaderInfo, *this, PTHMgr,
- /*OwnsHeaderSearch=*/true,
- /*DelayInitialization=*/false,
- /*IncrProcessing=*/false,
- TUKind);
+ /*OwnsHeaderSearch=*/true, TUKind);
+ PP->Initialize(getTarget());
// Note that this is different then passing PTHMgr to Preprocessor's ctor.
// That argument is used as the IdentifierInfoLookup argument to
@@ -300,40 +300,32 @@
void CompilerInstance::createASTContext() {
Preprocessor &PP = getPreprocessor();
Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
- &getTarget(), PP.getIdentifierTable(),
- PP.getSelectorTable(), PP.getBuiltinInfo(),
- /*size_reserve=*/ 0);
+ PP.getIdentifierTable(), PP.getSelectorTable(),
+ PP.getBuiltinInfo());
+ Context->InitBuiltinTypes(getTarget());
}
// ExternalASTSource
-void CompilerInstance::createPCHExternalASTSource(StringRef Path,
- bool DisablePCHValidation,
- bool AllowPCHWithCompilerErrors,
- void *DeserializationListener){
+void CompilerInstance::createPCHExternalASTSource(
+ StringRef Path, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors,
+ void *DeserializationListener, bool OwnDeserializationListener) {
IntrusiveRefCntPtr<ExternalASTSource> Source;
bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
- Source = createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
- DisablePCHValidation,
- AllowPCHWithCompilerErrors,
- getPreprocessor(), getASTContext(),
- DeserializationListener,
- Preamble,
- getFrontendOpts().UseGlobalModuleIndex);
+ Source = createPCHExternalASTSource(
+ Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation,
+ AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(),
+ DeserializationListener, OwnDeserializationListener, Preamble,
+ getFrontendOpts().UseGlobalModuleIndex);
ModuleManager = static_cast<ASTReader*>(Source.getPtr());
getASTContext().setExternalSource(Source);
}
-ExternalASTSource *
-CompilerInstance::createPCHExternalASTSource(StringRef Path,
- const std::string &Sysroot,
- bool DisablePCHValidation,
- bool AllowPCHWithCompilerErrors,
- Preprocessor &PP,
- ASTContext &Context,
- void *DeserializationListener,
- bool Preamble,
- bool UseGlobalModuleIndex) {
+ExternalASTSource *CompilerInstance::createPCHExternalASTSource(
+ StringRef Path, const std::string &Sysroot, bool DisablePCHValidation,
+ bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
+ void *DeserializationListener, bool OwnDeserializationListener,
+ bool Preamble, bool UseGlobalModuleIndex) {
HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
std::unique_ptr<ASTReader> Reader;
@@ -346,7 +338,8 @@
UseGlobalModuleIndex));
Reader->setDeserializationListener(
- static_cast<ASTDeserializationListener *>(DeserializationListener));
+ static_cast<ASTDeserializationListener *>(DeserializationListener),
+ /*TakeOwnership=*/OwnDeserializationListener);
switch (Reader->ReadAST(Path,
Preamble ? serialization::MK_Preamble
: serialization::MK_PCH,
@@ -371,7 +364,7 @@
break;
}
- return 0;
+ return nullptr;
}
// Code Completion
@@ -406,14 +399,14 @@
return;
} else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
Loc.Line, Loc.Column)) {
- setCodeCompletionConsumer(0);
+ setCodeCompletionConsumer(nullptr);
return;
}
if (CompletionConsumer->isOutputBinary() &&
llvm::sys::ChangeStdoutToBinary()) {
getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
- setCodeCompletionConsumer(0);
+ setCodeCompletionConsumer(nullptr);
}
}
@@ -429,7 +422,7 @@
const CodeCompleteOptions &Opts,
raw_ostream &OS) {
if (EnableCodeCompletion(PP, Filename, Line, Column))
- return 0;
+ return nullptr;
// Set up the creation routine for code-completion.
return new PrintingCodeCompleteConsumer(Opts, OS);
@@ -503,7 +496,7 @@
if (!OS) {
getDiagnostics().Report(diag::err_fe_unable_to_open_output)
<< OutputPath << Error;
- return 0;
+ return nullptr;
}
// Add the output file -- but don't try to remove "-", since this means we are
@@ -553,7 +546,7 @@
if (llvm::sys::fs::exists(Status)) {
// Fail early if we can't write to the final destination.
if (!llvm::sys::fs::can_write(OutputPath))
- return 0;
+ return nullptr;
// Don't use a temporary if the output is a special file. This handles
// things like '-o /dev/null'
@@ -596,7 +589,7 @@
OSFile.c_str(), Error,
(Binary ? llvm::sys::fs::F_None : llvm::sys::fs::F_Text)));
if (!Error.empty())
- return 0;
+ return nullptr;
}
// Make sure the out stream file gets removed if we crash.
@@ -628,7 +621,7 @@
Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
if (Input.isBuffer()) {
- SourceMgr.createMainFileIDForMemBuffer(Input.getBuffer(), Kind);
+ SourceMgr.setMainFileID(SourceMgr.createFileID(Input.getBuffer(), Kind));
assert(!SourceMgr.getMainFileID().isInvalid() &&
"Couldn't establish MainFileID!");
return true;
@@ -662,7 +655,8 @@
}
}
- SourceMgr.createMainFileID(File, Kind);
+ SourceMgr.setMainFileID(
+ SourceMgr.createFileID(File, SourceLocation(), Kind));
} else {
std::unique_ptr<llvm::MemoryBuffer> SB;
if (llvm::error_code ec = llvm::MemoryBuffer::getSTDIN(SB)) {
@@ -671,7 +665,8 @@
}
const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
SB->getBufferSize(), 0);
- SourceMgr.createMainFileID(File, Kind);
+ SourceMgr.setMainFileID(
+ SourceMgr.createFileID(File, SourceLocation(), Kind));
SourceMgr.overrideFileContents(File, SB.release());
}
@@ -770,31 +765,10 @@
/// \brief Compile a module file for the given module, using the options
/// provided by the importing compiler instance.
-static void compileModule(CompilerInstance &ImportingInstance,
+static void compileModuleImpl(CompilerInstance &ImportingInstance,
SourceLocation ImportLoc,
Module *Module,
StringRef ModuleFileName) {
- // FIXME: have LockFileManager return an error_code so that we can
- // avoid the mkdir when the directory already exists.
- StringRef Dir = llvm::sys::path::parent_path(ModuleFileName);
- llvm::sys::fs::create_directories(Dir);
-
- llvm::LockFileManager Locked(ModuleFileName);
- switch (Locked) {
- case llvm::LockFileManager::LFS_Error:
- return;
-
- case llvm::LockFileManager::LFS_Owned:
- // We're responsible for building the module ourselves. Do so below.
- break;
-
- case llvm::LockFileManager::LFS_Shared:
- // Someone else is responsible for building the module. Wait for them to
- // finish.
- Locked.waitForUnlock();
- return;
- }
-
ModuleMap &ModMap
= ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
@@ -851,7 +825,7 @@
// Construct a compiler instance that will be used to actually create the
// module.
- CompilerInstance Instance;
+ CompilerInstance Instance(/*BuildingModule=*/true);
Instance.setInvocation(&*Invocation);
Instance.createDiagnostics(new ForwardingDiagnosticConsumer(
@@ -891,8 +865,9 @@
SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer);
}
- // Construct a module-generating action.
- GenerateModuleAction CreateModuleAction(Module->IsSystem);
+ // Construct a module-generating action. Passing through Module->ModuleMap is
+ // safe because the FileManager is shared between the compiler instances.
+ GenerateModuleAction CreateModuleAction(Module->ModuleMap, Module->IsSystem);
// Execute the action to actually build the module in-place. Use a separate
// thread so that we get a stack large enough.
@@ -914,6 +889,38 @@
}
}
+static void compileModule(CompilerInstance &ImportingInstance,
+ SourceLocation ImportLoc,
+ Module *Module,
+ StringRef ModuleFileName) {
+ // FIXME: have LockFileManager return an error_code so that we can
+ // avoid the mkdir when the directory already exists.
+ StringRef Dir = llvm::sys::path::parent_path(ModuleFileName);
+ llvm::sys::fs::create_directories(Dir);
+
+ while (1) {
+ llvm::LockFileManager Locked(ModuleFileName);
+ switch (Locked) {
+ case llvm::LockFileManager::LFS_Error:
+ return;
+
+ case llvm::LockFileManager::LFS_Owned:
+ // We're responsible for building the module ourselves. Do so below.
+ break;
+
+ case llvm::LockFileManager::LFS_Shared:
+ // Someone else is responsible for building the module. Wait for them to
+ // finish.
+ if (Locked.waitForUnlock() == llvm::LockFileManager::Res_OwnerDied)
+ continue; // try again to get the lock.
+ return;
+ }
+
+ return compileModuleImpl(ImportingInstance, ImportLoc, Module,
+ ModuleFileName);
+ }
+}
+
/// \brief Diagnose differences between the current definition of the given
/// configuration macro and the definition provided on the command line.
static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
@@ -1027,7 +1034,7 @@
// Check whether the time stamp is older than our pruning interval.
// If not, do nothing.
time_t TimeStampModTime = StatBuf.st_mtime;
- time_t CurrentTime = time(0);
+ time_t CurrentTime = time(nullptr);
if (CurrentTime - TimeStampModTime <= time_t(HSOpts.ModuleCachePruneInterval))
return;
@@ -1085,6 +1092,43 @@
}
}
+void CompilerInstance::createModuleManager() {
+ if (!ModuleManager) {
+ if (!hasASTContext())
+ createASTContext();
+
+ // If we're not recursively building a module, check whether we
+ // need to prune the module cache.
+ if (getSourceManager().getModuleBuildStack().empty() &&
+ getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
+ getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
+ pruneModuleCache(getHeaderSearchOpts());
+ }
+
+ HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
+ std::string Sysroot = HSOpts.Sysroot;
+ const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+ ModuleManager = new ASTReader(getPreprocessor(), *Context,
+ Sysroot.empty() ? "" : Sysroot.c_str(),
+ PPOpts.DisablePCHValidation,
+ /*AllowASTWithCompilerErrors=*/false,
+ /*AllowConfigurationMismatch=*/false,
+ HSOpts.ModulesValidateSystemHeaders,
+ getFrontendOpts().UseGlobalModuleIndex);
+ if (hasASTConsumer()) {
+ ModuleManager->setDeserializationListener(
+ getASTConsumer().GetASTDeserializationListener());
+ getASTContext().setASTMutationListener(
+ getASTConsumer().GetASTMutationListener());
+ }
+ getASTContext().setExternalSource(ModuleManager);
+ if (hasSema())
+ ModuleManager->InitializeSema(getSema());
+ if (hasASTConsumer())
+ ModuleManager->StartTranslationUnit(&getASTConsumer());
+ }
+}
+
ModuleLoadResult
CompilerInstance::loadModule(SourceLocation ImportLoc,
ModuleIdPath Path,
@@ -1105,7 +1149,7 @@
return LastModuleImportResult;
}
- clang::Module *Module = 0;
+ clang::Module *Module = nullptr;
// If we don't already have information on this module, load the module now.
llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known
@@ -1115,7 +1159,7 @@
Module = Known->second;
} else if (ModuleName == getLangOpts().CurrentModule) {
// This is the module we're building.
- Module = PP->getHeaderSearchInfo().getModuleMap().findModule(ModuleName);
+ Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
} else {
// Search for a module with the given name.
@@ -1128,43 +1172,12 @@
return ModuleLoadResult();
}
- std::string ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
+ std::string ModuleFileName =
+ PP->getHeaderSearchInfo().getModuleFileName(Module);
// If we don't already have an ASTReader, create one now.
- if (!ModuleManager) {
- if (!hasASTContext())
- createASTContext();
-
- // If we're not recursively building a module, check whether we
- // need to prune the module cache.
- if (getSourceManager().getModuleBuildStack().empty() &&
- getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
- getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
- pruneModuleCache(getHeaderSearchOpts());
- }
-
- HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
- std::string Sysroot = HSOpts.Sysroot;
- const PreprocessorOptions &PPOpts = getPreprocessorOpts();
- ModuleManager = new ASTReader(getPreprocessor(), *Context,
- Sysroot.empty() ? "" : Sysroot.c_str(),
- PPOpts.DisablePCHValidation,
- /*AllowASTWithCompilerErrors=*/false,
- /*AllowConfigurationMismatch=*/false,
- HSOpts.ModulesValidateSystemHeaders,
- getFrontendOpts().UseGlobalModuleIndex);
- if (hasASTConsumer()) {
- ModuleManager->setDeserializationListener(
- getASTConsumer().GetASTDeserializationListener());
- getASTContext().setASTMutationListener(
- getASTConsumer().GetASTMutationListener());
- }
- getASTContext().setExternalSource(ModuleManager);
- if (hasSema())
- ModuleManager->InitializeSema(getSema());
- if (hasASTConsumer())
- ModuleManager->StartTranslationUnit(&getASTConsumer());
- }
+ if (!ModuleManager)
+ createModuleManager();
if (TheDependencyFileGenerator)
TheDependencyFileGenerator->AttachToASTReader(*ModuleManager);
@@ -1201,6 +1214,9 @@
return ModuleLoadResult();
}
+ getDiagnostics().Report(ImportLoc, diag::remark_module_build)
+ << ModuleName << ModuleFileName;
+
// Check whether we have already attempted to build this module (but
// failed).
if (getPreprocessorOpts().FailedModules &&
@@ -1231,7 +1247,7 @@
if (getPreprocessorOpts().FailedModules)
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
- KnownModules[Path[0].first] = 0;
+ KnownModules[Path[0].first] = nullptr;
ModuleBuildFailed = true;
return ModuleLoadResult();
}
@@ -1246,13 +1262,13 @@
ModuleLoader::HadFatalFailure = true;
// FIXME: The ASTReader will already have complained, but can we showhorn
// that diagnostic information into a more useful form?
- KnownModules[Path[0].first] = 0;
+ KnownModules[Path[0].first] = nullptr;
return ModuleLoadResult();
case ASTReader::Failure:
ModuleLoader::HadFatalFailure = true;
// Already complained, but note now that we failed.
- KnownModules[Path[0].first] = 0;
+ KnownModules[Path[0].first] = nullptr;
ModuleBuildFailed = true;
return ModuleLoadResult();
}
@@ -1332,8 +1348,8 @@
getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule)
<< Module->getFullModuleName()
<< SourceRange(Path.front().second, Path.back().second);
-
- return ModuleLoadResult(0, true);
+
+ return ModuleLoadResult(nullptr, true);
}
// Check whether this module is available.
@@ -1391,3 +1407,84 @@
ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc, Complain);
}
+GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
+ SourceLocation TriggerLoc) {
+ if (!ModuleManager)
+ createModuleManager();
+ // Can't do anything if we don't have the module manager.
+ if (!ModuleManager)
+ return nullptr;
+ // Get an existing global index. This loads it if not already
+ // loaded.
+ ModuleManager->loadGlobalIndex();
+ GlobalModuleIndex *GlobalIndex = ModuleManager->getGlobalIndex();
+ // If the global index doesn't exist, create it.
+ if (!GlobalIndex && shouldBuildGlobalModuleIndex() && hasFileManager() &&
+ hasPreprocessor()) {
+ llvm::sys::fs::create_directories(
+ getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+ GlobalModuleIndex::writeIndex(
+ getFileManager(),
+ getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+ ModuleManager->resetForReload();
+ ModuleManager->loadGlobalIndex();
+ GlobalIndex = ModuleManager->getGlobalIndex();
+ }
+ // For finding modules needing to be imported for fixit messages,
+ // we need to make the global index cover all modules, so we do that here.
+ if (!HaveFullGlobalModuleIndex && GlobalIndex && !buildingModule()) {
+ ModuleMap &MMap = getPreprocessor().getHeaderSearchInfo().getModuleMap();
+ bool RecreateIndex = false;
+ for (ModuleMap::module_iterator I = MMap.module_begin(),
+ E = MMap.module_end(); I != E; ++I) {
+ Module *TheModule = I->second;
+ const FileEntry *Entry = TheModule->getASTFile();
+ if (!Entry) {
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
+ Path.push_back(std::make_pair(
+ getPreprocessor().getIdentifierInfo(TheModule->Name), TriggerLoc));
+ std::reverse(Path.begin(), Path.end());
+ // Load a module as hidden. This also adds it to the global index.
+ loadModule(TheModule->DefinitionLoc, Path,
+ Module::Hidden, false);
+ RecreateIndex = true;
+ }
+ }
+ if (RecreateIndex) {
+ GlobalModuleIndex::writeIndex(
+ getFileManager(),
+ getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+ ModuleManager->resetForReload();
+ ModuleManager->loadGlobalIndex();
+ GlobalIndex = ModuleManager->getGlobalIndex();
+ }
+ HaveFullGlobalModuleIndex = true;
+ }
+ return GlobalIndex;
+}
+
+// Check global module index for missing imports.
+bool
+CompilerInstance::lookupMissingImports(StringRef Name,
+ SourceLocation TriggerLoc) {
+ // Look for the symbol in non-imported modules, but only if an error
+ // actually occurred.
+ if (!buildingModule()) {
+ // Load global module index, or retrieve a previously loaded one.
+ GlobalModuleIndex *GlobalIndex = loadGlobalModuleIndex(
+ TriggerLoc);
+
+ // Only if we have a global index.
+ if (GlobalIndex) {
+ GlobalModuleIndex::HitSet FoundModules;
+
+ // Find the modules that reference the identifier.
+ // Note that this only finds top-level modules.
+ // We'll let diagnoseTypo find the actual declaration module.
+ if (GlobalIndex->lookupIdentifier(Name, FoundModules))
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index b9706e8..2ba9450 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -8,12 +8,12 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Util.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
@@ -27,6 +27,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -56,6 +57,8 @@
HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
+CompilerInvocationBase::~CompilerInvocationBase() {}
+
//===----------------------------------------------------------------------===//
// Deserialization (from args)
//===----------------------------------------------------------------------===//
@@ -295,6 +298,17 @@
Opts.ParseAllComments = Args.hasArg(OPT_fparse_all_comments);
}
+static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) {
+ if (Arg *A = Args.getLastArg(OPT_mcode_model)) {
+ StringRef Value = A->getValue();
+ if (Value == "small" || Value == "kernel" || Value == "medium" ||
+ Value == "large")
+ return Value;
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value;
+ }
+ return "default";
+}
+
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags,
const TargetOptions &TargetOpts) {
@@ -325,9 +339,10 @@
} else if (Args.hasArg(OPT_g_Flag) || Args.hasArg(OPT_gdwarf_2) ||
Args.hasArg(OPT_gdwarf_3) || Args.hasArg(OPT_gdwarf_4)) {
bool Default = false;
- // Until dtrace (via CTF) can deal with distributed debug info,
- // Darwin defaults to standalone/full debug info.
- if (llvm::Triple(TargetOpts.Triple).isOSDarwin())
+ // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
+ // Darwin and FreeBSD default to standalone/full debug info.
+ if (llvm::Triple(TargetOpts.Triple).isOSDarwin() ||
+ llvm::Triple(TargetOpts.Triple).isOSFreeBSD())
Default = true;
if (Args.hasFlag(OPT_fstandalone_debug, OPT_fno_standalone_debug, Default))
@@ -376,7 +391,7 @@
Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);
Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
- Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model);
+ Opts.CodeModel = getCodeModel(Args, Diags);
Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim);
Opts.DisableFree = Args.hasArg(OPT_disable_free);
@@ -399,7 +414,6 @@
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels);
- Opts.NoDwarf2CFIAsm = Args.hasArg(OPT_fno_dwarf2_cfi_asm);
Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm);
Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums);
@@ -520,6 +534,17 @@
Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib);
+ if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
+ StringRef Val = A->getValue();
+ std::string RegexError;
+ Opts.OptimizationRemarkPattern = std::make_shared<llvm::Regex>(Val);
+ if (!Opts.OptimizationRemarkPattern->isValid(RegexError)) {
+ Diags.Report(diag::err_drv_optimization_remark_pattern)
+ << RegexError << A->getAsString(Args);
+ Opts.OptimizationRemarkPattern.reset();
+ }
+ }
+
return Success;
}
@@ -1343,7 +1368,13 @@
Opts.Blocks = Args.hasArg(OPT_fblocks);
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
Opts.Modules = Args.hasArg(OPT_fmodules);
- Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse);
+ Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
+ Opts.ModulesDeclUse =
+ Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
+ Opts.ModulesSearchAll = Opts.Modules &&
+ !Args.hasArg(OPT_fno_modules_search_all) &&
+ Args.hasArg(OPT_fmodules_search_all);
+ Opts.ModulesErrorRecovery = !Args.hasArg(OPT_fno_modules_error_recovery);
Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
@@ -1803,7 +1834,7 @@
// Extend the signature with the target options.
code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU,
- TargetOpts->ABI, TargetOpts->LinkerVersion);
+ TargetOpts->ABI);
for (unsigned i = 0, n = TargetOpts->FeaturesAsWritten.size(); i != n; ++i)
code = hash_combine(code, TargetOpts->FeaturesAsWritten[i]);
@@ -1833,6 +1864,7 @@
hsOpts.UseStandardSystemIncludes,
hsOpts.UseStandardCXXIncludes,
hsOpts.UseLibcxx);
+ code = hash_combine(code, hsOpts.ResourceDir);
// Extend the signature with the user build path.
code = hash_combine(code, hsOpts.ModuleUserBuildPath);
@@ -1905,4 +1937,31 @@
return;
GraveYard[Idx] = Ptr;
}
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+createVFSFromCompilerInvocation(const CompilerInvocation &CI,
+ DiagnosticsEngine &Diags) {
+ if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
+ return vfs::getRealFileSystem();
+
+ IntrusiveRefCntPtr<vfs::OverlayFileSystem>
+ Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ // earlier vfs files are on the bottom
+ for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
+ if (llvm::errc::success != llvm::MemoryBuffer::getFile(File, Buffer)) {
+ Diags.Report(diag::err_missing_vfs_overlay_file) << File;
+ return IntrusiveRefCntPtr<vfs::FileSystem>();
+ }
+
+ IntrusiveRefCntPtr<vfs::FileSystem> FS =
+ vfs::getVFSFromYAML(Buffer.release(), /*DiagHandler*/nullptr);
+ if (!FS.getPtr()) {
+ Diags.Report(diag::err_invalid_vfs_overlay) << File;
+ return IntrusiveRefCntPtr<vfs::FileSystem>();
+ }
+ Overlay->pushOverlay(FS);
+ }
+ return Overlay;
}
+} // end namespace clang
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index ededf9a..45f7aa3 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -47,7 +47,7 @@
// FIXME: We shouldn't have to pass in the path info.
driver::Driver TheDriver("clang", llvm::sys::getDefaultTargetTriple(),
- "a.out", *Diags);
+ *Diags);
// Don't check that inputs exist, they may have been remapped.
TheDriver.setCheckInputsExist(false);
@@ -57,7 +57,7 @@
// Just print the cc1 options if -### was present.
if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) {
C->getJobs().Print(llvm::errs(), "\n", true);
- return 0;
+ return nullptr;
}
// We expect to get back exactly one command job, if we didn't something
@@ -68,13 +68,13 @@
llvm::raw_svector_ostream OS(Msg);
Jobs.Print(OS, "; ", true);
Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
- return 0;
+ return nullptr;
}
const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
if (StringRef(Cmd->getCreator().getName()) != "clang") {
Diags->Report(diag::err_fe_expected_clang_command);
- return 0;
+ return nullptr;
}
const ArgStringList &CCArgs = Cmd->getArguments();
@@ -84,6 +84,6 @@
const_cast<const char **>(CCArgs.data()) +
CCArgs.size(),
*Diags))
- return 0;
+ return nullptr;
return CI.release();
}
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index b472eaa..e72be89 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -96,7 +96,7 @@
if (Opts.Targets.empty()) {
PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
- return NULL;
+ return nullptr;
}
// Disable the "file not found" diagnostic if the -MG option was given.
@@ -141,7 +141,7 @@
const FileEntry *FE =
SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
- if (FE == 0) return;
+ if (!FE) return;
StringRef Filename = FE->getName();
if (!FileMatchesDepCriteria(Filename.data(), FileType))
diff --git a/lib/Frontend/DependencyGraph.cpp b/lib/Frontend/DependencyGraph.cpp
index 4bff3db..051b7f9 100644
--- a/lib/Frontend/DependencyGraph.cpp
+++ b/lib/Frontend/DependencyGraph.cpp
@@ -79,7 +79,7 @@
SourceManager &SM = PP->getSourceManager();
const FileEntry *FromFile
= SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(HashLoc)));
- if (FromFile == 0)
+ if (!FromFile)
return;
Dependencies[FromFile].push_back(File);
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index 85e87a2..ce9fc05 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -186,7 +186,7 @@
emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
Diag.getRanges(), Diag.getFixIts(),
Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
- : 0,
+ : nullptr,
&Diag);
}
@@ -509,5 +509,5 @@
void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) {
- emitNote(SourceLocation(), Message, 0);
+ emitNote(SourceLocation(), Message, nullptr);
}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index d2ece7e..b085749 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -37,11 +37,16 @@
class DelegatingDeserializationListener : public ASTDeserializationListener {
ASTDeserializationListener *Previous;
+ bool DeletePrevious;
public:
explicit DelegatingDeserializationListener(
- ASTDeserializationListener *Previous)
- : Previous(Previous) { }
+ ASTDeserializationListener *Previous, bool DeletePrevious)
+ : Previous(Previous), DeletePrevious(DeletePrevious) {}
+ virtual ~DelegatingDeserializationListener() {
+ if (DeletePrevious)
+ delete Previous;
+ }
void ReaderInitialized(ASTReader *Reader) override {
if (Previous)
@@ -74,8 +79,9 @@
/// \brief Dumps deserialized declarations.
class DeserializedDeclsDumper : public DelegatingDeserializationListener {
public:
- explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous)
- : DelegatingDeserializationListener(Previous) { }
+ explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous,
+ bool DeletePrevious)
+ : DelegatingDeserializationListener(Previous, DeletePrevious) {}
void DeclRead(serialization::DeclID ID, const Decl *D) override {
llvm::outs() << "PCH DECL: " << D->getDeclKindName();
@@ -96,9 +102,10 @@
public:
DeserializedDeclsChecker(ASTContext &Ctx,
const std::set<std::string> &NamesToCheck,
- ASTDeserializationListener *Previous)
- : DelegatingDeserializationListener(Previous),
- Ctx(Ctx), NamesToCheck(NamesToCheck) { }
+ ASTDeserializationListener *Previous,
+ bool DeletePrevious)
+ : DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx),
+ NamesToCheck(NamesToCheck) {}
void DeclRead(serialization::DeclID ID, const Decl *D) override {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
@@ -116,7 +123,7 @@
} // end anonymous namespace
-FrontendAction::FrontendAction() : Instance(0) {}
+FrontendAction::FrontendAction() : Instance(nullptr) {}
FrontendAction::~FrontendAction() {}
@@ -130,7 +137,7 @@
StringRef InFile) {
ASTConsumer* Consumer = CreateASTConsumer(CI, InFile);
if (!Consumer)
- return 0;
+ return nullptr;
if (CI.getFrontendOpts().AddPluginActions.size() == 0)
return Consumer;
@@ -189,7 +196,7 @@
setCurrentInput(Input, AST);
// Inform the diagnostic client we are processing a source file.
- CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
+ CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
HasBegunSourceFile = true;
// Set the shared objects, these are reset when we finish processing the
@@ -211,30 +218,13 @@
return true;
}
- if (!CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) {
- IntrusiveRefCntPtr<vfs::OverlayFileSystem>
- Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
- // earlier vfs files are on the bottom
- const std::vector<std::string> &Files =
- CI.getHeaderSearchOpts().VFSOverlayFiles;
- for (std::vector<std::string>::const_iterator I = Files.begin(),
- E = Files.end();
- I != E; ++I) {
- std::unique_ptr<llvm::MemoryBuffer> Buffer;
- if (llvm::errc::success != llvm::MemoryBuffer::getFile(*I, Buffer)) {
- CI.getDiagnostics().Report(diag::err_missing_vfs_overlay_file) << *I;
- goto failure;
- }
-
- IntrusiveRefCntPtr<vfs::FileSystem> FS =
- vfs::getVFSFromYAML(Buffer.release(), /*DiagHandler*/ 0);
- if (!FS.getPtr()) {
- CI.getDiagnostics().Report(diag::err_invalid_vfs_overlay) << *I;
- goto failure;
- }
- Overlay->pushOverlay(FS);
- }
- CI.setVirtualFileSystem(Overlay);
+ if (!CI.hasVirtualFileSystem()) {
+ if (IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(CI.getInvocation(),
+ CI.getDiagnostics()))
+ CI.setVirtualFileSystem(VFS);
+ else
+ goto failure;
}
// Set up the file and source managers, if needed.
@@ -249,13 +239,17 @@
"This action does not have IR file support!");
// Inform the diagnostic client we are processing a source file.
- CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
+ CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
HasBegunSourceFile = true;
// Initialize the action.
if (!BeginSourceFileAction(CI, InputFile))
goto failure;
+ // Initialize the main file entry.
+ if (!CI.InitializeSourceManager(CurrentInput))
+ goto failure;
+
return true;
}
@@ -302,6 +296,11 @@
if (!BeginSourceFileAction(CI, InputFile))
goto failure;
+ // Initialize the main file entry. It is important that this occurs after
+ // BeginSourceFileAction, which may change CurrentInput during module builds.
+ if (!CI.InitializeSourceManager(CurrentInput))
+ goto failure;
+
// Create the AST context and consumer unless this is a preprocessor only
// action.
if (!usesPreprocessorOnly()) {
@@ -328,17 +327,24 @@
assert(hasPCHSupport() && "This action does not have PCH support!");
ASTDeserializationListener *DeserialListener =
Consumer->GetASTDeserializationListener();
- if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls)
- DeserialListener = new DeserializedDeclsDumper(DeserialListener);
- if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty())
- DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(),
- CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,
- DeserialListener);
+ bool DeleteDeserialListener = false;
+ if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) {
+ DeserialListener = new DeserializedDeclsDumper(DeserialListener,
+ DeleteDeserialListener);
+ DeleteDeserialListener = true;
+ }
+ if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) {
+ DeserialListener = new DeserializedDeclsChecker(
+ CI.getASTContext(),
+ CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,
+ DeserialListener, DeleteDeserialListener);
+ DeleteDeserialListener = true;
+ }
CI.createPCHExternalASTSource(
- CI.getPreprocessorOpts().ImplicitPCHInclude,
- CI.getPreprocessorOpts().DisablePCHValidation,
- CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
- DeserialListener);
+ CI.getPreprocessorOpts().ImplicitPCHInclude,
+ CI.getPreprocessorOpts().DisablePCHValidation,
+ CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener,
+ DeleteDeserialListener);
if (!CI.getASTContext().getExternalSource())
goto failure;
}
@@ -352,8 +358,21 @@
// source.
if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) {
Preprocessor &PP = CI.getPreprocessor();
+
+ // If modules are enabled, create the module manager before creating
+ // any builtins, so that all declarations know that they might be
+ // extended by an external source.
+ if (CI.getLangOpts().Modules)
+ CI.createModuleManager();
+
PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
PP.getLangOpts());
+ } else {
+ // FIXME: If this is a problem, recover from it by creating a multiplex
+ // source.
+ assert((!CI.getLangOpts().Modules || CI.getModuleManager()) &&
+ "modules enabled but created an external source that "
+ "doesn't support modules");
}
// If there is a layout overrides file, attach an external AST source that
@@ -365,37 +384,30 @@
CI.getFrontendOpts().OverrideRecordLayoutsFile));
CI.getASTContext().setExternalSource(Override);
}
-
+
return true;
// If we failed, reset state since the client will not end up calling the
// matching EndSourceFile().
failure:
if (isCurrentFileAST()) {
- CI.setASTContext(0);
- CI.setPreprocessor(0);
- CI.setSourceManager(0);
- CI.setFileManager(0);
+ CI.setASTContext(nullptr);
+ CI.setPreprocessor(nullptr);
+ CI.setSourceManager(nullptr);
+ CI.setFileManager(nullptr);
}
if (HasBegunSourceFile)
CI.getDiagnosticClient().EndSourceFile();
CI.clearOutputFiles(/*EraseFiles=*/true);
setCurrentInput(FrontendInputFile());
- setCompilerInstance(0);
+ setCompilerInstance(nullptr);
return false;
}
bool FrontendAction::Execute() {
CompilerInstance &CI = getCompilerInstance();
- // Initialize the main file entry. This needs to be delayed until after PCH
- // has loaded.
- if (!isCurrentFileAST()) {
- if (!CI.InitializeSourceManager(getCurrentInput()))
- return false;
- }
-
if (CI.hasFrontendTimer()) {
llvm::TimeRegion Timer(CI.getFrontendTimer());
ExecuteAction();
@@ -423,22 +435,22 @@
// Finalize the action.
EndSourceFileAction();
- // Release the consumer and the AST, in that order since the consumer may
- // perform actions in its destructor which require the context.
+ // Sema references the ast consumer, so reset sema first.
//
// FIXME: There is more per-file stuff we could just drop here?
- if (CI.getFrontendOpts().DisableFree) {
- BuryPointer(CI.takeASTConsumer());
+ bool DisableFree = CI.getFrontendOpts().DisableFree;
+ if (DisableFree) {
if (!isCurrentFileAST()) {
- BuryPointer(CI.takeSema());
+ CI.resetAndLeakSema();
CI.resetAndLeakASTContext();
}
+ BuryPointer(CI.takeASTConsumer());
} else {
if (!isCurrentFileAST()) {
- CI.setSema(0);
- CI.setASTContext(0);
+ CI.setSema(nullptr);
+ CI.setASTContext(nullptr);
}
- CI.setASTConsumer(0);
+ CI.setASTConsumer(nullptr);
}
// Inform the preprocessor we are done.
@@ -458,15 +470,16 @@
// FrontendAction.
CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles());
+ // FIXME: Only do this if DisableFree is set.
if (isCurrentFileAST()) {
- CI.takeSema();
+ CI.resetAndLeakSema();
CI.resetAndLeakASTContext();
CI.resetAndLeakPreprocessor();
CI.resetAndLeakSourceManager();
CI.resetAndLeakFileManager();
}
- setCompilerInstance(0);
+ setCompilerInstance(nullptr);
setCurrentInput(FrontendInputFile());
}
@@ -490,7 +503,7 @@
CI.createCodeCompletionConsumer();
// Use a code completion consumer?
- CodeCompleteConsumer *CompletionConsumer = 0;
+ CodeCompleteConsumer *CompletionConsumer = nullptr;
if (CI.hasCodeCompletionConsumer())
CompletionConsumer = &CI.getCodeCompletionConsumer();
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 2657c98..5c56ee3 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -49,7 +49,7 @@
StringRef InFile) {
if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
return CreateASTPrinter(OS, CI.getFrontendOpts().ASTDumpFilter);
- return 0;
+ return nullptr;
}
ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
@@ -77,13 +77,14 @@
StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = 0;
+ raw_ostream *OS = nullptr;
if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
- return 0;
+ return nullptr;
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
- return new PCHGenerator(CI.getPreprocessor(), OutputFile, 0, Sysroot, OS);
+ return new PCHGenerator(CI.getPreprocessor(), OutputFile, nullptr, Sysroot,
+ OS);
}
bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
@@ -114,10 +115,10 @@
StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = 0;
+ raw_ostream *OS = nullptr;
if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
- return 0;
-
+ return nullptr;
+
return new PCHGenerator(CI.getPreprocessor(), OutputFile, Module,
Sysroot, OS);
}
@@ -213,7 +214,7 @@
// If this header is marked 'unavailable' in this module, don't include
// it.
if (const FileEntry *Header = FileMgr.getFile(Dir->path())) {
- if (ModMap.isHeaderInUnavailableModule(Header))
+ if (ModMap.isHeaderUnavailableInModule(Header, Module))
continue;
Module->addTopHeader(Header);
}
@@ -288,7 +289,8 @@
if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement,
MissingHeader)) {
if (MissingHeader.FileNameLoc.isValid()) {
- CI.getDiagnostics().Report(diag::err_module_header_missing)
+ CI.getDiagnostics().Report(MissingHeader.FileNameLoc,
+ diag::err_module_header_missing)
<< MissingHeader.IsUmbrella << MissingHeader.FileName;
} else {
CI.getDiagnostics().Report(diag::err_module_unavailable)
@@ -299,6 +301,11 @@
return false;
}
+ if (!ModuleMapForUniquing)
+ ModuleMapForUniquing = ModuleMap;
+ Module->ModuleMap = ModuleMapForUniquing;
+ assert(Module->ModuleMap && "missing module map file");
+
FileManager &FileMgr = CI.getFileManager();
// Collect the set of #includes we need to build the module.
@@ -337,10 +344,9 @@
// in the module cache.
if (CI.getFrontendOpts().OutputFile.empty()) {
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
- SmallString<256> ModuleFileName(HS.getModuleCachePath());
- llvm::sys::path::append(ModuleFileName,
- CI.getLangOpts().CurrentModule + ".pcm");
- CI.getFrontendOpts().OutputFile = ModuleFileName.str();
+ CI.getFrontendOpts().OutputFile =
+ HS.getModuleFileName(CI.getLangOpts().CurrentModule,
+ ModuleMapForUniquing->getName());
}
// We use createOutputFile here because this is exposed via libclang, and we
@@ -412,6 +418,13 @@
return ASTReaderListener::ReadFullVersionInformation(FullVersion);
}
+ void ReadModuleName(StringRef ModuleName) override {
+ Out.indent(2) << "Module name: " << ModuleName << "\n";
+ }
+ void ReadModuleMapFile(StringRef ModuleMapPath) override {
+ Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";
+ }
+
bool ReadLanguageOptions(const LangOptions &LangOpts,
bool Complain) override {
Out.indent(2) << "Language options:\n";
@@ -434,7 +447,6 @@
Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n";
Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n";
Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n";
- Out.indent(4) << " Linker version: " << TargetOpts.LinkerVersion << "\n";
if (!TargetOpts.FeaturesAsWritten.empty()) {
Out.indent(4) << "Target features:\n";
@@ -447,6 +459,25 @@
return false;
}
+ virtual 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) \
+ Out.indent(4) << #Name << ": " << DiagOpts->get##Name() << "\n";
+#define VALUE_DIAGOPT(Name, Bits, Default) \
+ Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n";
+#include "clang/Basic/DiagnosticOptions.def"
+
+ Out.indent(4) << "Warning options:\n";
+ for (const std::string &Warning : DiagOpts->Warnings) {
+ Out.indent(6) << "-W" << Warning << "\n";
+ }
+
+ return false;
+ }
+
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
bool Complain) override {
Out.indent(2) << "Header search options:\n";
@@ -562,7 +593,7 @@
Preprocessor &PP = getCompilerInstance().getPreprocessor();
// Ignore unknown pragmas.
- PP.AddPragmaHandler(new EmptyPragmaHandler());
+ PP.IgnorePragmas();
Token Tok;
// Start parsing the specified input file.
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 34c01b4..d2890f0 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -379,6 +379,7 @@
"arm-apple-darwin10", "v6", "", triple);
break;
+ case llvm::Triple::aarch64:
case llvm::Triple::arm64:
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
"arm64-apple-darwin10", "", "", triple);
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 761dba4..fb52eb4 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -86,7 +86,7 @@
StringRef ImplicitIncludePTH) {
PTHManager *P = PP.getPTHManager();
// Null check 'P' in the corner case where it couldn't be created.
- const char *OriginalFile = P ? P->getOriginalSourceFile() : 0;
+ const char *OriginalFile = P ? P->getOriginalSourceFile() : nullptr;
if (!OriginalFile) {
PP.getDiagnostics().Report(diag::err_fe_pth_file_has_no_source_header)
@@ -508,10 +508,6 @@
}
if (LangOpts.MicrosoftExt) {
- // Both __PRETTY_FUNCTION__ and __FUNCTION__ are GCC extensions, however
- // VC++ appears to only like __FUNCTION__.
- Builder.defineMacro("__PRETTY_FUNCTION__", "__FUNCTION__");
- // Work around some issues with Visual C++ headers.
if (LangOpts.WChar) {
// wchar_t supported as a keyword.
Builder.defineMacro("_WCHAR_T_DEFINED");
diff --git a/lib/Frontend/LangStandards.cpp b/lib/Frontend/LangStandards.cpp
index f86a574..f133327 100644
--- a/lib/Frontend/LangStandards.cpp
+++ b/lib/Frontend/LangStandards.cpp
@@ -35,7 +35,7 @@
#include "clang/Frontend/LangStandards.def"
.Default(lang_unspecified);
if (K == lang_unspecified)
- return 0;
+ return nullptr;
return &getLangStandardForKind(K);
}
diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp
index 53b13fc..917c13f 100644
--- a/lib/Frontend/LogDiagnosticPrinter.cpp
+++ b/lib/Frontend/LogDiagnosticPrinter.cpp
@@ -19,7 +19,7 @@
LogDiagnosticPrinter::LogDiagnosticPrinter(raw_ostream &os,
DiagnosticOptions *diags,
bool _OwnsOutputStream)
- : OS(os), LangOpts(0), DiagOpts(diags),
+ : OS(os), LangOpts(nullptr), DiagOpts(diags),
OwnsOutputStream(_OwnsOutputStream) {
}
diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp
index 4b4804f..058cee8 100644
--- a/lib/Frontend/MultiplexConsumer.cpp
+++ b/lib/Frontend/MultiplexConsumer.cpp
@@ -226,6 +226,11 @@
return Continue;
}
+void MultiplexConsumer::HandleInlineMethodDefinition(CXXMethodDecl *D) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->HandleInlineMethodDefinition(D);
+}
+
void MultiplexConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
for (size_t i = 0, e = Consumers.size(); i != e; ++i)
Consumers[i]->HandleCXXStaticMemberVarInstantiation(VD);
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 349401a..8c32c24 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -162,7 +162,8 @@
const Token &Tok) {
return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok);
}
- void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
+ void WriteLineInfo(unsigned LineNo, const char *Extra=nullptr,
+ unsigned ExtraLen=0);
bool LineMarkersAreDisabled() const { return DisableLineMarkers; }
void HandleNewlinesInToken(const char *TokStr, unsigned Len);
@@ -220,7 +221,7 @@
}
} else if (!DisableLineMarkers) {
// Emit a #line or line marker.
- WriteLineInfo(LineNo, 0, 0);
+ WriteLineInfo(LineNo, nullptr, 0);
} else {
// Okay, we're in -P mode, which turns off line markers. However, we still
// need to emit a newline between tokens on different lines.
@@ -671,7 +672,7 @@
static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) {
// Ignore unknown pragmas.
- PP.AddPragmaHandler(new EmptyPragmaHandler());
+ PP.IgnorePragmas();
// -dM mode just scans and ignores all tokens in the files, then dumps out
// the macro table at the end.
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 527f727..db89f25 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -93,11 +93,12 @@
struct SharedState;
explicit SDiagsWriter(IntrusiveRefCntPtr<SharedState> State)
- : LangOpts(0), OriginalInstance(false), State(State) { }
+ : LangOpts(nullptr), OriginalInstance(false), State(State) {}
public:
SDiagsWriter(raw_ostream *os, DiagnosticOptions *diags)
- : LangOpts(0), OriginalInstance(true), State(new SharedState(os, diags))
+ : LangOpts(nullptr), OriginalInstance(true),
+ State(new SharedState(os, diags))
{
EmitPreamble();
}
@@ -254,7 +255,7 @@
Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
// Emit the block name if present.
- if (Name == 0 || Name[0] == 0)
+ if (!Name || Name[0] == 0)
return;
Record.clear();
@@ -545,7 +546,7 @@
EnterDiagBlock();
EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel,
- State->diagBuf, 0, &Info);
+ State->diagBuf, nullptr, &Info);
if (DiagLevel == DiagnosticsEngine::Note)
ExitDiagBlock();
@@ -559,8 +560,7 @@
Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
State->diagBuf.str(),
Info.getRanges(),
- llvm::makeArrayRef(Info.getFixItHints(),
- Info.getNumFixItHints()),
+ Info.getFixItHints(),
&Info.getSourceManager(),
&Info);
}
@@ -702,5 +702,5 @@
State->OS->write((char *)&State->Buffer.front(), State->Buffer.size());
State->OS->flush();
- State->OS.reset(0);
+ State->OS.reset(nullptr);
}
diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp
index b1c793a..9c6bebb 100644
--- a/lib/Frontend/TextDiagnosticBuffer.cpp
+++ b/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -35,6 +35,9 @@
case DiagnosticsEngine::Warning:
Warnings.push_back(std::make_pair(Info.getLocation(), Buf.str()));
break;
+ case DiagnosticsEngine::Remark:
+ Remarks.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+ break;
case DiagnosticsEngine::Error:
case DiagnosticsEngine::Fatal:
Errors.push_back(std::make_pair(Info.getLocation(), Buf.str()));
@@ -50,6 +53,9 @@
for (const_iterator it = warn_begin(), ie = warn_end(); it != ie; ++it)
Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Warning, "%0"))
<< it->second;
+ for (const_iterator it = remark_begin(), ie = remark_end(); it != ie; ++it)
+ Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Remark, "%0"))
+ << it->second;
for (const_iterator it = note_begin(), ie = note_end(); it != ie; ++it)
Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0"))
<< it->second;
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 994a8f7..d6df655 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -43,7 +43,7 @@
}
void TextDiagnosticPrinter::EndSourceFile() {
- TextDiag.reset(0);
+ TextDiag.reset(nullptr);
}
/// \brief Print any diagnostic option information to a raw_ostream.
@@ -81,7 +81,11 @@
StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID());
if (!Opt.empty()) {
- OS << (Started ? "," : " [") << "-W" << Opt;
+ OS << (Started ? "," : " [")
+ << (DiagnosticIDs::isRemark(Info.getID()) ? "-R" : "-W") << Opt;
+ StringRef OptValue = Info.getDiags()->getFlagNameValue();
+ if (!OptValue.empty())
+ OS << "=" << OptValue;
Started = true;
}
}
@@ -150,8 +154,7 @@
TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(),
Info.getRanges(),
- llvm::makeArrayRef(Info.getFixItHints(),
- Info.getNumFixItHints()),
+ Info.getFixItHints(),
&Info.getSourceManager());
OS.flush();
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 0221a55..856b51d 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -30,8 +30,9 @@
VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags)
: Diags(_Diags),
PrimaryClient(Diags.getClient()), OwnsPrimaryClient(Diags.ownsClient()),
- Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0),
- LangOpts(0), SrcManager(0), ActiveSourceFiles(0), Status(HasNoDirectives)
+ Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(nullptr),
+ LangOpts(nullptr), SrcManager(nullptr), ActiveSourceFiles(0),
+ Status(HasNoDirectives)
{
Diags.takeClient();
if (Diags.hasSourceManager())
@@ -41,7 +42,7 @@
VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
assert(!ActiveSourceFiles && "Incomplete parsing of source files!");
assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");
- SrcManager = 0;
+ SrcManager = nullptr;
CheckDiagnostics();
Diags.takeClient();
if (OwnsPrimaryClient)
@@ -104,8 +105,8 @@
// Check diagnostics once last file completed.
CheckDiagnostics();
- CurrentPreprocessor = 0;
- LangOpts = 0;
+ CurrentPreprocessor = nullptr;
+ LangOpts = nullptr;
}
}
@@ -202,7 +203,7 @@
{
public:
ParseHelper(StringRef S)
- : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(NULL) { }
+ : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(nullptr) {}
// Return true if string literal is next.
bool Next(StringRef S) {
@@ -325,13 +326,15 @@
PH.Advance();
// Next token: { error | warning | note }
- DirectiveList* DL = NULL;
+ DirectiveList *DL = nullptr;
if (PH.Next("error"))
- DL = ED ? &ED->Errors : NULL;
+ DL = ED ? &ED->Errors : nullptr;
else if (PH.Next("warning"))
- DL = ED ? &ED->Warnings : NULL;
+ DL = ED ? &ED->Warnings : nullptr;
+ else if (PH.Next("remark"))
+ DL = ED ? &ED->Remarks : nullptr;
else if (PH.Next("note"))
- DL = ED ? &ED->Notes : NULL;
+ DL = ED ? &ED->Notes : nullptr;
else if (PH.Next("no-diagnostics")) {
if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives)
Diags.Report(Pos, diag::err_verify_invalid_no_diags)
@@ -395,8 +398,8 @@
// Lookup file via Preprocessor, like a #include.
const DirectoryLookup *CurDir;
- const FileEntry *FE = PP->LookupFile(Pos, Filename, false, NULL, CurDir,
- NULL, NULL, 0);
+ const FileEntry *FE = PP->LookupFile(Pos, Filename, false, nullptr,
+ CurDir, nullptr, nullptr, nullptr);
if (!FE) {
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
diag::err_verify_missing_file) << Filename << KindStr;
@@ -491,11 +494,12 @@
}
// Construct new directive.
- Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text,
- Min, Max);
+ std::unique_ptr<Directive> D(
+ Directive::create(RegexKind, Pos, ExpectedLoc, Text, Min, Max));
+
std::string Error;
if (D->isValid(Error)) {
- DL->push_back(D);
+ DL->push_back(D.release());
FoundDirective = true;
} else {
Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin),
@@ -593,7 +597,8 @@
if (Comment.empty()) continue;
// Find first directive.
- if (ParseDirective(Comment, 0, SM, 0, Tok.getLocation(), Status))
+ if (ParseDirective(Comment, nullptr, SM, nullptr, Tok.getLocation(),
+ Status))
return true;
}
return false;
@@ -736,6 +741,10 @@
NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings,
Buffer.warn_begin(), Buffer.warn_end());
+ // See if there are remark mismatches.
+ NumProblems += CheckLists(Diags, SourceMgr, "remark", ED.Remarks,
+ Buffer.remark_begin(), Buffer.remark_end());
+
// See if there are note mismatches.
NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes,
Buffer.note_begin(), Buffer.note_end());
@@ -833,11 +842,11 @@
// Check that the expected diagnostics occurred.
NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED);
} else {
- NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(),
+ NumErrors += (PrintUnexpected(Diags, nullptr, Buffer->err_begin(),
Buffer->err_end(), "error") +
- PrintUnexpected(Diags, 0, Buffer->warn_begin(),
+ PrintUnexpected(Diags, nullptr, Buffer->warn_begin(),
Buffer->warn_end(), "warn") +
- PrintUnexpected(Diags, 0, Buffer->note_begin(),
+ PrintUnexpected(Diags, nullptr, Buffer->note_begin(),
Buffer->note_end(), "note"));
}
@@ -846,9 +855,7 @@
// Reset the buffer, we have processed all the diagnostics in it.
Buffer.reset(new TextDiagnosticBuffer());
- ED.Errors.clear();
- ED.Warnings.clear();
- ED.Notes.clear();
+ ED.Reset();
}
Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
@@ -880,5 +887,6 @@
}
}
- return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max, RegexStr);
+ return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max,
+ RegexStr);
}
diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 0edd577..76baec7 100644
--- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -74,14 +74,14 @@
if (it->getName() == CI.getFrontendOpts().ActionName) {
std::unique_ptr<PluginASTAction> P(it->instantiate());
if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
- return 0;
+ return nullptr;
return P.release();
}
}
CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
<< CI.getFrontendOpts().ActionName;
- return 0;
+ return nullptr;
}
case PrintDeclContext: return new DeclContextPrintAction();
@@ -133,7 +133,7 @@
// Create the underlying action.
FrontendAction *Act = CreateFrontendBaseAction(CI);
if (!Act)
- return 0;
+ return nullptr;
const FrontendOptions &FEOpts = CI.getFrontendOpts();
@@ -144,7 +144,8 @@
#endif
#ifdef CLANG_ENABLE_ARCMT
- if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource) {
+ if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource &&
+ CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) {
// Potentially wrap the base FE action in an ARC Migrate Tool action.
switch (FEOpts.ARCMTAction) {
case FrontendOptions::ARCMT_None:
@@ -212,12 +213,12 @@
// This should happen AFTER plugins have been loaded!
if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
- const char **Args = new const char*[NumArgs + 2];
+ auto Args = llvm::make_unique<const char*[]>(NumArgs + 2);
Args[0] = "clang (LLVM option parsing)";
for (unsigned i = 0; i != NumArgs; ++i)
Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
- Args[NumArgs + 1] = 0;
- llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
+ Args[NumArgs + 1] = nullptr;
+ llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
}
#ifdef CLANG_ENABLE_STATIC_ANALYZER
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index d0c2684..23b2446 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -45,7 +45,7 @@
xopintrin.h
cpuid.h
unwind.h
- module.map
+ module.modulemap
)
set(output_dir ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/include)
diff --git a/lib/Headers/Intrin.h b/lib/Headers/Intrin.h
index e365abe..ff6d278 100644
--- a/lib/Headers/Intrin.h
+++ b/lib/Headers/Intrin.h
@@ -100,11 +100,9 @@
unsigned int __popcnt(unsigned int);
static __inline__
unsigned short __popcnt16(unsigned short);
-static __inline__
-unsigned __int64 __rdtsc(void);
-unsigned __int64 __rdtscp(unsigned int *);
unsigned long __readcr0(void);
unsigned long __readcr2(void);
+static __inline__
unsigned long __readcr3(void);
unsigned long __readcr4(void);
unsigned long __readcr8(void);
@@ -119,6 +117,7 @@
static __inline__
unsigned short __readfsword(unsigned long);
#endif
+static __inline__
unsigned __int64 __readmsr(unsigned long);
unsigned __int64 __readpmc(unsigned long);
unsigned long __segmentlimit(unsigned long);
@@ -143,6 +142,7 @@
void __vmx_vmptrst(unsigned __int64 *);
void __wbinvd(void);
void __writecr0(unsigned int);
+static __inline__
void __writecr3(unsigned int);
void __writecr4(unsigned int);
void __writecr8(unsigned int);
@@ -825,14 +825,12 @@
return _Comparand;
}
#endif
-#ifdef __x86_64__
static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
_InterlockedCompareExchange64(__int64 volatile *_Destination,
__int64 _Exchange, __int64 _Comparand) {
__atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0, 0, 0);
return _Comparand;
}
-#endif
/*----------------------------------------------------------------------------*\
|* Barriers
\*----------------------------------------------------------------------------*/
@@ -981,6 +979,35 @@
__asm__ volatile ("hlt");
}
+/*----------------------------------------------------------------------------*\
+|* Privileged intrinsics
+\*----------------------------------------------------------------------------*/
+static __inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__))
+__readmsr(unsigned long __register) {
+ // Loads the contents of a 64-bit model specific register (MSR) specified in
+ // the ECX register into registers EDX:EAX. The EDX register is loaded with
+ // the high-order 32 bits of the MSR and the EAX register is loaded with the
+ // low-order 32 bits. If less than 64 bits are implemented in the MSR being
+ // read, the values returned to EDX:EAX in unimplemented bit locations are
+ // undefined.
+ unsigned long __edx;
+ unsigned long __eax;
+ __asm__ ("rdmsr" : "=d"(__edx), "=a"(__eax) : "c"(__register));
+ return (((unsigned __int64)__edx) << 32) | (unsigned __int64)__eax;
+}
+
+static __inline__ unsigned long __attribute__((always_inline, __nodebug__))
+__readcr3(void) {
+ unsigned long __cr3_val;
+ __asm__ __volatile__ ("mov %%cr3, %0" : "=q"(__cr3_val) : : "memory");
+ return __cr3_val;
+}
+
+static __inline__ void __attribute__((always_inline, __nodebug__))
+__writecr3(unsigned int __cr3_val) {
+ __asm__ ("mov %0, %%cr3" : : "q"(__cr3_val) : "memory");
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/Headers/Makefile b/lib/Headers/Makefile
index 42219c4..903acac 100644
--- a/lib/Headers/Makefile
+++ b/lib/Headers/Makefile
@@ -32,13 +32,13 @@
$(Verb) cp $< $@
$(Echo) Copying $(notdir $<) to build dir
-$(HeaderDir)/module.map: $(PROJ_SRC_DIR)/module.map $(HeaderDir)/.dir
+$(HeaderDir)/module.modulemap: $(PROJ_SRC_DIR)/module.modulemap $(HeaderDir)/.dir
$(Verb) cp $< $@
$(Echo) Copying $(notdir $<) to build dir
# Hook into the standard Makefile rules.
-all-local:: $(OBJHEADERS) $(HeaderDir)/module.map
+all-local:: $(OBJHEADERS) $(HeaderDir)/module.modulemap
PROJ_headers := $(DESTDIR)$(PROJ_prefix)/lib/clang/$(CLANG_VERSION)/include
@@ -52,12 +52,12 @@
$(Verb) $(DataInstall) $< $(PROJ_headers)
$(Echo) Installing compiler include file: $(notdir $<)
-$(PROJ_headers)/module.map: $(HeaderDir)/module.map | $(PROJ_headers)
+$(PROJ_headers)/module.modulemap: $(HeaderDir)/module.modulemap | $(PROJ_headers)
$(Verb) $(DataInstall) $< $(PROJ_headers)
$(Echo) Installing compiler module map file: $(notdir $<)
-install-local:: $(INSTHEADERS) $(PROJ_headers)/module.map
+install-local:: $(INSTHEADERS) $(PROJ_headers)/module.modulemap
$(ObjDir)/arm_neon.h.inc.tmp : $(CLANG_LEVEL)/include/clang/Basic/arm_neon.td $(CLANG_TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang arm_neon.h.inc with tblgen"
diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h
index 9574469..394fdfe 100644
--- a/lib/Headers/avx2intrin.h
+++ b/lib/Headers/avx2intrin.h
@@ -160,7 +160,23 @@
#define _mm256_blend_epi16(V1, V2, M) __extension__ ({ \
__m256i __V1 = (V1); \
__m256i __V2 = (V2); \
- (__m256i)__builtin_ia32_pblendw256((__v16hi)__V1, (__v16hi)__V2, (M)); })
+ (__m256d)__builtin_shufflevector((__v16hi)__V1, (__v16hi)__V2, \
+ (((M) & 0x01) ? 16 : 0), \
+ (((M) & 0x02) ? 17 : 1), \
+ (((M) & 0x04) ? 18 : 2), \
+ (((M) & 0x08) ? 19 : 3), \
+ (((M) & 0x10) ? 20 : 4), \
+ (((M) & 0x20) ? 21 : 5), \
+ (((M) & 0x40) ? 22 : 6), \
+ (((M) & 0x80) ? 23 : 7), \
+ (((M) & 0x01) ? 24 : 8), \
+ (((M) & 0x02) ? 25 : 9), \
+ (((M) & 0x04) ? 26 : 10), \
+ (((M) & 0x08) ? 27 : 11), \
+ (((M) & 0x10) ? 28 : 12), \
+ (((M) & 0x20) ? 29 : 13), \
+ (((M) & 0x40) ? 30 : 14), \
+ (((M) & 0x80) ? 31 : 15)); })
static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
_mm256_cmpeq_epi8(__m256i __a, __m256i __b)
@@ -761,12 +777,24 @@
#define _mm_blend_epi32(V1, V2, M) __extension__ ({ \
__m128i __V1 = (V1); \
__m128i __V2 = (V2); \
- (__m128i)__builtin_ia32_pblendd128((__v4si)__V1, (__v4si)__V2, (M)); })
+ (__m128i)__builtin_shufflevector((__v4si)__V1, (__v4si)__V2, \
+ (((M) & 0x01) ? 4 : 0), \
+ (((M) & 0x02) ? 5 : 1), \
+ (((M) & 0x04) ? 6 : 2), \
+ (((M) & 0x08) ? 7 : 3)); })
#define _mm256_blend_epi32(V1, V2, M) __extension__ ({ \
__m256i __V1 = (V1); \
__m256i __V2 = (V2); \
- (__m256i)__builtin_ia32_pblendd256((__v8si)__V1, (__v8si)__V2, (M)); })
+ (__m256i)__builtin_shufflevector((__v8si)__V1, (__v8si)__V2, \
+ (((M) & 0x01) ? 8 : 0), \
+ (((M) & 0x02) ? 9 : 1), \
+ (((M) & 0x04) ? 10 : 2), \
+ (((M) & 0x08) ? 11 : 3), \
+ (((M) & 0x10) ? 12 : 4), \
+ (((M) & 0x20) ? 13 : 5), \
+ (((M) & 0x40) ? 14 : 6), \
+ (((M) & 0x80) ? 15 : 7)); })
static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
_mm256_broadcastb_epi8(__m128i __X)
diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h
index 141c4d9..3d50439 100644
--- a/lib/Headers/avxintrin.h
+++ b/lib/Headers/avxintrin.h
@@ -308,12 +308,24 @@
#define _mm256_blend_pd(V1, V2, M) __extension__ ({ \
__m256d __V1 = (V1); \
__m256d __V2 = (V2); \
- (__m256d)__builtin_ia32_blendpd256((__v4df)__V1, (__v4df)__V2, (M)); })
+ (__m256d)__builtin_shufflevector((__v4df)__V1, (__v4df)__V2, \
+ (((M) & 0x01) ? 4 : 0), \
+ (((M) & 0x02) ? 5 : 1), \
+ (((M) & 0x04) ? 6 : 2), \
+ (((M) & 0x08) ? 7 : 3)); })
#define _mm256_blend_ps(V1, V2, M) __extension__ ({ \
__m256 __V1 = (V1); \
__m256 __V2 = (V2); \
- (__m256)__builtin_ia32_blendps256((__v8sf)__V1, (__v8sf)__V2, (M)); })
+ (__m256)__builtin_shufflevector((__v8sf)__V1, (__v8sf)__V2, \
+ (((M) & 0x01) ? 8 : 0), \
+ (((M) & 0x02) ? 9 : 1), \
+ (((M) & 0x04) ? 10 : 2), \
+ (((M) & 0x08) ? 11 : 3), \
+ (((M) & 0x10) ? 12 : 4), \
+ (((M) & 0x20) ? 13 : 5), \
+ (((M) & 0x40) ? 14 : 6), \
+ (((M) & 0x80) ? 15 : 7)); })
static __inline __m256d __attribute__((__always_inline__, __nodebug__))
_mm256_blendv_pd(__m256d __a, __m256d __b, __m256d __c)
diff --git a/lib/Headers/ia32intrin.h b/lib/Headers/ia32intrin.h
index a5985f6..55c2247 100644
--- a/lib/Headers/ia32intrin.h
+++ b/lib/Headers/ia32intrin.h
@@ -82,9 +82,13 @@
/* __rdtsc */
static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
__rdtsc(void) {
- unsigned int __eax, __edx;
- __asm__ ("rdtsc" : "=a" (__eax), "=d" (__edx));
- return ((unsigned long long)__edx << 32) | __eax;
+ return __builtin_ia32_rdtsc();
+}
+
+/* __rdtscp */
+static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+__rdtscp(unsigned int *__A) {
+ return __builtin_ia32_rdtscp(__A);
}
#define _rdtsc() __rdtsc()
diff --git a/lib/Headers/module.map b/lib/Headers/module.modulemap
similarity index 100%
rename from lib/Headers/module.map
rename to lib/Headers/module.modulemap
diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h
index 53b3ccb..6e35734 100644
--- a/lib/Headers/smmintrin.h
+++ b/lib/Headers/smmintrin.h
@@ -79,12 +79,18 @@
#define _mm_blend_pd(V1, V2, M) __extension__ ({ \
__m128d __V1 = (V1); \
__m128d __V2 = (V2); \
- (__m128d) __builtin_ia32_blendpd ((__v2df)__V1, (__v2df)__V2, (M)); })
+ (__m128d)__builtin_shufflevector((__v2df)__V1, (__v2df)__V2, \
+ (((M) & 0x01) ? 2 : 0), \
+ (((M) & 0x02) ? 3 : 1)); })
#define _mm_blend_ps(V1, V2, M) __extension__ ({ \
__m128 __V1 = (V1); \
__m128 __V2 = (V2); \
- (__m128) __builtin_ia32_blendps ((__v4sf)__V1, (__v4sf)__V2, (M)); })
+ (__m128)__builtin_shufflevector((__v4sf)__V1, (__v4sf)__V2, \
+ (((M) & 0x01) ? 4 : 0), \
+ (((M) & 0x02) ? 5 : 1), \
+ (((M) & 0x04) ? 6 : 2), \
+ (((M) & 0x08) ? 7 : 3)); })
static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
_mm_blendv_pd (__m128d __V1, __m128d __V2, __m128d __M)
@@ -110,7 +116,15 @@
#define _mm_blend_epi16(V1, V2, M) __extension__ ({ \
__m128i __V1 = (V1); \
__m128i __V2 = (V2); \
- (__m128i) __builtin_ia32_pblendw128 ((__v8hi)__V1, (__v8hi)__V2, (M)); })
+ (__m128i)__builtin_shufflevector((__v8hi)__V1, (__v8hi)__V2, \
+ (((M) & 0x01) ? 8 : 0), \
+ (((M) & 0x02) ? 9 : 1), \
+ (((M) & 0x04) ? 10 : 2), \
+ (((M) & 0x08) ? 11 : 3), \
+ (((M) & 0x10) ? 12 : 4), \
+ (((M) & 0x20) ? 13 : 5), \
+ (((M) & 0x40) ? 14 : 6), \
+ (((M) & 0x80) ? 15 : 7)); })
/* SSE4 Dword Multiply Instructions. */
static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
diff --git a/lib/Headers/stddef.h b/lib/Headers/stddef.h
index 97126ed..2dfe0a2 100644
--- a/lib/Headers/stddef.h
+++ b/lib/Headers/stddef.h
@@ -23,9 +23,22 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef __STDDEF_H
-#define __STDDEF_H
+#if !defined(__STDDEF_H) || defined(__need_ptrdiff_t) || \
+ defined(__need_size_t) || defined(__need_wchar_t) || \
+ defined(__need_NULL) || defined(__need_wint_t)
+#if !defined(__need_ptrdiff_t) && !defined(__need_size_t) && \
+ !defined(__need_wchar_t) && !defined(__need_NULL) && \
+ !defined(__need_wint_t)
+#define __STDDEF_H
+#define __need_ptrdiff_t
+#define __need_size_t
+#define __need_wchar_t
+#define __need_NULL
+/* __need_wint_t is intentionally not defined here. */
+#endif
+
+#if defined(__need_ptrdiff_t)
#if !defined(_PTRDIFF_T) || __has_feature(modules)
/* Always define ptrdiff_t when modules are available. */
#if !__has_feature(modules)
@@ -33,7 +46,10 @@
#endif
typedef __PTRDIFF_TYPE__ ptrdiff_t;
#endif
+#undef __need_ptrdiff_t
+#endif /* defined(__need_ptrdiff_t) */
+#if defined(__need_size_t)
#if !defined(_SIZE_T) || __has_feature(modules)
/* Always define size_t when modules are available. */
#if !__has_feature(modules)
@@ -41,7 +57,10 @@
#endif
typedef __SIZE_TYPE__ size_t;
#endif
+#undef __need_size_t
+#endif /*defined(__need_size_t) */
+#if defined(__STDDEF_H)
/* ISO9899:2011 7.20 (C11 Annex K): Define rsize_t if __STDC_WANT_LIB_EXT1__ is
* enabled. */
#if (defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1 && \
@@ -52,7 +71,9 @@
#endif
typedef __SIZE_TYPE__ rsize_t;
#endif
+#endif /* defined(__STDDEF_H) */
+#if defined(__need_wchar_t)
#ifndef __cplusplus
/* Always define wchar_t when modules are available. */
#if !defined(_WCHAR_T) || __has_feature(modules)
@@ -65,7 +86,10 @@
typedef __WCHAR_TYPE__ wchar_t;
#endif
#endif
+#undef __need_wchar_t
+#endif /* defined(__need_wchar_t) */
+#if defined(__need_NULL)
#undef NULL
#ifdef __cplusplus
# if !defined(__MINGW32__) && !defined(_MSC_VER)
@@ -76,15 +100,19 @@
#else
# define NULL ((void*)0)
#endif
-
#ifdef __cplusplus
#if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED)
namespace std { typedef decltype(nullptr) nullptr_t; }
using ::std::nullptr_t;
#endif
#endif
+#undef __need_NULL
+#endif /* defined(__need_NULL) */
+
+#if defined(__STDDEF_H)
#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L
+#if !defined(__CLANG_MAX_ALIGN_T_DEFINED) || __has_feature(modules)
#ifndef _MSC_VER
typedef struct {
long long __clang_max_align_nonce1
@@ -97,10 +125,10 @@
#endif
#define __CLANG_MAX_ALIGN_T_DEFINED
#endif
+#endif
#define offsetof(t, d) __builtin_offsetof(t, d)
-
-#endif /* __STDDEF_H */
+#endif /* __STDDEF_H */
/* Some C libraries expect to see a wint_t here. Others (notably MinGW) will use
__WINT_TYPE__ directly; accommodate both by requiring __need_wint_t */
@@ -114,3 +142,5 @@
#endif
#undef __need_wint_t
#endif /* __need_wint_t */
+
+#endif
diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h
index c8765a7..e777ec0 100644
--- a/lib/Headers/xmmintrin.h
+++ b/lib/Headers/xmmintrin.h
@@ -905,7 +905,7 @@
__a = _mm_movehl_ps(__a, __a);
__c = _mm_cvtps_pi32(__a);
- return _mm_packs_pi16(__b, __c);
+ return _mm_packs_pi32(__b, __c);
}
static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
diff --git a/lib/Index/CommentToXML.cpp b/lib/Index/CommentToXML.cpp
index 43c4232..a67c806 100644
--- a/lib/Index/CommentToXML.cpp
+++ b/lib/Index/CommentToXML.cpp
@@ -97,7 +97,7 @@
FullCommentParts::FullCommentParts(const FullComment *C,
const CommandTraits &Traits) :
- Brief(NULL), Headerfile(NULL), FirstParagraph(NULL) {
+ Brief(nullptr), Headerfile(nullptr), FirstParagraph(nullptr) {
for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
I != E; ++I) {
const Comment *Child = *I;
@@ -563,6 +563,7 @@
// Helpers.
void appendToResultWithXMLEscaping(StringRef S);
+ void appendToResultWithCDATAEscaping(StringRef S);
void formatTextOfDeclaration(const DeclInfo *DI,
SmallString<128> &Declaration);
@@ -667,14 +668,27 @@
void CommentASTToXMLConverter::visitHTMLStartTagComment(
const HTMLStartTagComment *C) {
- Result << "<rawHTML><![CDATA[";
- printHTMLStartTagComment(C, Result);
- Result << "]]></rawHTML>";
+ Result << "<rawHTML";
+ if (C->isMalformed())
+ Result << " isMalformed=\"1\"";
+ Result << ">";
+ {
+ SmallString<32> Tag;
+ {
+ llvm::raw_svector_ostream TagOS(Tag);
+ printHTMLStartTagComment(C, TagOS);
+ }
+ appendToResultWithCDATAEscaping(Tag);
+ }
+ Result << "</rawHTML>";
}
void
CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
- Result << "<rawHTML></" << C->getTagName() << "></rawHTML>";
+ Result << "<rawHTML";
+ if (C->isMalformed())
+ Result << " isMalformed=\"1\"";
+ Result << "></" << C->getTagName() << "></rawHTML>";
}
void
@@ -1100,6 +1114,31 @@
}
}
+void CommentASTToXMLConverter::appendToResultWithCDATAEscaping(StringRef S) {
+ if (S.empty())
+ return;
+
+ Result << "<![CDATA[";
+ while (!S.empty()) {
+ size_t Pos = S.find("]]>");
+ if (Pos == 0) {
+ Result << "]]]]><![CDATA[>";
+ S = S.drop_front(3);
+ continue;
+ }
+ if (Pos == StringRef::npos)
+ Pos = S.size();
+
+ Result << S.substr(0, Pos);
+
+ S = S.drop_front(Pos);
+ }
+ Result << "]]>";
+}
+
+CommentToXMLConverter::CommentToXMLConverter() : FormatInMemoryUniqueId(0) {}
+CommentToXMLConverter::~CommentToXMLConverter() {}
+
void CommentToXMLConverter::convertCommentToHTML(const FullComment *FC,
SmallVectorImpl<char> &HTML,
const ASTContext &Context) {
@@ -1111,7 +1150,7 @@
void CommentToXMLConverter::convertHTMLTagNodeToText(
const comments::HTMLTagComment *HTC, SmallVectorImpl<char> &Text,
const ASTContext &Context) {
- CommentASTToHTMLConverter Converter(0, Text,
+ CommentASTToHTMLConverter Converter(nullptr, Text,
Context.getCommentCommandTraits());
Converter.visit(HTC);
}
@@ -1119,13 +1158,10 @@
void CommentToXMLConverter::convertCommentToXML(const FullComment *FC,
SmallVectorImpl<char> &XML,
const ASTContext &Context) {
- if (!FormatContext) {
- FormatContext = new SimpleFormatContext(Context.getLangOpts());
- } else if ((FormatInMemoryUniqueId % 1000) == 0) {
- // Delete after some number of iterations, so the buffers don't grow
- // too large.
- delete FormatContext;
- FormatContext = new SimpleFormatContext(Context.getLangOpts());
+ if (!FormatContext || (FormatInMemoryUniqueId % 1000) == 0) {
+ // Create a new format context, or re-create it after some number of
+ // iterations, so the buffers don't grow too large.
+ FormatContext.reset(new SimpleFormatContext(Context.getLangOpts()));
}
CommentASTToXMLConverter Converter(FC, XML, Context.getCommentCommandTraits(),
diff --git a/lib/Index/SimpleFormatContext.h b/lib/Index/SimpleFormatContext.h
index fde43ae..147323a 100644
--- a/lib/Index/SimpleFormatContext.h
+++ b/lib/Index/SimpleFormatContext.h
@@ -51,8 +51,8 @@
llvm::MemoryBuffer::getMemBuffer(Content);
const FileEntry *Entry =
Files.getVirtualFile(Name, Source->getBufferSize(), 0);
- Sources.overrideFileContents(Entry, Source, true);
- assert(Entry != NULL);
+ Sources.overrideFileContents(Entry, Source);
+ assert(Entry != nullptr);
return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
}
diff --git a/lib/Index/USRGeneration.cpp b/lib/Index/USRGeneration.cpp
index 15aa875..7554bc6 100644
--- a/lib/Index/USRGeneration.cpp
+++ b/lib/Index/USRGeneration.cpp
@@ -109,7 +109,7 @@
bool ShouldGenerateLocation(const NamedDecl *D);
bool isLocal(const NamedDecl *D) {
- return D->getParentFunctionOrMethod() != 0;
+ return D->getParentFunctionOrMethod() != nullptr;
}
/// Generate the string component containing the location of the
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index 2d07428..f6c658e 100644
--- a/lib/Lex/HeaderMap.cpp
+++ b/lib/Lex/HeaderMap.cpp
@@ -79,10 +79,10 @@
const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) {
// If the file is too small to be a header map, ignore it.
unsigned FileSize = FE->getSize();
- if (FileSize <= sizeof(HMapHeader)) return 0;
+ if (FileSize <= sizeof(HMapHeader)) return nullptr;
std::unique_ptr<const llvm::MemoryBuffer> FileBuffer(FM.getBufferForFile(FE));
- if (!FileBuffer) return 0; // Unreadable file?
+ if (!FileBuffer) return nullptr; // Unreadable file?
const char *FileStart = FileBuffer->getBufferStart();
// We know the file is at least as big as the header, check it now.
@@ -98,9 +98,9 @@
Header->Version == llvm::ByteSwap_16(HMAP_HeaderVersion))
NeedsByteSwap = true; // Mixed endianness headermap.
else
- return 0; // Not a header map.
+ return nullptr; // Not a header map.
- if (Header->Reserved != 0) return 0;
+ if (Header->Reserved != 0) return nullptr;
// Okay, everything looks good, create the header map.
return new HeaderMap(FileBuffer.release(), NeedsByteSwap);
@@ -165,7 +165,7 @@
// Check for invalid index.
if (StrTabIdx >= FileBuffer->getBufferSize())
- return 0;
+ return nullptr;
// Otherwise, we have a valid pointer into the file. Just return it. We know
// that the "string" can not overrun the end of the file, because the buffer
@@ -205,7 +205,7 @@
SmallString<1024> Path;
StringRef Dest = lookupFilename(Filename, Path);
if (Dest.empty())
- return 0;
+ return nullptr;
return FM.getFile(Dest);
}
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index f081024..a1dbe49 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -18,6 +18,8 @@
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/FileSystem.h"
@@ -35,7 +37,7 @@
return ControllingMacro;
if (!ControllingMacroID || !External)
- return 0;
+ return nullptr;
ControllingMacro = External->GetIdentifier(ControllingMacroID);
return ControllingMacro;
@@ -53,8 +55,8 @@
SystemDirIdx = 0;
NoCurDirSearch = false;
- ExternalLookup = 0;
- ExternalSource = 0;
+ ExternalLookup = nullptr;
+ ExternalSource = nullptr;
NumIncluded = 0;
NumMultiIncludeFileOptzn = 0;
NumFrameworkLookups = NumSubFrameworkLookups = 0;
@@ -108,28 +110,37 @@
return HM;
}
- return 0;
+ return nullptr;
}
std::string HeaderSearch::getModuleFileName(Module *Module) {
- // If we don't have a module cache path, we can't do anything.
- if (ModuleCachePath.empty())
- return std::string();
-
-
- SmallString<256> Result(ModuleCachePath);
- llvm::sys::path::append(Result, Module->getTopLevelModule()->Name + ".pcm");
- return Result.str().str();
+ return getModuleFileName(Module->Name, Module->ModuleMap->getName());
}
-std::string HeaderSearch::getModuleFileName(StringRef ModuleName) {
+std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
+ StringRef ModuleMapPath) {
// If we don't have a module cache path, we can't do anything.
if (ModuleCachePath.empty())
return std::string();
-
-
+
SmallString<256> Result(ModuleCachePath);
- llvm::sys::path::append(Result, ModuleName + ".pcm");
+ llvm::sys::fs::make_absolute(Result);
+
+ if (HSOpts->DisableModuleHash) {
+ llvm::sys::path::append(Result, ModuleName + ".pcm");
+ } else {
+ // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
+ // be globally unique to this particular module. To avoid false-negatives
+ // on case-insensitive filesystems, we use lower-case, which is safe because
+ // to cause a collision the modules must have the same name, which is an
+ // error if they are imported in the same translation.
+ SmallString<256> AbsModuleMapPath(ModuleMapPath);
+ llvm::sys::fs::make_absolute(AbsModuleMapPath);
+ llvm::APInt Code(64, llvm::hash_value(AbsModuleMapPath.str().lower()));
+ SmallString<128> HashStr;
+ Code.toStringUnsigned(HashStr, /*Radix*/36);
+ llvm::sys::path::append(Result, ModuleName + "-" + HashStr.str() + ".pcm");
+ }
return Result.str().str();
}
@@ -266,12 +277,12 @@
// Concatenate the requested file onto the directory.
TmpDir = getDir()->getName();
llvm::sys::path::append(TmpDir, Filename);
- if (SearchPath != NULL) {
+ if (SearchPath) {
StringRef SearchPathRef(getDir()->getName());
SearchPath->clear();
SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
}
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin(), Filename.end());
}
@@ -290,7 +301,7 @@
SmallString<1024> Path;
StringRef Dest = HM->lookupFilename(Filename, Path);
if (Dest.empty())
- return 0;
+ return nullptr;
const FileEntry *Result;
@@ -309,12 +320,12 @@
}
if (Result) {
- if (SearchPath != NULL) {
+ if (SearchPath) {
StringRef SearchPathRef(getName());
SearchPath->clear();
SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
}
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin(), Filename.end());
}
@@ -386,7 +397,7 @@
// Framework names must have a '/' in the filename.
size_t SlashPos = Filename.find('/');
- if (SlashPos == StringRef::npos) return 0;
+ if (SlashPos == StringRef::npos) return nullptr;
// Find out if this is the home for the specified framework, by checking
// HeaderSearch. Possible answers are yes/no and unknown.
@@ -395,7 +406,7 @@
// If it is known and in some other directory, fail.
if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir())
- return 0;
+ return nullptr;
// Otherwise, construct the path to this framework dir.
@@ -413,12 +424,12 @@
FrameworkName += ".framework/";
// If the cache entry was unresolved, populate it now.
- if (CacheEntry.Directory == 0) {
+ if (!CacheEntry.Directory) {
HS.IncrementFrameworkLookupCount();
// If the framework dir doesn't exist, we fail.
const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
- if (Dir == 0) return 0;
+ if (!Dir) return nullptr;
// Otherwise, if it does, remember that this is the right direntry for this
// framework.
@@ -438,7 +449,7 @@
// Set the 'user-specified system framework' flag.
InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
}
@@ -448,7 +459,7 @@
FrameworkName += "Headers/";
- if (SearchPath != NULL) {
+ if (SearchPath) {
SearchPath->clear();
// Without trailing '/'.
SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
@@ -462,7 +473,7 @@
const char *Private = "Private";
FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
Private+strlen(Private));
- if (SearchPath != NULL)
+ if (SearchPath)
SearchPath->insert(SearchPath->begin()+OrigSize, Private,
Private+strlen(Private));
@@ -472,14 +483,9 @@
// If we found the header and are allowed to suggest a module, do so now.
if (FE && SuggestedModule) {
// Find the framework in which this header occurs.
- StringRef FrameworkPath = FE->getName();
+ StringRef FrameworkPath = FE->getDir()->getName();
bool FoundFramework = false;
do {
- // Get the parent directory name.
- FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
- if (FrameworkPath.empty())
- break;
-
// Determine whether this directory exists.
const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath);
if (!Dir)
@@ -491,6 +497,11 @@
FoundFramework = true;
break;
}
+
+ // Get the parent directory name.
+ FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
+ if (FrameworkPath.empty())
+ break;
} while (true);
if (FoundFramework) {
@@ -579,14 +590,14 @@
// If 'Filename' is absolute, check to see if it exists and no searching.
if (llvm::sys::path::is_absolute(Filename)) {
- CurDir = 0;
+ CurDir = nullptr;
// If this was an #include_next "/absolute/file", fail.
- if (FromDir) return 0;
+ if (FromDir) return nullptr;
- if (SearchPath != NULL)
+ if (SearchPath)
SearchPath->clear();
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin(), Filename.end());
}
@@ -595,7 +606,7 @@
}
// This is the header that MSVC's header search would have found.
- const FileEntry *MSFE = 0;
+ const FileEntry *MSFE = nullptr;
ModuleMap::KnownHeader MSSuggestedModule;
// Unless disabled, check to see if the file is in the #includer's
@@ -640,12 +651,12 @@
ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
ToHFI.Framework = Framework;
- if (SearchPath != NULL) {
+ if (SearchPath) {
StringRef SearchPathRef(Includer->getDir()->getName());
SearchPath->clear();
SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
}
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin(), Filename.end());
}
@@ -671,7 +682,7 @@
}
}
- CurDir = 0;
+ CurDir = nullptr;
// If this is a system #include, ignore the user #include locs.
unsigned i = isAngled ? AngledDirIdx : 0;
@@ -795,7 +806,7 @@
}
}
- if (checkMSVCHeaderSearch(Diags, MSFE, 0, IncludeLoc)) {
+ if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) {
if (SuggestedModule)
*SuggestedModule = MSSuggestedModule;
return MSFE;
@@ -803,7 +814,7 @@
// Otherwise, didn't find it. Remember we didn't find this.
CacheLookup.HitIdx = SearchDirs.size();
- return 0;
+ return nullptr;
}
/// LookupSubframeworkHeader - Look up a subframework for the specified
@@ -822,7 +833,7 @@
// Framework names must have a '/' in the filename. Find it.
// FIXME: Should we permit '\' on Windows?
size_t SlashPos = Filename.find('/');
- if (SlashPos == StringRef::npos) return 0;
+ if (SlashPos == StringRef::npos) return nullptr;
// Look up the base framework name of the ContextFileEnt.
const char *ContextName = ContextFileEnt->getName();
@@ -830,10 +841,10 @@
// If the context info wasn't a framework, couldn't be a subframework.
const unsigned DotFrameworkLen = 10;
const char *FrameworkPos = strstr(ContextName, ".framework");
- if (FrameworkPos == 0 ||
+ if (FrameworkPos == nullptr ||
(FrameworkPos[DotFrameworkLen] != '/' &&
FrameworkPos[DotFrameworkLen] != '\\'))
- return 0;
+ return nullptr;
SmallString<1024> FrameworkName(ContextName, FrameworkPos+DotFrameworkLen+1);
@@ -850,24 +861,24 @@
CacheLookup.getKeyLength() == FrameworkName.size() &&
memcmp(CacheLookup.getKeyData(), &FrameworkName[0],
CacheLookup.getKeyLength()) != 0)
- return 0;
+ return nullptr;
// Cache subframework.
- if (CacheLookup.getValue().Directory == 0) {
+ if (!CacheLookup.getValue().Directory) {
++NumSubFrameworkLookups;
// If the framework dir doesn't exist, we fail.
const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
- if (Dir == 0) return 0;
+ if (!Dir) return nullptr;
// Otherwise, if it does, remember that this is the right direntry for this
// framework.
CacheLookup.getValue().Directory = Dir;
}
- const FileEntry *FE = 0;
+ const FileEntry *FE = nullptr;
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
}
@@ -875,7 +886,7 @@
// Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"
SmallString<1024> HeadersFilename(FrameworkName);
HeadersFilename += "Headers/";
- if (SearchPath != NULL) {
+ if (SearchPath) {
SearchPath->clear();
// Without trailing '/'.
SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
@@ -887,7 +898,7 @@
// Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
HeadersFilename = FrameworkName;
HeadersFilename += "PrivateHeaders/";
- if (SearchPath != NULL) {
+ if (SearchPath) {
SearchPath->clear();
// Without trailing '/'.
SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
@@ -895,7 +906,7 @@
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true)))
- return 0;
+ return nullptr;
}
// This file is a system header or C++ unfriendly if the old file is.
@@ -1217,15 +1228,15 @@
case LMM_AlreadyLoaded:
case LMM_NoDirectory:
- return 0;
-
+ return nullptr;
+
case LMM_NewlyLoaded:
return ModMap.findModule(Name);
}
// Try to infer a module map from the framework directory.
- return ModMap.inferFrameworkModule(Name, Dir, IsSystem, /*Parent=*/0);
+ return ModMap.inferFrameworkModule(Name, Dir, IsSystem, /*Parent=*/nullptr);
}
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 86d01d6..21b51e1 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -10,19 +10,6 @@
// This file implements the Lexer and Token interfaces.
//
//===----------------------------------------------------------------------===//
-//
-// TODO: GCC Diagnostics emitted by the lexer:
-// PEDWARN: (form feed|vertical tab) in preprocessing directive
-//
-// Universal characters, unicode, char mapping:
-// WARNING: `%.*s' is not in NFKC
-// WARNING: `%.*s' is not in NFC
-//
-// Other:
-// TODO: Options to support:
-// -fexec-charset,-fwide-exec-charset
-//
-//===----------------------------------------------------------------------===//
#include "clang/Lex/Lexer.h"
#include "UnicodeCharSets.h"
@@ -174,7 +161,7 @@
/// expansion location that indicates where all lexed tokens should be
/// "expanded from".
///
-/// FIXME: It would really be nice to make _Pragma just be a wrapper around a
+/// TODO: It would really be nice to make _Pragma just be a wrapper around a
/// normal lexer that remaps tokens as they fly by. This would require making
/// Preprocessor::Lex virtual. Given that, we could just dump in a magic lexer
/// interface that could handle this stuff. This would pull GetMappedTokenLoc
@@ -379,10 +366,10 @@
const LangOptions &LangOpts, bool *Invalid) {
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
- const char *TokStart = 0;
+ const char *TokStart = nullptr;
// NOTE: this has to be checked *before* testing for an IdentifierInfo.
if (Tok.is(tok::raw_identifier))
- TokStart = Tok.getRawIdentifierData();
+ TokStart = Tok.getRawIdentifier().data();
else if (!Tok.hasUCN()) {
if (const IdentifierInfo *II = Tok.getIdentifierInfo()) {
// Just return the string from the identifier table, which is very quick.
@@ -395,7 +382,7 @@
if (Tok.isLiteral())
TokStart = Tok.getLiteralData();
- if (TokStart == 0) {
+ if (!TokStart) {
// Compute the start of the token in the input lexer buffer.
bool CharDataInvalid = false;
TokStart = SourceMgr.getCharacterData(Tok.getLocation(), &CharDataInvalid);
@@ -637,8 +624,7 @@
// the raw identifier to recognize and categorize preprocessor directives.
TheLexer.LexFromRawLexer(TheTok);
if (TheTok.getKind() == tok::raw_identifier && !TheTok.needsCleaning()) {
- StringRef Keyword(TheTok.getRawIdentifierData(),
- TheTok.getLength());
+ StringRef Keyword = TheTok.getRawIdentifier();
PreambleDirectiveKind PDK
= llvm::StringSwitch<PreambleDirectiveKind>(Keyword)
.Case("include", PDK_Skipped)
@@ -1287,7 +1273,7 @@
if (Ptr[0] == '?' && Ptr[1] == '?') {
// If this is actually a legal trigraph (not something like "??x"), emit
// a trigraph warning. If so, and if trigraphs are enabled, return it.
- if (char C = DecodeTrigraphChar(Ptr+2, Tok ? this : 0)) {
+ if (char C = DecodeTrigraphChar(Ptr+2, Tok ? this : nullptr)) {
// Remember that this token needs to be cleaned.
if (Tok) Tok->setFlag(Token::NeedsCleaning);
@@ -1450,7 +1436,7 @@
bool Lexer::tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size,
Token &Result) {
const char *UCNPtr = CurPtr + Size;
- uint32_t CodePoint = tryReadUCN(UCNPtr, CurPtr, /*Token=*/0);
+ uint32_t CodePoint = tryReadUCN(UCNPtr, CurPtr, /*Token=*/nullptr);
if (CodePoint == 0 || !isAllowedIDChar(CodePoint, LangOpts))
return false;
@@ -1733,7 +1719,8 @@
/// either " or L" or u8" or u" or U".
bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
tok::TokenKind Kind) {
- const char *NulCharacter = 0; // Does this string contain the \0 character?
+ // Does this string contain the \0 character?
+ const char *NulCharacter = nullptr;
if (!isLexingRawMode() &&
(Kind == tok::utf8_string_literal ||
@@ -1869,7 +1856,8 @@
/// LexAngledStringLiteral - Lex the remainder of an angled string literal,
/// after having lexed the '<' character. This is used for #include filenames.
bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
- const char *NulCharacter = 0; // Does this string contain the \0 character?
+ // Does this string contain the \0 character?
+ const char *NulCharacter = nullptr;
const char *AfterLessPos = CurPtr;
char C = getAndAdvanceChar(CurPtr, Result);
while (C != '>') {
@@ -1906,7 +1894,8 @@
/// lexed either ' or L' or u' or U'.
bool Lexer::LexCharConstant(Token &Result, const char *CurPtr,
tok::TokenKind Kind) {
- const char *NulCharacter = 0; // Does this character contain the \0 character?
+ // Does this character contain the \0 character?
+ const char *NulCharacter = nullptr;
if (!isLexingRawMode() &&
(Kind == tok::utf16_char_constant || Kind == tok::utf32_char_constant))
@@ -2251,8 +2240,6 @@
#ifdef __SSE2__
#include <emmintrin.h>
-#elif __AVX2__
-#include <avx2intrin.h>
#elif __ALTIVEC__
#include <altivec.h>
#undef bool
@@ -2308,33 +2295,17 @@
// If there is a code-completion point avoid the fast scan because it
// doesn't check for '\0'.
!(PP && PP->getCodeCompletionFileLoc() == FileLoc)) {
-#ifndef __AVX2__
// While not aligned to a 16-byte boundary.
while (C != '/' && ((intptr_t)CurPtr & 0x0F) != 0)
C = *CurPtr++;
-#endif
if (C == '/') goto FoundSlash;
#ifdef __SSE2__
-#define VECTOR_TYPE __m128i
-#define SET1_EPI8(v) _mm_set1_epi8(v)
-#define CMPEQ_EPI8(v1,v2) _mm_cmpeq_epi8(v1,v2)
-#define MOVEMASK_EPI8(v) _mm_movemask_epi8(v)
-#define STEP 16
-#elif __AVX2__
-#define VECTOR_TYPE __m256i
-#define SET1_EPI8(v) _mm256_set1_epi8(v)
-#define CMPEQ_EPI8(v1,v2) _mm256_cmpeq_epi8(v1,v2)
-#define MOVEMASK_EPI8(v) _mm256_movemask_epi8(v)
-#define STEP 32
-#endif
-
-#if defined(__SSE2__) || defined(__AVX2__)
- VECTOR_TYPE Slashes = SET1_EPI8('/');
- while (CurPtr+STEP <= BufferEnd) {
- int cmp = MOVEMASK_EPI8(CMPEQ_EPI8(*(const VECTOR_TYPE*)CurPtr,
- Slashes));
+ __m128i Slashes = _mm_set1_epi8('/');
+ while (CurPtr+16 <= BufferEnd) {
+ int cmp = _mm_movemask_epi8(_mm_cmpeq_epi8(*(const __m128i*)CurPtr,
+ Slashes));
if (cmp != 0) {
// Adjust the pointer to point directly after the first slash. It's
// not necessary to set C here, it will be overwritten at the end of
@@ -2342,13 +2313,8 @@
CurPtr += llvm::countTrailingZeros<unsigned>(cmp) + 1;
goto FoundSlash;
}
- CurPtr += STEP;
+ CurPtr += 16;
}
-#undef VECTOR_TYPE
-#undef SET1_EPI8
-#undef CMPEQ_EPI8
-#undef MOVEMASK_EPI8
-#undef STEP
#elif __ALTIVEC__
__vector unsigned char Slashes = {
'/', '/', '/', '/', '/', '/', '/', '/',
@@ -2630,7 +2596,7 @@
}
return RestOfBuffer.data()+Pos;
}
- return 0;
+ return nullptr;
}
/// IsStartOfConflictMarker - If the specified pointer is the start of a version
@@ -2940,7 +2906,7 @@
LexNextToken:
// New token, can't need cleaning yet.
Result.clearFlag(Token::NeedsCleaning);
- Result.setIdentifierInfo(0);
+ Result.setIdentifierInfo(nullptr);
// CurPtr - Cache BufferPtr in an automatic variable.
const char *CurPtr = BufferPtr;
@@ -3406,7 +3372,7 @@
// We parsed a # character. If this occurs at the start of the line,
// it's actually the start of a preprocessing directive. Callback to
// the preprocessor to handle it.
- // FIXME: -fpreprocessed mode??
+ // TODO: -fpreprocessed mode??
if (TokAtPhysicalStartOfLine && !LexingRawMode && !Is_PragmaLexer)
goto HandleDirective;
@@ -3572,7 +3538,7 @@
// We parsed a # character. If this occurs at the start of the line,
// it's actually the start of a preprocessing directive. Callback to
// the preprocessor to handle it.
- // FIXME: -fpreprocessed mode??
+ // TODO: -fpreprocessed mode??
if (TokAtPhysicalStartOfLine && !LexingRawMode && !Is_PragmaLexer)
goto HandleDirective;
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index ddfa10c..8550198 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -195,7 +195,7 @@
<< std::string(1, ResultChar);
break;
default:
- if (Diags == 0)
+ if (!Diags)
break;
if (isPrintable(ResultChar))
@@ -340,7 +340,7 @@
FullSourceLoc Loc;
if (!ProcessUCNEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, UcnVal,
- UcnLen, Loc, 0, Features, true)) {
+ UcnLen, Loc, nullptr, Features, true)) {
HadError = true;
return 0;
}
@@ -571,7 +571,7 @@
// Parse the suffix. At this point we can classify whether we have an FP or
// integer constant.
bool isFPConstant = isFloatingLiteral();
- const char *ImaginarySuffixLoc = 0;
+ const char *ImaginarySuffixLoc = nullptr;
// Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop.
@@ -765,6 +765,7 @@
s++;
saw_period = true;
const char *floatDigitsBegin = s;
+ checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = SkipHexDigits(s);
noSignificand &= (floatDigitsBegin == s);
}
@@ -779,6 +780,7 @@
// A binary exponent can appear with or with a '.'. If dotted, the
// binary exponent is required.
if (*s == 'p' || *s == 'P') {
+ checkSeparator(TokLoc, s, CSK_AfterDigits);
const char *Exponent = s;
s++;
saw_exponent = true;
@@ -790,6 +792,7 @@
hadError = true;
return;
}
+ checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = first_non_digit;
if (!PP.getLangOpts().HexFloats)
@@ -858,9 +861,11 @@
s++;
radix = 10;
saw_period = true;
+ checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = SkipDigits(s); // Skip suffix.
}
if (*s == 'e' || *s == 'E') { // exponent
+ checkSeparator(TokLoc, s, CSK_AfterDigits);
const char *Exponent = s;
s++;
radix = 10;
@@ -868,6 +873,7 @@
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s);
if (first_non_digit != s) {
+ checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = first_non_digit;
} else {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
@@ -1248,7 +1254,7 @@
StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
Preprocessor &PP, bool Complain)
: SM(PP.getSourceManager()), Features(PP.getLangOpts()),
- Target(PP.getTargetInfo()), Diags(Complain ? &PP.getDiagnostics() : 0),
+ Target(PP.getTargetInfo()), Diags(Complain ? &PP.getDiagnostics() :nullptr),
MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown),
ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) {
init(StringToks, NumStringToks);
@@ -1571,8 +1577,7 @@
Dummy.reserve(Fragment.size() * CharByteWidth);
char *Ptr = Dummy.data();
- while (!Builder.hasMaxRanges() &&
- !ConvertUTF8toWide(CharByteWidth, NextFragment, Ptr, ErrorPtrTmp)) {
+ while (!ConvertUTF8toWide(CharByteWidth, NextFragment, Ptr, ErrorPtrTmp)) {
const char *ErrorPtr = reinterpret_cast<const char *>(ErrorPtrTmp);
NextStart = resyncUTF8(ErrorPtr, Fragment.end());
Builder << MakeCharSourceRange(Features, SourceLoc, TokBegin,
diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp
index d2dc04b..a746fb7 100644
--- a/lib/Lex/MacroArgs.cpp
+++ b/lib/Lex/MacroArgs.cpp
@@ -1,4 +1,4 @@
-//===--- TokenLexer.cpp - Lex from a token stream -------------------------===//
+//===--- MacroArgs.cpp - Formal argument info for Macros ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the TokenLexer interface.
+// This file implements the MacroArgs interface.
//
//===----------------------------------------------------------------------===//
@@ -27,7 +27,7 @@
bool VarargsElided, Preprocessor &PP) {
assert(MI->isFunctionLike() &&
"Can't have args for an object-like macro!");
- MacroArgs **ResultEnt = 0;
+ MacroArgs **ResultEnt = nullptr;
unsigned ClosestMatch = ~0U;
// See if we have an entry with a big enough argument list to reuse on the
@@ -46,7 +46,7 @@
}
MacroArgs *Result;
- if (ResultEnt == 0) {
+ if (!ResultEnt) {
// Allocate memory for a MacroArgs object with the lexer tokens at the end.
Result = (MacroArgs*)malloc(sizeof(MacroArgs) +
UnexpArgTokens.size() * sizeof(Token));
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index 0325a80..cb39456 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -17,7 +17,7 @@
MacroInfo::MacroInfo(SourceLocation DefLoc)
: Location(DefLoc),
- ArgumentList(0),
+ ArgumentList(nullptr),
NumArguments(0),
IsDefinitionLengthCached(false),
IsFunctionLike(false),
@@ -29,7 +29,8 @@
IsUsed(false),
IsAllowRedefinitionsWithoutWarning(false),
IsWarnIfUnused(false),
- FromASTFile(false) {
+ FromASTFile(false),
+ UsedForHeaderGuard(false) {
}
unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
@@ -144,7 +145,8 @@
isPublic = VisMD->isPublic();
}
- return DefInfo(0, UndefLoc, !isPublic.hasValue() || isPublic.getValue());
+ return DefInfo(nullptr, UndefLoc,
+ !isPublic.hasValue() || isPublic.getValue());
}
const MacroDirective::DefInfo
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index e78806d..0538d33 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -42,7 +42,7 @@
// We may have just a wildcard.
if (Unresolved.Id.empty()) {
assert(Unresolved.Wildcard && "Invalid unresolved export");
- return Module::ExportDecl(0, true);
+ return Module::ExportDecl(nullptr, true);
}
// Resolve the module-id.
@@ -62,7 +62,7 @@
Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
<< Id[0].first << Mod->getFullModuleName();
- return 0;
+ return nullptr;
}
// Dig into the module path.
@@ -74,7 +74,7 @@
<< Id[I].first << Context->getFullModuleName()
<< SourceRange(Id[0].second, Id[I-1].second);
- return 0;
+ return nullptr;
}
Context = Sub;
@@ -87,8 +87,8 @@
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo)
: SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
- HeaderInfo(HeaderInfo), BuiltinIncludeDir(0), CompilingModule(0),
- SourceModule(0) {}
+ HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
+ CompilingModule(nullptr), SourceModule(nullptr) {}
ModuleMap::~ModuleMap() {
for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
@@ -170,6 +170,38 @@
return Known;
}
+ModuleMap::KnownHeader
+ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
+ SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
+ const DirectoryEntry *Dir = File->getDir();
+ assert(Dir && "file in no directory");
+
+ // Note: as an egregious but useful hack we use the real path here, because
+ // frameworks moving from top-level frameworks to embedded frameworks tend
+ // to be symlinked from the top-level location to the embedded location,
+ // and we need to resolve lookups as if we had found the embedded location.
+ StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
+
+ // Keep walking up the directory hierarchy, looking for a directory with
+ // an umbrella header.
+ do {
+ auto KnownDir = UmbrellaDirs.find(Dir);
+ if (KnownDir != UmbrellaDirs.end())
+ return KnownHeader(KnownDir->second, NormalHeader);
+
+ IntermediateDirs.push_back(Dir);
+
+ // Retrieve our parent path.
+ DirName = llvm::sys::path::parent_path(DirName);
+ if (DirName.empty())
+ break;
+
+ // Resolve the parent path to a directory entry.
+ Dir = SourceMgr.getFileManager().getDirectory(DirName);
+ } while (Dir);
+ return KnownHeader();
+}
+
// Returns 'true' if 'RequestingModule directly uses 'RequestedModule'.
static bool directlyUses(const Module *RequestingModule,
const Module *RequestedModule) {
@@ -198,69 +230,87 @@
RequestedModule->getTopLevelModule() != RequestingModule;
}
+static Module *getTopLevelOrNull(Module *M) {
+ return M ? M->getTopLevelModule() : nullptr;
+}
+
void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
SourceLocation FilenameLoc,
StringRef Filename,
const FileEntry *File) {
// No errors for indirect modules. This may be a bit of a problem for modules
// with no source files.
- if (RequestingModule != SourceModule)
+ if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
return;
if (RequestingModule)
resolveUses(RequestingModule, /*Complain=*/false);
+ bool Excluded = false;
+ Module *Private = nullptr;
+ Module *NotUsed = nullptr;
+
HeadersMap::iterator Known = findKnownHeader(File);
- if (Known == Headers.end())
- return;
+ if (Known != Headers.end()) {
+ for (const KnownHeader &Header : Known->second) {
+ // Excluded headers don't really belong to a module.
+ if (Header.getRole() == ModuleMap::ExcludedHeader) {
+ Excluded = true;
+ continue;
+ }
- Module *Private = NULL;
- Module *NotUsed = NULL;
- for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(),
- E = Known->second.end();
- I != E; ++I) {
- // Excluded headers don't really belong to a module.
- if (I->getRole() == ModuleMap::ExcludedHeader)
- continue;
+ // If 'File' is part of 'RequestingModule' we can definitely include it.
+ if (Header.getModule() == RequestingModule)
+ return;
- // If 'File' is part of 'RequestingModule' we can definitely include it.
- if (I->getModule() == RequestingModule)
+ // Remember private headers for later printing of a diagnostic.
+ if (violatesPrivateInclude(RequestingModule, File, Header.getRole(),
+ Header.getModule())) {
+ Private = Header.getModule();
+ continue;
+ }
+
+ // If uses need to be specified explicitly, we are only allowed to return
+ // modules that are explicitly used by the requesting module.
+ if (RequestingModule && LangOpts.ModulesDeclUse &&
+ !directlyUses(RequestingModule, Header.getModule())) {
+ NotUsed = Header.getModule();
+ continue;
+ }
+
+ // We have found a module that we can happily use.
return;
-
- // Remember private headers for later printing of a diagnostic.
- if (violatesPrivateInclude(RequestingModule, File, I->getRole(),
- I->getModule())) {
- Private = I->getModule();
- continue;
}
-
- // If uses need to be specified explicitly, we are only allowed to return
- // modules that are explicitly used by the requesting module.
- if (RequestingModule && LangOpts.ModulesDeclUse &&
- !directlyUses(RequestingModule, I->getModule())) {
- NotUsed = I->getModule();
- continue;
- }
-
- // We have found a module that we can happily use.
- return;
}
// We have found a header, but it is private.
- if (Private != NULL) {
+ if (Private) {
Diags.Report(FilenameLoc, diag::error_use_of_private_header_outside_module)
<< Filename;
return;
}
// We have found a module, but we don't use it.
- if (NotUsed != NULL) {
+ if (NotUsed) {
Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
<< RequestingModule->getFullModuleName() << Filename;
return;
}
- // Headers for which we have not found a module are fine to include.
+ if (Excluded || isHeaderInUmbrellaDirs(File))
+ return;
+
+ // At this point, only non-modular includes remain.
+
+ if (LangOpts.ModulesStrictDeclUse) {
+ Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
+ << RequestingModule->getFullModuleName() << Filename;
+ } else if (RequestingModule) {
+ diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
+ diag::warn_non_modular_include_in_framework_module :
+ diag::warn_non_modular_include_in_module;
+ Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName();
+ }
}
ModuleMap::KnownHeader
@@ -305,121 +355,111 @@
return Result;
}
- const DirectoryEntry *Dir = File->getDir();
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
+ KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
+ if (H) {
+ Module *Result = H.getModule();
- // Note: as an egregious but useful hack we use the real path here, because
- // frameworks moving from top-level frameworks to embedded frameworks tend
- // to be symlinked from the top-level location to the embedded location,
- // and we need to resolve lookups as if we had found the embedded location.
- StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
+ // Search up the module stack until we find a module with an umbrella
+ // directory.
+ Module *UmbrellaModule = Result;
+ while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
+ UmbrellaModule = UmbrellaModule->Parent;
- // Keep walking up the directory hierarchy, looking for a directory with
- // an umbrella header.
- do {
- llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
- = UmbrellaDirs.find(Dir);
- if (KnownDir != UmbrellaDirs.end()) {
- Module *Result = KnownDir->second;
-
- // Search up the module stack until we find a module with an umbrella
- // directory.
- Module *UmbrellaModule = Result;
- while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
- UmbrellaModule = UmbrellaModule->Parent;
+ if (UmbrellaModule->InferSubmodules) {
+ // Infer submodules for each of the directories we found between
+ // the directory of the umbrella header and the directory where
+ // the actual header is located.
+ bool Explicit = UmbrellaModule->InferExplicitSubmodules;
- if (UmbrellaModule->InferSubmodules) {
- // Infer submodules for each of the directories we found between
- // the directory of the umbrella header and the directory where
- // the actual header is located.
- bool Explicit = UmbrellaModule->InferExplicitSubmodules;
-
- for (unsigned I = SkippedDirs.size(); I != 0; --I) {
- // Find or create the module that corresponds to this directory name.
- SmallString<32> NameBuf;
- StringRef Name = sanitizeFilenameAsIdentifier(
- llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
- NameBuf);
- Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
- Explicit).first;
-
- // Associate the module and the directory.
- UmbrellaDirs[SkippedDirs[I-1]] = Result;
-
- // If inferred submodules export everything they import, add a
- // wildcard to the set of exports.
- if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
- Result->Exports.push_back(Module::ExportDecl(0, true));
- }
-
- // Infer a submodule with the same name as this header file.
+ for (unsigned I = SkippedDirs.size(); I != 0; --I) {
+ // Find or create the module that corresponds to this directory name.
SmallString<32> NameBuf;
StringRef Name = sanitizeFilenameAsIdentifier(
- llvm::sys::path::stem(File->getName()), NameBuf);
- Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
- Explicit).first;
- Result->addTopHeader(File);
-
- // If inferred submodules export everything they import, add a
+ llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
+ Result = findOrCreateModule(Name, Result, UmbrellaModule->ModuleMap,
+ /*IsFramework=*/false, Explicit).first;
+ Result->IsInferred = true;
+
+ // Associate the module and the directory.
+ UmbrellaDirs[SkippedDirs[I-1]] = Result;
+
+ // If inferred submodules export everything they import, add a
// wildcard to the set of exports.
if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
- Result->Exports.push_back(Module::ExportDecl(0, true));
- } else {
- // Record each of the directories we stepped through as being part of
- // the module we found, since the umbrella header covers them all.
- for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
- UmbrellaDirs[SkippedDirs[I]] = Result;
+ Result->Exports.push_back(Module::ExportDecl(nullptr, true));
}
-
- Headers[File].push_back(KnownHeader(Result, NormalHeader));
- // If a header corresponds to an unavailable module, don't report
- // that it maps to anything.
- if (!Result->isAvailable())
- return KnownHeader();
+ // Infer a submodule with the same name as this header file.
+ SmallString<32> NameBuf;
+ StringRef Name = sanitizeFilenameAsIdentifier(
+ llvm::sys::path::stem(File->getName()), NameBuf);
+ Result = findOrCreateModule(Name, Result, UmbrellaModule->ModuleMap,
+ /*IsFramework=*/false, Explicit).first;
+ Result->IsInferred = true;
+ Result->addTopHeader(File);
- return Headers[File].back();
+ // If inferred submodules export everything they import, add a
+ // wildcard to the set of exports.
+ if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
+ Result->Exports.push_back(Module::ExportDecl(nullptr, true));
+ } else {
+ // Record each of the directories we stepped through as being part of
+ // the module we found, since the umbrella header covers them all.
+ for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
+ UmbrellaDirs[SkippedDirs[I]] = Result;
}
-
- SkippedDirs.push_back(Dir);
-
- // Retrieve our parent path.
- DirName = llvm::sys::path::parent_path(DirName);
- if (DirName.empty())
- break;
-
- // Resolve the parent path to a directory entry.
- Dir = SourceMgr.getFileManager().getDirectory(DirName);
- } while (Dir);
+
+ Headers[File].push_back(KnownHeader(Result, NormalHeader));
+
+ // If a header corresponds to an unavailable module, don't report
+ // that it maps to anything.
+ if (!Result->isAvailable())
+ return KnownHeader();
+
+ return Headers[File].back();
+ }
return KnownHeader();
}
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
+ return isHeaderUnavailableInModule(Header, nullptr);
+}
+
+bool
+ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
+ const Module *RequestingModule) const {
HeadersMap::const_iterator Known = Headers.find(Header);
if (Known != Headers.end()) {
for (SmallVectorImpl<KnownHeader>::const_iterator
I = Known->second.begin(),
E = Known->second.end();
I != E; ++I) {
- if (I->isAvailable())
+ if (I->isAvailable() && (!RequestingModule ||
+ I->getModule()->isSubModuleOf(RequestingModule)))
return false;
}
return true;
}
-
+
const DirectoryEntry *Dir = Header->getDir();
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
StringRef DirName = Dir->getName();
+ auto IsUnavailable = [&](const Module *M) {
+ return !M->isAvailable() && (!RequestingModule ||
+ M->isSubModuleOf(RequestingModule));
+ };
+
// Keep walking up the directory hierarchy, looking for a directory with
// an umbrella header.
- do {
+ do {
llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
= UmbrellaDirs.find(Dir);
if (KnownDir != UmbrellaDirs.end()) {
Module *Found = KnownDir->second;
- if (!Found->isAvailable())
+ if (IsUnavailable(Found))
return true;
// Search up the module stack until we find a module with an umbrella
@@ -438,7 +478,7 @@
Found = lookupModuleQualified(Name, Found);
if (!Found)
return false;
- if (!Found->isAvailable())
+ if (IsUnavailable(Found))
return true;
}
@@ -452,7 +492,7 @@
return false;
}
- return !Found->isAvailable();
+ return IsUnavailable(Found);
}
SkippedDirs.push_back(Dir);
@@ -473,8 +513,8 @@
llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
if (Known != Modules.end())
return Known->getValue();
-
- return 0;
+
+ return nullptr;
}
Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
@@ -495,15 +535,16 @@
}
std::pair<Module *, bool>
-ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
+ModuleMap::findOrCreateModule(StringRef Name, Module *Parent,
+ const FileEntry *ModuleMap, bool IsFramework,
bool IsExplicit) {
// Try to find an existing module with this name.
if (Module *Sub = lookupModuleQualified(Name, Parent))
return std::make_pair(Sub, false);
// Create a new module with this name.
- Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
- IsExplicit);
+ Module *Result = new Module(Name, SourceLocation(), Parent, ModuleMap,
+ IsFramework, IsExplicit);
if (LangOpts.CurrentModule == Name) {
SourceModule = Result;
SourceModuleName = Name;
@@ -572,6 +613,7 @@
// If the framework has a parent path from which we're allowed to infer
// a framework module, do so.
+ const FileEntry *ModuleMapFile = nullptr;
if (!Parent) {
// Determine whether we're allowed to infer a module map.
@@ -616,14 +658,16 @@
if (inferred->second.InferSystemModules)
IsSystem = true;
+ ModuleMapFile = inferred->second.ModuleMapFile;
}
}
}
// If we're not allowed to infer a framework module, don't.
if (!canInfer)
- return 0;
- }
+ return nullptr;
+ } else
+ ModuleMapFile = Parent->ModuleMap;
// Look for an umbrella header.
@@ -635,9 +679,9 @@
// framework to load *everything*. But, it's not clear that this is a good
// idea.
if (!UmbrellaHeader)
- return 0;
-
- Module *Result = new Module(ModuleName, SourceLocation(), Parent,
+ return nullptr;
+
+ Module *Result = new Module(ModuleName, SourceLocation(), Parent, ModuleMapFile,
/*IsFramework=*/true, /*IsExplicit=*/false);
if (LangOpts.CurrentModule == ModuleName) {
SourceModule = Result;
@@ -655,8 +699,8 @@
UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
// export *
- Result->Exports.push_back(Module::ExportDecl(0, true));
-
+ Result->Exports.push_back(Module::ExportDecl(nullptr, true));
+
// module * { export * }
Result->InferSubmodules = true;
Result->InferExportWildcard = true;
@@ -743,7 +787,7 @@
const FileEntry *
ModuleMap::getContainingModuleMapFile(Module *Module) const {
if (Module->DefinitionLoc.isInvalid())
- return 0;
+ return nullptr;
return SourceMgr.getFileEntryForID(
SourceMgr.getFileID(Module->DefinitionLoc));
@@ -820,14 +864,13 @@
Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
if (Loc.isInvalid())
- return 0;
-
+ return nullptr;
+
// Use the expansion location to determine which module we're in.
FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
if (!ExpansionLoc.isFileID())
- return 0;
-
-
+ return nullptr;
+
const SourceManager &SrcMgr = Loc.getManager();
FileID ExpansionFileID = ExpansionLoc.getFileID();
@@ -841,12 +884,12 @@
// any included header has an associated module.
SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
if (IncludeLoc.isInvalid())
- return 0;
-
+ return nullptr;
+
ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
}
-
- return 0;
+
+ return nullptr;
}
//----------------------------------------------------------------------------//
@@ -892,7 +935,7 @@
Kind = EndOfFile;
Location = 0;
StringLength = 0;
- StringData = 0;
+ StringData = nullptr;
}
bool is(TokenKind K) const { return Kind == K; }
@@ -931,6 +974,9 @@
DiagnosticsEngine &Diags;
ModuleMap ⤅
+
+ /// \brief The current module map file.
+ const FileEntry *ModuleMapFile;
/// \brief The directory that this module map resides in.
const DirectoryEntry *Directory;
@@ -976,20 +1022,20 @@
void parseConflict();
void parseInferredModuleDecl(bool Framework, bool Explicit);
bool parseOptionalAttributes(Attributes &Attrs);
-
- const DirectoryEntry *getOverriddenHeaderSearchDir();
public:
explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
const TargetInfo *Target,
DiagnosticsEngine &Diags,
ModuleMap &Map,
+ const FileEntry *ModuleMapFile,
const DirectoryEntry *Directory,
const DirectoryEntry *BuiltinIncludeDir,
bool IsSystem)
: L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
- Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
- IsSystem(IsSystem), HadError(false), ActiveModule(0)
+ ModuleMapFile(ModuleMapFile), Directory(Directory),
+ BuiltinIncludeDir(BuiltinIncludeDir), IsSystem(IsSystem),
+ HadError(false), ActiveModule(nullptr)
{
Tok.clear();
consumeToken();
@@ -1008,10 +1054,11 @@
L.LexFromRawLexer(LToken);
Tok.Location = LToken.getLocation().getRawEncoding();
switch (LToken.getKind()) {
- case tok::raw_identifier:
- Tok.StringData = LToken.getRawIdentifierData();
- Tok.StringLength = LToken.getLength();
- Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
+ case tok::raw_identifier: {
+ StringRef RI = LToken.getRawIdentifier();
+ Tok.StringData = RI.data();
+ Tok.StringLength = RI.size();
+ Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
.Case("config_macros", MMToken::ConfigMacros)
.Case("conflict", MMToken::Conflict)
.Case("exclude", MMToken::ExcludeKeyword)
@@ -1028,6 +1075,7 @@
.Case("use", MMToken::UseKeyword)
.Default(MMToken::Identifier);
break;
+ }
case tok::comma:
Tok.Kind = MMToken::Comma;
@@ -1273,7 +1321,7 @@
if (Id.size() > 1) {
// This module map defines a submodule. Go find the module of which it
// is a submodule.
- ActiveModule = 0;
+ ActiveModule = nullptr;
for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
ActiveModule = Next;
@@ -1336,9 +1384,14 @@
return;
}
+ // If this is a submodule, use the parent's module map, since we don't want
+ // the private module map file.
+ const FileEntry *ModuleMap = ActiveModule ? ActiveModule->ModuleMap
+ : ModuleMapFile;
+
// Start defining this module.
- ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
- Explicit).first;
+ ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, ModuleMap,
+ Framework, Explicit).first;
ActiveModule->DefinitionLoc = ModuleNameLoc;
if (Attrs.IsSystem || IsSystem)
ActiveModule->IsSystem = true;
@@ -1441,6 +1494,15 @@
inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
}
+ // If the module meets all requirements but is still unavailable, mark the
+ // whole tree as unavailable to prevent it from building.
+ if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
+ ActiveModule->Parent) {
+ ActiveModule->getTopLevelModule()->markUnavailable();
+ ActiveModule->getTopLevelModule()->MissingHeaders.append(
+ ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
+ }
+
// We're done parsing this module. Pop back to the previous module.
ActiveModule = PreviousActiveModule;
}
@@ -1585,16 +1647,12 @@
}
// Look for this file.
- const FileEntry *File = 0;
- const FileEntry *BuiltinFile = 0;
+ const FileEntry *File = nullptr;
+ const FileEntry *BuiltinFile = nullptr;
SmallString<128> PathName;
if (llvm::sys::path::is_absolute(Header.FileName)) {
PathName = Header.FileName;
File = SourceMgr.getFileManager().getFile(PathName);
- } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
- PathName = Dir->getName();
- llvm::sys::path::append(PathName, Header.FileName);
- File = SourceMgr.getFileManager().getFile(PathName);
} else {
// Search for the header file within the search directory.
PathName = Directory->getName();
@@ -1633,7 +1691,7 @@
// up adding both (later).
if (!File && BuiltinFile) {
File = BuiltinFile;
- BuiltinFile = 0;
+ BuiltinFile = nullptr;
}
}
}
@@ -1673,9 +1731,8 @@
// If we find a module that has a missing header, we mark this module as
// unavailable and store the header directive for displaying diagnostics.
- // Other submodules in the same module can still be used.
Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
- ActiveModule->IsAvailable = false;
+ ActiveModule->markUnavailable();
ActiveModule->MissingHeaders.push_back(Header);
}
}
@@ -1705,7 +1762,7 @@
}
// Look for this file.
- const DirectoryEntry *Dir = 0;
+ const DirectoryEntry *Dir = nullptr;
if (llvm::sys::path::is_absolute(DirName))
Dir = SourceMgr.getFileManager().getDirectory(DirName);
else {
@@ -1948,7 +2005,8 @@
if (ActiveModule) {
// Inferred modules must have umbrella directories.
- if (!Failed && !ActiveModule->getUmbrellaDir()) {
+ if (!Failed && ActiveModule->IsAvailable &&
+ !ActiveModule->getUmbrellaDir()) {
Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
Failed = true;
}
@@ -1997,6 +2055,7 @@
// We'll be inferring framework modules for this directory.
Map.InferredDirectories[Directory].InferModules = true;
Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
+ Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
// FIXME: Handle the 'framework' keyword.
}
@@ -2020,7 +2079,7 @@
case MMToken::ExcludeKeyword: {
if (ActiveModule) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
- << (ActiveModule != 0);
+ << (ActiveModule != nullptr);
consumeToken();
break;
}
@@ -2040,7 +2099,7 @@
case MMToken::ExportKeyword:
if (!ActiveModule) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
- << (ActiveModule != 0);
+ << (ActiveModule != nullptr);
consumeToken();
break;
}
@@ -2061,7 +2120,7 @@
case MMToken::UmbrellaKeyword:
default:
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
- << (ActiveModule != 0);
+ << (ActiveModule != nullptr);
consumeToken();
break;
}
@@ -2146,22 +2205,6 @@
return HadError;
}
-/// \brief If there is a specific header search directory due the presence
-/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
-const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
- for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
- // If we have an umbrella directory, use that.
- if (Mod->hasUmbrellaDir())
- return Mod->getUmbrellaDir();
-
- // If we have a framework directory, stop looking.
- if (Mod->IsFramework)
- return 0;
- }
-
- return 0;
-}
-
/// \brief Parse a module map file.
///
/// module-map-file:
@@ -2213,7 +2256,7 @@
if (Known != ParsedModuleMap.end())
return Known->second;
- assert(Target != 0 && "Missing target information");
+ assert(Target && "Missing target information");
auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
FileID ID = SourceMgr.createFileID(File, SourceLocation(), FileCharacter);
const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
@@ -2233,7 +2276,7 @@
// Parse this module map file.
Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts);
- ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, Dir,
+ ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
BuiltinIncludeDir, IsSystem);
bool Result = Parser.parseModuleMapFile();
ParsedModuleMap[File] = Result;
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 57dc495..a7a4bbc 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -45,7 +45,7 @@
}
MIChain->Next = MIChainHead;
- MIChain->Prev = 0;
+ MIChain->Prev = nullptr;
if (MIChainHead)
MIChainHead->Prev = MIChain;
MIChainHead = MIChain;
@@ -111,7 +111,7 @@
else {
assert(MIChainHead == MIChain);
MIChainHead = MIChain->Next;
- MIChainHead->Prev = 0;
+ MIChainHead->Prev = nullptr;
}
MIChain->Next = MICache;
MICache = MIChain;
@@ -129,6 +129,51 @@
} while (Tmp.isNot(tok::eod));
}
+bool Preprocessor::CheckMacroName(Token &MacroNameTok, char isDefineUndef) {
+ // Missing macro name?
+ if (MacroNameTok.is(tok::eod))
+ return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
+
+ IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
+ if (!II) {
+ bool Invalid = false;
+ std::string Spelling = getSpelling(MacroNameTok, &Invalid);
+ if (Invalid)
+ return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
+
+ const IdentifierInfo &Info = Identifiers.get(Spelling);
+
+ // Allow #defining |and| and friends in microsoft mode.
+ if (Info.isCPlusPlusOperatorKeyword() && getLangOpts().MSVCCompat) {
+ MacroNameTok.setIdentifierInfo(getIdentifierInfo(Spelling));
+ return false;
+ }
+
+ if (Info.isCPlusPlusOperatorKeyword())
+ // C++ 2.5p2: Alternative tokens behave the same as its primary token
+ // except for their spellings.
+ return Diag(MacroNameTok, diag::err_pp_operator_used_as_macro_name)
+ << Spelling << MacroNameTok.getKind();
+
+ return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
+ }
+
+ if (isDefineUndef && II->getPPKeywordID() == tok::pp_defined) {
+ // Error if defining "defined": C99 6.10.8/4, C++ [cpp.predefined]p4.
+ return Diag(MacroNameTok, diag::err_defined_macro_name);
+ }
+
+ if (isDefineUndef == 2 && II->hasMacroDefinition() &&
+ getMacroInfo(II)->isBuiltinMacro()) {
+ // Warn if undefining "__LINE__" and other builtins, per C99 6.10.8/4
+ // and C++ [cpp.predefined]p4], but allow it as an extension.
+ Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
+ }
+
+ // Okay, we got a good identifier.
+ return false;
+}
+
/// \brief Lex and validate a macro name, which occurs after a
/// \#define or \#undef.
///
@@ -146,53 +191,16 @@
setCodeCompletionReached();
LexUnexpandedToken(MacroNameTok);
}
-
- // Missing macro name?
- if (MacroNameTok.is(tok::eod)) {
- Diag(MacroNameTok, diag::err_pp_missing_macro_name);
+
+ if (!CheckMacroName(MacroNameTok, isDefineUndef))
return;
+
+ // Invalid macro name, read and discard the rest of the line and set the
+ // token kind to tok::eod if necessary.
+ if (MacroNameTok.isNot(tok::eod)) {
+ MacroNameTok.setKind(tok::eod);
+ DiscardUntilEndOfDirective();
}
-
- IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
- if (II == 0) {
- bool Invalid = false;
- std::string Spelling = getSpelling(MacroNameTok, &Invalid);
- if (Invalid)
- return;
-
- const IdentifierInfo &Info = Identifiers.get(Spelling);
-
- // Allow #defining |and| and friends in microsoft mode.
- if (Info.isCPlusPlusOperatorKeyword() && getLangOpts().MSVCCompat) {
- MacroNameTok.setIdentifierInfo(getIdentifierInfo(Spelling));
- return;
- }
-
- if (Info.isCPlusPlusOperatorKeyword())
- // C++ 2.5p2: Alternative tokens behave the same as its primary token
- // except for their spellings.
- Diag(MacroNameTok, diag::err_pp_operator_used_as_macro_name) << Spelling;
- else
- Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
- // Fall through on error.
- } else if (isDefineUndef && II->getPPKeywordID() == tok::pp_defined) {
- // Error if defining "defined": C99 6.10.8/4, C++ [cpp.predefined]p4.
- Diag(MacroNameTok, diag::err_defined_macro_name);
- } else if (isDefineUndef == 2 && II->hasMacroDefinition() &&
- getMacroInfo(II)->isBuiltinMacro()) {
- // Warn if undefining "__LINE__" and other builtins, per C99 6.10.8/4
- // and C++ [cpp.predefined]p4], but allow it as an extension.
- Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
- return;
- } else {
- // Okay, we got a good identifier node. Return it.
- return;
- }
-
- // Invalid macro name, read and discard the rest of the line. Then set the
- // token kind to tok::eod.
- MacroNameTok.setKind(tok::eod);
- return DiscardUntilEndOfDirective();
}
/// \brief Ensure that the next token is a tok::eod token.
@@ -310,9 +318,9 @@
// to spell an i/e in a strange way that is another letter. Skipping this
// allows us to avoid looking up the identifier info for #define/#undef and
// other common directives.
- const char *RawCharData = Tok.getRawIdentifierData();
+ StringRef RI = Tok.getRawIdentifier();
- char FirstChar = RawCharData[0];
+ char FirstChar = RI[0];
if (FirstChar >= 'a' && FirstChar <= 'z' &&
FirstChar != 'i' && FirstChar != 'e') {
CurPPLexer->ParsingPreprocessorDirective = false;
@@ -326,8 +334,8 @@
// when skipping.
char DirectiveBuf[20];
StringRef Directive;
- if (!Tok.needsCleaning() && Tok.getLength() < 20) {
- Directive = StringRef(RawCharData, Tok.getLength());
+ if (!Tok.needsCleaning() && RI.size() < 20) {
+ Directive = RI;
} else {
std::string DirectiveStr = getSpelling(Tok);
unsigned IdLen = DirectiveStr.size();
@@ -418,7 +426,7 @@
// looked up, etc, inside the #elif expression.
assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
CurPPLexer->LexingRawMode = false;
- IdentifierInfo *IfNDefMacro = 0;
+ IdentifierInfo *IfNDefMacro = nullptr;
const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro);
CurPPLexer->LexingRawMode = true;
if (Callbacks) {
@@ -515,7 +523,7 @@
continue;
// Evaluate the condition of the #elif.
- IdentifierInfo *IfNDefMacro = 0;
+ IdentifierInfo *IfNDefMacro = nullptr;
CurPTHLexer->ParsingPreprocessorDirective = true;
bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro);
CurPTHLexer->ParsingPreprocessorDirective = false;
@@ -611,27 +619,37 @@
// to one of the headers on the #include stack. Walk the list of the current
// headers on the #include stack and pass them to HeaderInfo.
if (IsFileLexer()) {
- if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID())))
+ if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt,
SearchPath, RelativePath,
- SuggestedModule)))
+ SuggestedModule))) {
+ if (SuggestedModule && !LangOpts.AsmPreprocessor)
+ HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
+ getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
return FE;
+ }
+ }
}
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1];
if (IsFileLexer(ISEntry)) {
if ((CurFileEnt =
- SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID())))
+ SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(
Filename, CurFileEnt, SearchPath, RelativePath,
- SuggestedModule)))
+ SuggestedModule))) {
+ if (SuggestedModule && !LangOpts.AsmPreprocessor)
+ HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
+ getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
return FE;
+ }
+ }
}
}
// Otherwise, we really couldn't find the file.
- return 0;
+ return nullptr;
}
@@ -729,7 +747,7 @@
return HandleDigitDirective(Result);
default:
IdentifierInfo *II = Result.getIdentifierInfo();
- if (II == 0) break; // Not an identifier.
+ if (!II) break; // Not an identifier.
// Ask what the preprocessor keyword ID is.
switch (II->getPPKeywordID()) {
@@ -1194,7 +1212,7 @@
MacroDirective *MD = getMacroDirective(II);
// If the macro is not defined, this is an error.
- if (MD == 0) {
+ if (!MD) {
Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
return;
}
@@ -1221,7 +1239,7 @@
MacroDirective *MD = getMacroDirective(II);
// If the macro is not defined, this is an error.
- if (MD == 0) {
+ if (!MD) {
Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
return;
}
@@ -1457,9 +1475,9 @@
}
const FileEntry *File = LookupFile(
FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
- isAngled, LookupFrom, CurDir, Callbacks ? &SearchPath : NULL,
- Callbacks ? &RelativePath : NULL,
- HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : 0);
+ isAngled, LookupFrom, CurDir, Callbacks ? &SearchPath : nullptr,
+ Callbacks ? &RelativePath : nullptr,
+ HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : nullptr);
if (Callbacks) {
if (!File) {
@@ -1475,10 +1493,10 @@
File = LookupFile(FilenameLoc,
LangOpts.MSVCCompat ? NormalizedPath.c_str()
: Filename,
- isAngled, LookupFrom, CurDir, 0, 0,
+ isAngled, LookupFrom, CurDir, nullptr, nullptr,
HeaderInfo.getHeaderSearchOpts().ModuleMaps
? &SuggestedModule
- : 0,
+ : nullptr,
/*SkipCache*/ true);
}
}
@@ -1490,11 +1508,11 @@
LangOpts.MSVCCompat ? NormalizedPath.c_str()
: Filename,
isAngled, FilenameRange, File, SearchPath,
- RelativePath, /*ImportedModule=*/0);
+ RelativePath, /*ImportedModule=*/nullptr);
}
}
-
- if (File == 0) {
+
+ if (!File) {
if (!SuppressIncludeNotFoundError) {
// If the file could not be located and it was included via angle
// brackets, we can attempt a lookup as though it were a quoted path to
@@ -1502,9 +1520,10 @@
if (isAngled) {
File = LookupFile(
FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
- false, LookupFrom, CurDir, Callbacks ? &SearchPath : 0,
- Callbacks ? &RelativePath : 0,
- HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : 0);
+ false, LookupFrom, CurDir, Callbacks ? &SearchPath : nullptr,
+ Callbacks ? &RelativePath : nullptr,
+ HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule
+ : nullptr);
if (File) {
SourceRange Range(FilenameTok.getLocation(), CharEnd);
Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) <<
@@ -1585,7 +1604,7 @@
ModuleLoadResult Imported
= TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
/*IsIncludeDirective=*/true);
- assert((Imported == 0 || Imported == SuggestedModule.getModule()) &&
+ assert((Imported == nullptr || Imported == SuggestedModule.getModule()) &&
"the imported module is different than the suggested one");
if (!Imported && hadModuleLoaderFatalFailure()) {
@@ -1636,7 +1655,7 @@
Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled,
FilenameRange, File,
SearchPath, RelativePath,
- /*ImportedModule=*/0);
+ /*ImportedModule=*/nullptr);
}
// The #included file will be considered to be a system header if either it is
@@ -1697,9 +1716,9 @@
// diagnostic.
const DirectoryLookup *Lookup = CurDirLookup;
if (isInPrimaryFile()) {
- Lookup = 0;
+ Lookup = nullptr;
Diag(IncludeNextTok, diag::pp_include_next_in_primary);
- } else if (Lookup == 0) {
+ } else if (!Lookup) {
Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
} else {
// Start looking up in the next directory.
@@ -1732,7 +1751,7 @@
return HandleMicrosoftImportDirective(ImportTok);
Diag(ImportTok, diag::ext_pp_import_directive);
}
- return HandleIncludeDirective(HashLoc, ImportTok, 0, true);
+ return HandleIncludeDirective(HashLoc, ImportTok, nullptr, true);
}
/// HandleIncludeMacrosDirective - The -imacros command line option turns into a
@@ -1753,7 +1772,7 @@
// Treat this as a normal #include for checking purposes. If this is
// successful, it will push a new lexer onto the include stack.
- HandleIncludeDirective(HashLoc, IncludeMacrosTok, 0, false);
+ HandleIncludeDirective(HashLoc, IncludeMacrosTok, nullptr, false);
Token TmpTok;
do {
@@ -1813,7 +1832,7 @@
// Handle keywords and identifiers here to accept things like
// #define Foo(for) for.
IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II == 0) {
+ if (!II) {
// #define X(1
Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
return true;
@@ -2017,7 +2036,7 @@
LexUnexpandedToken(Tok);
// Check for a valid macro arg identifier.
- if (Tok.getIdentifierInfo() == 0 ||
+ if (Tok.getIdentifierInfo() == nullptr ||
MI->getArgumentNum(Tok.getIdentifierInfo()) == -1) {
// If this is assembler-with-cpp mode, we accept random gibberish after
@@ -2133,7 +2152,7 @@
// Okay, we finally have a valid identifier to undef.
MacroDirective *MD = getMacroDirective(MacroNameTok.getIdentifierInfo());
- const MacroInfo *MI = MD ? MD->getMacroInfo() : 0;
+ const MacroInfo *MI = MD ? MD->getMacroInfo() : nullptr;
// If the callbacks want to know, tell them about the macro #undef.
// Note: no matter if the macro was defined or not.
@@ -2141,7 +2160,8 @@
Callbacks->MacroUndefined(MacroNameTok, MD);
// If the macro is not defined, this is a noop undef, just return.
- if (MI == 0) return;
+ if (!MI)
+ return;
if (!MI->isUsed() && MI->isWarnIfUnused())
Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used);
@@ -2185,14 +2205,14 @@
IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
MacroDirective *MD = getMacroDirective(MII);
- MacroInfo *MI = MD ? MD->getMacroInfo() : 0;
+ MacroInfo *MI = MD ? MD->getMacroInfo() : nullptr;
if (CurPPLexer->getConditionalStackDepth() == 0) {
// If the start of a top-level #ifdef and if the macro is not defined,
// inform MIOpt that this might be the start of a proper include guard.
// Otherwise it is some other form of unknown conditional which we can't
// handle.
- if (!ReadAnyTokensBeforeDirective && MI == 0) {
+ if (!ReadAnyTokensBeforeDirective && !MI) {
assert(isIfndef && "#ifdef shouldn't reach here");
CurPPLexer->MIOpt.EnterTopLevelIfndef(MII, MacroNameTok.getLocation());
} else
@@ -2231,7 +2251,7 @@
++NumIf;
// Parse and evaluate the conditional expression.
- IdentifierInfo *IfNDefMacro = 0;
+ IdentifierInfo *IfNDefMacro = nullptr;
const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
const bool ConditionalTrue = EvaluateDirectiveExpression(IfNDefMacro);
const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index 6975d31..2260bf9 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -81,7 +81,6 @@
/// EvaluateDefined - Process a 'defined(sym)' expression.
static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
bool ValueLive, Preprocessor &PP) {
- IdentifierInfo *II;
SourceLocation beginLoc(PeekTok.getLocation());
Result.setBegin(beginLoc);
@@ -102,18 +101,17 @@
PP.setCodeCompletionReached();
PP.LexUnexpandedNonComment(PeekTok);
}
-
+
// If we don't have a pp-identifier now, this is an error.
- if ((II = PeekTok.getIdentifierInfo()) == 0) {
- PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
+ if (PP.CheckMacroName(PeekTok, 0))
return true;
- }
// Otherwise, we got an identifier, is it defined to something?
+ IdentifierInfo *II = PeekTok.getIdentifierInfo();
Result.Val = II->hasMacroDefinition();
Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
- MacroDirective *Macro = 0;
+ MacroDirective *Macro = nullptr;
// If there is a macro, mark it used.
if (Result.Val != 0 && ValueLive) {
Macro = PP.getMacroDirective(II);
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index 949cd63..e79fbe1 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -58,7 +58,7 @@
if (IsFileLexer(ISI))
return ISI.ThePPLexer;
}
- return 0;
+ return nullptr;
}
@@ -117,7 +117,7 @@
CurLexer.reset(TheLexer);
CurPPLexer = TheLexer;
CurDirLookup = CurDir;
- CurSubmodule = 0;
+ CurSubmodule = nullptr;
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_Lexer;
@@ -142,7 +142,7 @@
CurDirLookup = CurDir;
CurPTHLexer.reset(PL);
CurPPLexer = CurPTHLexer.get();
- CurSubmodule = 0;
+ CurSubmodule = nullptr;
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_PTHLexer;
@@ -169,7 +169,7 @@
}
PushIncludeMacroStack();
- CurDirLookup = 0;
+ CurDirLookup = nullptr;
CurTokenLexer.reset(TokLexer);
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_TokenLexer;
@@ -202,7 +202,7 @@
// Save our current state.
PushIncludeMacroStack();
- CurDirLookup = 0;
+ CurDirLookup = nullptr;
CurTokenLexer.reset(TokLexer);
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_TokenLexer;
@@ -284,6 +284,10 @@
if (const FileEntry *FE =
SourceMgr.getFileEntryForID(CurPPLexer->getFileID())) {
HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
+ if (MacroInfo *MI =
+ getMacroInfo(const_cast<IdentifierInfo*>(ControllingMacro))) {
+ MI->UsedForHeaderGuard = true;
+ }
if (const IdentifierInfo *DefinedMacro =
CurPPLexer->MIOpt.GetDefinedMacro()) {
if (!ControllingMacro->hasMacroDefinition() &&
@@ -350,7 +354,7 @@
CurPTHLexer.reset();
}
- CurPPLexer = 0;
+ CurPPLexer = nullptr;
return true;
}
@@ -425,7 +429,7 @@
}
if (!isIncrementalProcessingEnabled())
- CurPPLexer = 0;
+ CurPPLexer = nullptr;
if (TUKind == TU_Complete) {
// This is the end of the top-level file. 'WarnUnusedMacroLocs' has
@@ -557,11 +561,11 @@
// We handle this by scanning for the closest real lexer, switching it to
// raw mode and preprocessor mode. This will cause it to return \n as an
// explicit EOD token.
- PreprocessorLexer *FoundLexer = 0;
+ PreprocessorLexer *FoundLexer = nullptr;
bool LexerWasInPPMode = false;
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
IncludeStackInfo &ISI = *(IncludeMacroStack.end()-i-1);
- if (ISI.ThePPLexer == 0) continue; // Scan for a real lexer.
+ if (ISI.ThePPLexer == nullptr) continue; // Scan for a real lexer.
// Once we find a real lexer, mark it as raw mode (disabling macro
// expansions) and preprocessor mode (return EOD). We know that the lexer
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 35f9192..57bc946 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -103,8 +103,8 @@
Ident__identifier = RegisterBuiltinMacro(*this, "__identifier");
Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
} else {
- Ident__identifier = 0;
- Ident__pragma = 0;
+ Ident__identifier = nullptr;
+ Ident__pragma = nullptr;
}
// Clang Extensions.
@@ -115,6 +115,7 @@
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning");
+ Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier");
// Modules.
if (LangOpts.Modules) {
@@ -124,10 +125,10 @@
if (!LangOpts.CurrentModule.empty())
Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__");
else
- Ident__MODULE__ = 0;
+ Ident__MODULE__ = nullptr;
} else {
- Ident__building_module = 0;
- Ident__MODULE__ = 0;
+ Ident__building_module = nullptr;
+ Ident__MODULE__ = nullptr;
}
}
@@ -139,7 +140,7 @@
IdentifierInfo *II = MI->getReplacementToken(0).getIdentifierInfo();
// If the token isn't an identifier, it's always literally expanded.
- if (II == 0) return true;
+ if (!II) return true;
// If the information about this identifier is out of date, update it from
// the external source.
@@ -227,7 +228,8 @@
// If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
if (MI->isBuiltinMacro()) {
if (Callbacks) Callbacks->MacroExpands(Identifier, MD,
- Identifier.getLocation(),/*Args=*/0);
+ Identifier.getLocation(),
+ /*Args=*/nullptr);
ExpandBuiltinMacro(Identifier);
return true;
}
@@ -235,7 +237,7 @@
/// Args - If this is a function-like macro expansion, this contains,
/// for each macro argument, the list of tokens that were provided to the
/// invocation.
- MacroArgs *Args = 0;
+ MacroArgs *Args = nullptr;
// Remember where the end of the expansion occurred. For an object-like
// macro, this is the identifier. For a function-like macro, this is the ')'.
@@ -253,7 +255,7 @@
InMacroArgs = false;
// If there was an error parsing the arguments, bail out.
- if (Args == 0) return true;
+ if (!Args) return true;
++NumFnMacroExpanded;
} else {
@@ -281,7 +283,8 @@
for (unsigned i=0, e = DelayedMacroExpandsCallbacks.size(); i!=e; ++i) {
MacroExpandsInfo &Info = DelayedMacroExpandsCallbacks[i];
// FIXME: We lose macro args info with delayed callback.
- Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range, /*Args=*/0);
+ Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range,
+ /*Args=*/nullptr);
}
DelayedMacroExpandsCallbacks.clear();
}
@@ -556,7 +559,7 @@
<< MacroName.getIdentifierInfo();
// Do not lose the EOF/EOD. Return it to the client.
MacroName = Tok;
- return 0;
+ return nullptr;
} else {
// Do not lose the EOF/EOD.
Token *Toks = new Token[1];
@@ -588,7 +591,7 @@
// If this is a comment token in the argument list and we're just in
// -C mode (not -CC mode), discard the comment.
continue;
- } else if (Tok.getIdentifierInfo() != 0) {
+ } else if (Tok.getIdentifierInfo() != nullptr) {
// Reading macro arguments can cause macros that we are currently
// expanding from to be popped off the expansion stack. Doing so causes
// them to be reenabled for expansion. Here we record whether any
@@ -672,29 +675,18 @@
DiagnosticBuilder DB =
Diag(MacroName,
diag::note_init_list_at_beginning_of_macro_argument);
- for (SmallVector<SourceRange, 4>::iterator
- Range = InitLists.begin(), RangeEnd = InitLists.end();
- Range != RangeEnd; ++Range) {
- if (DB.hasMaxRanges())
- break;
- DB << *Range;
- }
+ for (const SourceRange &Range : InitLists)
+ DB << Range;
}
- return 0;
+ return nullptr;
}
if (FixedNumArgs != MinArgsExpected)
- return 0;
+ return nullptr;
DiagnosticBuilder DB = Diag(MacroName, diag::note_suggest_parens_for_macro);
- for (SmallVector<SourceRange, 4>::iterator
- ParenLocation = ParenHints.begin(), ParenEnd = ParenHints.end();
- ParenLocation != ParenEnd; ++ParenLocation) {
- if (DB.hasMaxFixItHints())
- break;
- DB << FixItHint::CreateInsertion(ParenLocation->getBegin(), "(");
- if (DB.hasMaxFixItHints())
- break;
- DB << FixItHint::CreateInsertion(ParenLocation->getEnd(), ")");
+ for (const SourceRange &ParenLocation : ParenHints) {
+ DB << FixItHint::CreateInsertion(ParenLocation.getBegin(), "(");
+ DB << FixItHint::CreateInsertion(ParenLocation.getEnd(), ")");
}
ArgTokens.swap(FixedArgTokens);
NumActuals = FixedNumArgs;
@@ -750,7 +742,7 @@
Diag(Tok, diag::err_too_few_args_in_macro_invoc);
Diag(MI->getDefinitionLoc(), diag::note_macro_here)
<< MacroName.getIdentifierInfo();
- return 0;
+ return nullptr;
}
// Add a marker EOF token to the end of the token list for this argument.
@@ -772,7 +764,7 @@
Diag(MacroName, diag::err_too_many_args_in_macro_invoc);
Diag(MI->getDefinitionLoc(), diag::note_macro_here)
<< MacroName.getIdentifierInfo();
- return 0;
+ return nullptr;
}
return MacroArgs::create(MI, ArgTokens, isVarargsElided, *this);
@@ -787,7 +779,7 @@
ArrayRef<Token> tokens) {
assert(tokLexer);
if (tokens.empty())
- return 0;
+ return nullptr;
size_t newIndex = MacroExpandedTokens.size();
bool cacheNeedsToGrow = tokens.size() >
@@ -823,7 +815,7 @@
/// the identifier tokens inserted.
static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
Preprocessor &PP) {
- time_t TT = time(0);
+ time_t TT = time(nullptr);
struct tm *TM = localtime(&TT);
static const char * const Months[] = {
@@ -885,7 +877,7 @@
.Case("attribute_unused_on_fields", true)
.Case("blocks", LangOpts.Blocks)
.Case("c_thread_safety_attributes", true)
- .Case("cxx_exceptions", LangOpts.Exceptions)
+ .Case("cxx_exceptions", LangOpts.CXXExceptions)
.Case("cxx_rtti", LangOpts.RTTI)
.Case("enumerator_attributes", true)
.Case("memory_sanitizer", LangOpts.Sanitize.Memory)
@@ -917,7 +909,7 @@
.Case("c_atomic", LangOpts.C11)
.Case("c_generic_selections", LangOpts.C11)
.Case("c_static_assert", LangOpts.C11)
- .Case("c_thread_local",
+ .Case("c_thread_local",
LangOpts.C11 && PP.getTargetInfo().isTLSSupported())
// C++11 features
.Case("cxx_access_control_sfinae", LangOpts.CPlusPlus11)
@@ -961,12 +953,17 @@
.Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus1y)
.Case("cxx_binary_literals", LangOpts.CPlusPlus1y)
.Case("cxx_contextual_conversions", LangOpts.CPlusPlus1y)
- //.Case("cxx_generic_lambdas", LangOpts.CPlusPlus1y)
+ .Case("cxx_decltype_auto", LangOpts.CPlusPlus1y)
+ .Case("cxx_generic_lambdas", LangOpts.CPlusPlus1y)
.Case("cxx_init_captures", LangOpts.CPlusPlus1y)
.Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus1y)
.Case("cxx_return_type_deduction", LangOpts.CPlusPlus1y)
- //.Case("cxx_runtime_arrays", LangOpts.CPlusPlus1y)
.Case("cxx_variable_templates", LangOpts.CPlusPlus1y)
+ // C++ TSes
+ //.Case("cxx_runtime_arrays", LangOpts.CPlusPlusTSArrays)
+ //.Case("cxx_concepts", LangOpts.CPlusPlusTSConcepts)
+ // FIXME: Should this be __has_feature or __has_extension?
+ //.Case("raw_invocation_type", LangOpts.CPlusPlus)
// Type traits
.Case("has_nothrow_assign", LangOpts.CPlusPlus)
.Case("has_nothrow_copy", LangOpts.CPlusPlus)
@@ -1148,18 +1145,18 @@
// Search include directories.
const DirectoryLookup *CurDir;
const FileEntry *File =
- PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir, NULL,
- NULL, NULL);
+ PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
+ nullptr, nullptr, nullptr);
// Get the result value. A result of true means the file exists.
- return File != 0;
+ return File != nullptr;
}
/// EvaluateHasInclude - Process a '__has_include("path")' expression.
/// Returns true if successful.
static bool EvaluateHasInclude(Token &Tok, IdentifierInfo *II,
Preprocessor &PP) {
- return EvaluateHasIncludeCommon(Tok, II, PP, NULL);
+ return EvaluateHasIncludeCommon(Tok, II, PP, nullptr);
}
/// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression.
@@ -1171,9 +1168,9 @@
// issue a diagnostic.
const DirectoryLookup *Lookup = PP.GetCurDirLookup();
if (PP.isInPrimaryFile()) {
- Lookup = 0;
+ Lookup = nullptr;
PP.Diag(Tok, diag::pp_include_next_in_primary);
- } else if (Lookup == 0) {
+ } else if (!Lookup) {
PP.Diag(Tok, diag::pp_include_next_absolute_path);
} else {
// Start looking up in the next directory.
@@ -1246,7 +1243,7 @@
llvm::raw_svector_ostream OS(TmpBuffer);
// Set up the return result.
- Tok.setIdentifierInfo(0);
+ Tok.setIdentifierInfo(nullptr);
Tok.clearFlag(Token::NeedsCleaning);
if (II == Ident__LINE__) {
@@ -1335,7 +1332,7 @@
// Get the file that we are lexing out of. If we're currently lexing from
// a macro, dig into the include stack.
- const FileEntry *CurFile = 0;
+ const FileEntry *CurFile = nullptr;
PreprocessorLexer *TheLexer = getCurrentFileLexer();
if (TheLexer)
@@ -1359,12 +1356,13 @@
} else if (II == Ident__has_feature ||
II == Ident__has_extension ||
II == Ident__has_builtin ||
+ II == Ident__is_identifier ||
II == Ident__has_attribute) {
// The argument to these builtins should be a parenthesized identifier.
SourceLocation StartLoc = Tok.getLocation();
bool IsValid = false;
- IdentifierInfo *FeatureII = 0;
+ IdentifierInfo *FeatureII = nullptr;
// Read the '('.
LexUnexpandedToken(Tok);
@@ -1382,6 +1380,8 @@
bool Value = false;
if (!IsValid)
Diag(StartLoc, diag::err_feature_check_malformed);
+ else if (II == Ident__is_identifier)
+ Value = FeatureII->getTokenID() == tok::identifier;
else if (II == Ident__has_builtin) {
// Check for a builtin is trivial.
Value = FeatureII->getBuiltinID() != 0;
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index 1ca16d3..42629d4 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/lib/Lex/PTHLexer.cpp
@@ -15,7 +15,6 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/PTHManager.h"
@@ -25,10 +24,10 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/system_error.h"
#include <memory>
using namespace clang;
-using namespace clang::io;
#define DISK_TOKEN_SIZE (1+1+2+4+4)
@@ -38,7 +37,7 @@
PTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const unsigned char *D,
const unsigned char *ppcond, PTHManager &PM)
- : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
+ : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(nullptr),
PPCond(ppcond), CurPPCondPtr(ppcond), PTHMgr(PM) {
FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID);
@@ -192,7 +191,7 @@
assert(CurPPCondPtr && "No cached PP conditional information.");
assert(LastHashTokPtr && "No known '#' token.");
- const unsigned char* HashEntryI = 0;
+ const unsigned char *HashEntryI = nullptr;
uint32_t TableIdx;
do {
@@ -319,8 +318,10 @@
class PTHFileLookupCommonTrait {
public:
typedef std::pair<unsigned char, const char*> internal_key_type;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
- static unsigned ComputeHash(internal_key_type x) {
+ static hash_value_type ComputeHash(internal_key_type x) {
return llvm::HashString(x.second);
}
@@ -364,13 +365,11 @@
class PTHStringLookupTrait {
public:
- typedef uint32_t
- data_type;
-
- typedef const std::pair<const char*, unsigned>
- external_key_type;
-
+ typedef uint32_t data_type;
+ typedef const std::pair<const char*, unsigned> external_key_type;
typedef external_key_type internal_key_type;
+ typedef uint32_t hash_value_type;
+ typedef unsigned offset_type;
static bool EqualKey(const internal_key_type& a,
const internal_key_type& b) {
@@ -378,7 +377,7 @@
: false;
}
- static unsigned ComputeHash(const internal_key_type& a) {
+ static hash_value_type ComputeHash(const internal_key_type& a) {
return llvm::HashString(StringRef(a.first, a.second));
}
@@ -409,8 +408,8 @@
} // end anonymous namespace
-typedef OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup;
-typedef OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup;
+typedef llvm::OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup;
+typedef llvm::OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup;
//===----------------------------------------------------------------------===//
// PTHManager methods.
@@ -424,7 +423,7 @@
const char* originalSourceFile)
: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup),
IdDataTable(idDataTable), StringIdLookup(stringIdLookup),
- NumIds(numIds), PP(0), SpellingBase(spellingBase),
+ NumIds(numIds), PP(nullptr), SpellingBase(spellingBase),
OriginalSourceFile(originalSourceFile) {}
PTHManager::~PTHManager() {
@@ -446,7 +445,7 @@
if (llvm::MemoryBuffer::getFile(file, File)) {
// FIXME: Add ec.message() to this diag.
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
using namespace llvm::support;
@@ -460,7 +459,7 @@
if ((BufEnd - BufBeg) < (signed)(sizeof("cfe-pth") + 4 + 4) ||
memcmp(BufBeg, "cfe-pth", sizeof("cfe-pth")) != 0) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
// Read the PTH version.
@@ -472,7 +471,7 @@
Version < PTHManager::Version
? "PTH file uses an older PTH format that is no longer supported"
: "PTH file uses a newer PTH format that cannot be read");
- return 0;
+ return nullptr;
}
// Compute the address of the index table at the end of the PTH file.
@@ -480,7 +479,7 @@
if (PrologueOffset >= BufEnd) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
// Construct the file lookup table. This will be used for mapping from
@@ -491,7 +490,7 @@
if (!(FileTable > BufBeg && FileTable < BufEnd)) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0; // FIXME: Proper error diagnostic?
+ return nullptr; // FIXME: Proper error diagnostic?
}
std::unique_ptr<PTHFileLookup> FL(PTHFileLookup::Create(FileTable, BufBeg));
@@ -509,7 +508,7 @@
if (!(IData >= BufBeg && IData < BufEnd)) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
// Get the location of the hashtable mapping between strings and
@@ -519,7 +518,7 @@
BufBeg + endian::readNext<uint32_t, little, aligned>(StringIdTableOffset);
if (!(StringIdTable >= BufBeg && StringIdTable < BufEnd)) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
std::unique_ptr<PTHStringIdLookup> SL(
@@ -531,7 +530,7 @@
BufBeg + endian::readNext<uint32_t, little, aligned>(spellingBaseOffset);
if (!(spellingBase >= BufBeg && spellingBase < BufEnd)) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
// Get the number of IdentifierInfos and pre-allocate the identifier cache.
@@ -540,13 +539,13 @@
// Pre-allocate the persistent ID -> IdentifierInfo* cache. We use calloc()
// so that we in the best case only zero out memory once when the OS returns
// us new pages.
- IdentifierInfo** PerIDCache = 0;
+ IdentifierInfo **PerIDCache = nullptr;
if (NumIds) {
PerIDCache = (IdentifierInfo**)calloc(NumIds, sizeof(*PerIDCache));
if (!PerIDCache) {
InvalidPTH(Diags, "Could not allocate memory for processing PTH file");
- return 0;
+ return nullptr;
}
}
@@ -554,7 +553,7 @@
const unsigned char* originalSourceBase = PrologueOffset + sizeof(uint32_t)*4;
unsigned len =
endian::readNext<uint16_t, little, unaligned>(originalSourceBase);
- if (!len) originalSourceBase = 0;
+ if (!len) originalSourceBase = nullptr;
// Create the new PTHManager.
return new PTHManager(File.release(), FL.release(), IData, PerIDCache,
@@ -592,7 +591,7 @@
PTHStringIdLookup::iterator I = SL.find(std::make_pair(Name.data(),
Name.size()));
if (I == SL.end()) // No identifier found?
- return 0;
+ return nullptr;
// Match found. Return the identifier!
assert(*I > 0);
@@ -602,7 +601,7 @@
PTHLexer *PTHManager::CreateLexer(FileID FID) {
const FileEntry *FE = PP->getSourceManager().getFileEntryForID(FID);
if (!FE)
- return 0;
+ return nullptr;
using namespace llvm::support;
@@ -613,7 +612,7 @@
PTHFileLookup::iterator I = PFL.find(FE);
if (I == PFL.end()) // No tokens available?
- return 0;
+ return nullptr;
const PTHFileData& FileData = *I;
@@ -624,7 +623,7 @@
// Get the location of pp-conditional table.
const unsigned char* ppcond = BufStart + FileData.getPPCondOffset();
uint32_t Len = endian::readNext<uint32_t, little, aligned>(ppcond);
- if (Len == 0) ppcond = 0;
+ if (Len == 0) ppcond = nullptr;
assert(PP && "No preprocessor set yet!");
return new PTHLexer(*PP, FID, data, ppcond, *this);
@@ -693,7 +692,7 @@
};
class PTHStatCache : public FileSystemStatCache {
- typedef OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy;
+ typedef llvm::OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy;
CacheTy Cache;
public:
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 99ba8de..b837fc5 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -59,7 +59,7 @@
bool IgnoreNull) const {
if (PragmaHandler *Handler = Handlers.lookup(Name))
return Handler;
- return IgnoreNull ? 0 : Handlers.lookup(StringRef());
+ return IgnoreNull ? nullptr : Handlers.lookup(StringRef());
}
void PragmaNamespace::AddPragma(PragmaHandler *Handler) {
@@ -88,7 +88,7 @@
= FindHandler(Tok.getIdentifierInfo() ? Tok.getIdentifierInfo()->getName()
: StringRef(),
/*IgnoreNull=*/false);
- if (Handler == 0) {
+ if (!Handler) {
PP.Diag(Tok, diag::warn_pragma_ignored);
return;
}
@@ -290,7 +290,7 @@
Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
StrVal.size(), *this);
- EnterSourceFileWithLexer(TL, 0);
+ EnterSourceFileWithLexer(TL, nullptr);
// With everything set up, lex this as a #pragma directive.
HandlePragmaDirective(PragmaLoc, PIK__Pragma);
@@ -473,8 +473,9 @@
// Search include directories for this file.
const DirectoryLookup *CurDir;
const FileEntry *File = LookupFile(FilenameTok.getLocation(), Filename,
- isAngled, 0, CurDir, NULL, NULL, NULL);
- if (File == 0) {
+ isAngled, nullptr, CurDir, nullptr,
+ nullptr, nullptr);
+ if (!File) {
if (!SuppressIncludeNotFoundError)
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return;
@@ -510,7 +511,7 @@
if (Tok.isNot(tok::l_paren)) {
Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
<< getSpelling(PragmaTok);
- return 0;
+ return nullptr;
}
// Read the macro name string.
@@ -518,12 +519,12 @@
if (Tok.isNot(tok::string_literal)) {
Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
<< getSpelling(PragmaTok);
- return 0;
+ return nullptr;
}
if (Tok.hasUDSuffix()) {
Diag(Tok, diag::err_invalid_string_udl);
- return 0;
+ return nullptr;
}
// Remember the macro string.
@@ -534,7 +535,7 @@
if (Tok.isNot(tok::r_paren)) {
Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
<< getSpelling(PragmaTok);
- return 0;
+ return nullptr;
}
assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
@@ -736,7 +737,7 @@
// we already have the namespace to insert into.
if (PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace)) {
InsertNS = Existing->getIfNamespace();
- assert(InsertNS != 0 && "Cannot have a pragma namespace and pragma"
+ assert(InsertNS != nullptr && "Cannot have a pragma namespace and pragma"
" handler with the same name!");
} else {
// Otherwise, this namespace doesn't exist yet, create and insert the
@@ -1385,3 +1386,26 @@
AddPragmaHandler(new PragmaRegionHandler("endregion"));
}
}
+
+/// Ignore all pragmas, useful for modes such as -Eonly which would otherwise
+/// warn about those pragmas being unknown.
+void Preprocessor::IgnorePragmas() {
+ AddPragmaHandler(new EmptyPragmaHandler());
+ // Also ignore all pragmas in all namespaces created
+ // in Preprocessor::RegisterBuiltinPragmas().
+ AddPragmaHandler("GCC", new EmptyPragmaHandler());
+ AddPragmaHandler("clang", new EmptyPragmaHandler());
+ if (PragmaHandler *NS = PragmaHandlers->FindHandler("STDC")) {
+ // Preprocessor::RegisterBuiltinPragmas() already registers
+ // PragmaSTDC_UnknownHandler as the empty handler, so remove it first,
+ // otherwise there will be an assert about a duplicate handler.
+ PragmaNamespace *STDCNamespace = NS->getIfNamespace();
+ assert(STDCNamespace &&
+ "Invalid namespace, registered as a regular pragma handler!");
+ if (PragmaHandler *Existing = STDCNamespace->FindHandler("", false)) {
+ RemovePragmaHandler("STDC", Existing);
+ delete Existing;
+ }
+ }
+ AddPragmaHandler("STDC", new EmptyPragmaHandler());
+}
diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp
index db5a9f9..41bb581 100644
--- a/lib/Lex/PreprocessingRecord.cpp
+++ b/lib/Lex/PreprocessingRecord.cpp
@@ -40,7 +40,7 @@
PreprocessingRecord::PreprocessingRecord(SourceManager &SM)
: SourceMgr(SM),
- ExternalSource(0) {
+ ExternalSource(nullptr) {
}
/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
@@ -334,7 +334,7 @@
}
if (PPID.ID == 0)
- return 0;
+ return nullptr;
unsigned Index = PPID.ID - 1;
assert(Index < PreprocessedEntities.size() &&
"Out-of bounds local preprocessed entity");
@@ -361,7 +361,7 @@
llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
= MacroDefinitions.find(MI);
if (Pos == MacroDefinitions.end())
- return 0;
+ return nullptr;
return Pos->second;
}
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index d85df38..b561636 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -56,22 +56,21 @@
Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
DiagnosticsEngine &diags, LangOptions &opts,
- const TargetInfo *target, SourceManager &SM,
- HeaderSearch &Headers, ModuleLoader &TheModuleLoader,
+ SourceManager &SM, HeaderSearch &Headers,
+ ModuleLoader &TheModuleLoader,
IdentifierInfoLookup *IILookup, bool OwnsHeaders,
- bool DelayInitialization, bool IncrProcessing,
TranslationUnitKind TUKind)
- : PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(target),
+ : PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(0),
FileMgr(Headers.getFileMgr()), SourceMgr(SM), HeaderInfo(Headers),
- TheModuleLoader(TheModuleLoader), ExternalSource(0),
- Identifiers(opts, IILookup), IncrementalProcessing(IncrProcessing),
- TUKind(TUKind),
- CodeComplete(0), CodeCompletionFile(0), CodeCompletionOffset(0),
- LastTokenWasAt(false), ModuleImportExpectsIdentifier(false),
- CodeCompletionReached(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
- CurDirLookup(0), CurLexerKind(CLK_Lexer), CurSubmodule(0),
- Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0), MICache(0),
- DeserialMIChainHead(0) {
+ TheModuleLoader(TheModuleLoader), ExternalSource(nullptr),
+ Identifiers(opts, IILookup), IncrementalProcessing(false), TUKind(TUKind),
+ CodeComplete(nullptr), CodeCompletionFile(nullptr),
+ CodeCompletionOffset(0), LastTokenWasAt(false),
+ ModuleImportExpectsIdentifier(false), CodeCompletionReached(0),
+ SkipMainFilePreamble(0, true), CurPPLexer(nullptr),
+ CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr),
+ Callbacks(nullptr), MacroArgCache(nullptr), Record(nullptr),
+ MIChainHead(nullptr), MICache(nullptr), DeserialMIChainHead(0) {
OwnsHeaderSearch = OwnsHeaders;
ScratchBuf = new ScratchBuffer(SourceMgr);
@@ -129,14 +128,11 @@
Ident___abnormal_termination = getIdentifierInfo("__abnormal_termination");
Ident_AbnormalTermination = getIdentifierInfo("AbnormalTermination");
} else {
- Ident__exception_info = Ident__exception_code = Ident__abnormal_termination = 0;
- Ident___exception_info = Ident___exception_code = Ident___abnormal_termination = 0;
- Ident_GetExceptionInfo = Ident_GetExceptionCode = Ident_AbnormalTermination = 0;
- }
-
- if (!DelayInitialization) {
- assert(Target && "Must provide target information for PP initialization");
- Initialize(*Target);
+ Ident__exception_info = Ident__exception_code = nullptr;
+ Ident__abnormal_termination = Ident___exception_info = nullptr;
+ Ident___exception_code = Ident___abnormal_termination = nullptr;
+ Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr;
+ Ident_AbnormalTermination = nullptr;
}
}
@@ -150,14 +146,17 @@
I->MI.Destroy();
// Free any cached macro expanders.
+ // This populates MacroArgCache, so all TokenLexers need to be destroyed
+ // before the code below that frees up the MacroArgCache list.
for (unsigned i = 0, e = NumCachedTokenLexers; i != e; ++i)
delete TokenLexerCache[i];
+ CurTokenLexer.reset();
for (DeserializedMacroInfoChain *I = DeserialMIChainHead ; I ; I = I->Next)
I->MI.Destroy();
// Free any cached MacroArgs.
- for (MacroArgs *ArgList = MacroArgCache; ArgList; )
+ for (MacroArgs *ArgList = MacroArgCache; ArgList;)
ArgList = ArgList->deallocate();
// Release pragma information.
@@ -442,8 +441,8 @@
Module *Preprocessor::getCurrentModule() {
if (getLangOpts().CurrentModule.empty())
- return 0;
-
+ return nullptr;
+
return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule);
}
@@ -465,8 +464,8 @@
// a main file.
if (!SourceMgr.isLoadedFileID(MainFileID)) {
// Enter the main file source buffer.
- EnterSourceFile(MainFileID, 0, SourceLocation());
-
+ EnterSourceFile(MainFileID, nullptr, SourceLocation());
+
// If we've been asked to skip bytes in the main file (e.g., as part of a
// precompiled preamble), do so now.
if (SkipMainFilePreamble.first > 0)
@@ -483,12 +482,12 @@
llvm::MemoryBuffer *SB =
llvm::MemoryBuffer::getMemBufferCopy(Predefines, "<built-in>");
assert(SB && "Cannot create predefined source buffer");
- FileID FID = SourceMgr.createFileIDForMemBuffer(SB);
+ FileID FID = SourceMgr.createFileID(SB);
assert(!FID.isInvalid() && "Could not create FileID for predefines?");
setPredefinesFileID(FID);
// Start parsing the predefines.
- EnterSourceFile(FID, 0, SourceLocation());
+ EnterSourceFile(FID, nullptr, SourceLocation());
}
void Preprocessor::EndSourceFile() {
@@ -505,14 +504,13 @@
/// identifier information for the token and install it into the token,
/// updating the token kind accordingly.
IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const {
- assert(Identifier.getRawIdentifierData() != 0 && "No raw identifier data!");
+ assert(!Identifier.getRawIdentifier().empty() && "No raw identifier data!");
// Look up this token, see if it is a macro, or if it is a language keyword.
IdentifierInfo *II;
if (!Identifier.needsCleaning() && !Identifier.hasUCN()) {
// No cleaning needed, just use the characters from the lexed buffer.
- II = getIdentifierInfo(StringRef(Identifier.getRawIdentifierData(),
- Identifier.getLength()));
+ II = getIdentifierInfo(Identifier.getRawIdentifier());
} else {
// Cleaning needed, alloca a buffer, clean into it, then use the buffer.
SmallString<64> IdentifierBuffer;
@@ -635,7 +633,7 @@
// then we act as if it is the actual operator and not the textual
// representation of it.
if (II.isCPlusPlusOperatorKeyword())
- Identifier.setIdentifierInfo(0);
+ Identifier.setIdentifierInfo(nullptr);
// If this is an extension token, diagnose its use.
// We avoid diagnosing tokens that originate from macro definitions.
diff --git a/lib/Lex/ScratchBuffer.cpp b/lib/Lex/ScratchBuffer.cpp
index 3d363fa..d7104b1 100644
--- a/lib/Lex/ScratchBuffer.cpp
+++ b/lib/Lex/ScratchBuffer.cpp
@@ -21,7 +21,8 @@
//than a page, almost certainly enough for anything. :)
static const unsigned ScratchBufSize = 4060;
-ScratchBuffer::ScratchBuffer(SourceManager &SM) : SourceMgr(SM), CurBuffer(0) {
+ScratchBuffer::ScratchBuffer(SourceManager &SM)
+ : SourceMgr(SM), CurBuffer(nullptr) {
// Set BytesUsed so that the first call to getToken will require an alloc.
BytesUsed = ScratchBufSize;
}
@@ -65,7 +66,7 @@
llvm::MemoryBuffer *Buf =
llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
- FileID FID = SourceMgr.createFileIDForMemBuffer(Buf);
+ FileID FID = SourceMgr.createFileID(Buf);
BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
CurBuffer = const_cast<char*>(Buf->getBufferStart());
BytesUsed = 1;
diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp
index 40e9707..9d03e8d 100644
--- a/lib/Lex/TokenLexer.cpp
+++ b/lib/Lex/TokenLexer.cpp
@@ -86,8 +86,8 @@
// associated with it.
destroy();
- Macro = 0;
- ActualArgs = 0;
+ Macro = nullptr;
+ ActualArgs = nullptr;
Tokens = TokArray;
OwnsTokens = ownsTokens;
DisableMacroExpansion = disableMacroExpansion;
@@ -113,7 +113,7 @@
// the expanded tokens.
if (OwnsTokens) {
delete [] Tokens;
- Tokens = 0;
+ Tokens = nullptr;
OwnsTokens = false;
}
@@ -121,10 +121,9 @@
if (ActualArgs) ActualArgs->destroy(PP);
}
-bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(SmallVectorImpl<Token> &ResultToks,
- bool HasPasteOperator,
- MacroInfo *Macro, unsigned MacroArgNo,
- Preprocessor &PP) {
+bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(
+ SmallVectorImpl<Token> &ResultToks, bool HasPasteOperator, MacroInfo *Macro,
+ unsigned MacroArgNo, Preprocessor &PP) {
// Is the macro argument __VA_ARGS__?
if (!Macro->isVariadic() || MacroArgNo != Macro->getNumArgs()-1)
return false;
@@ -481,7 +480,7 @@
HasLeadingSpace = false;
// Handle recursive expansion!
- if (!Tok.isAnnotation() && Tok.getIdentifierInfo() != 0) {
+ if (!Tok.isAnnotation() && Tok.getIdentifierInfo() != nullptr) {
// Change the kind of this identifier to the appropriate token kind, e.g.
// turning "for" into a keyword.
IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -508,7 +507,7 @@
/// If this returns true, the caller should immediately return the token.
bool TokenLexer::PasteTokens(Token &Tok) {
SmallString<128> Buffer;
- const char *ResultTokStrPtr = 0;
+ const char *ResultTokStrPtr = nullptr;
SourceLocation StartLoc = Tok.getLocation();
SourceLocation PasteOpLoc;
do {
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 4cf87e5..19aa664 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -35,8 +35,9 @@
"Current token not a '{', ':', '=', or 'try'!");
MultiTemplateParamsArg TemplateParams(
- TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0,
- TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
+ TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data()
+ : nullptr,
+ TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
NamedDecl *FnD;
D.setFunctionDefinitionKind(DefinitionKind);
@@ -45,7 +46,7 @@
TemplateParams);
else {
FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
- TemplateParams, 0,
+ TemplateParams, nullptr,
VS, ICIS_NoInit);
if (FnD) {
Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs);
@@ -65,7 +66,7 @@
if (TryConsumeToken(tok::equal)) {
if (!FnD) {
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
bool Delete = false;
@@ -262,7 +263,8 @@
/// delayed (such as default arguments) and parse them.
void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
- ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
+ ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
+ HasTemplateScope);
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
if (HasTemplateScope) {
Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
@@ -275,14 +277,16 @@
ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
HasClassScope);
if (HasClassScope)
- Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
+ Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
+ Class.TagOrTemplate);
for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations();
}
if (HasClassScope)
- Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
+ Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
+ Class.TagOrTemplate);
}
void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
@@ -302,7 +306,7 @@
Scope::FunctionDeclarationScope | Scope::DeclScope);
for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
// Introduce the parameter into scope.
- Actions.ActOnDelayedCXXMethodParameter(getCurScope(),
+ Actions.ActOnDelayedCXXMethodParameter(getCurScope(),
LM.DefaultArgs[I].Param);
if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
@@ -357,7 +361,7 @@
ConsumeAnyToken();
delete Toks;
- LM.DefaultArgs[I].Toks = 0;
+ LM.DefaultArgs[I].Toks = nullptr;
}
}
@@ -431,7 +435,7 @@
// Error recovery.
if (!Tok.is(tok::l_brace)) {
FnScope.Exit();
- Actions.ActOnFinishFunctionBody(LM.D, 0);
+ Actions.ActOnFinishFunctionBody(LM.D, nullptr);
while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
ConsumeAnyToken();
return;
@@ -463,6 +467,9 @@
while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
ConsumeAnyToken();
}
+
+ if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(LM.D))
+ Actions.ActOnFinishInlineMethodDef(MD);
}
/// ParseLexedMemberInitializers - We finished parsing the member specification
@@ -830,8 +837,9 @@
ConsumeToken();
while (Tok.isNot(tok::colon)) {
- if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks, /*StopAtSemi*/true,
- /*ConsumeFinalToken*/false))
+ if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks,
+ /*StopAtSemi=*/true,
+ /*ConsumeFinalToken=*/false))
return false;
// If we found a nested conditional, consume it.
@@ -919,15 +927,15 @@
? tok::semi : tok::r_paren);
Sema::TentativeAnalysisScope Scope(Actions);
- TPResult Result = TPResult::Error();
+ TPResult Result = TPResult::Error;
ConsumeToken();
switch (CIK) {
case CIK_DefaultInitializer:
Result = TryParseInitDeclaratorList();
// If we parsed a complete, ambiguous init-declarator-list, this
// is only syntactically-valid if it's followed by a semicolon.
- if (Result == TPResult::Ambiguous() && Tok.isNot(tok::semi))
- Result = TPResult::False();
+ if (Result == TPResult::Ambiguous && Tok.isNot(tok::semi))
+ Result = TPResult::False;
break;
case CIK_DefaultArgument:
@@ -936,13 +944,13 @@
&InvalidAsDeclaration, /*VersusTemplateArgument*/true);
// If this is an expression or a declaration with a missing
// 'typename', assume it's not a declaration.
- if (Result == TPResult::Ambiguous() && InvalidAsDeclaration)
- Result = TPResult::False();
+ if (Result == TPResult::Ambiguous && InvalidAsDeclaration)
+ Result = TPResult::False;
break;
}
// If what follows could be a declaration, it is a declaration.
- if (Result != TPResult::False() && Result != TPResult::Error()) {
+ if (Result != TPResult::False && Result != TPResult::Error) {
PA.Revert();
return true;
}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 331c5e4..7507ddf 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -53,7 +53,7 @@
DS.addAttributes(Attrs->getList());
ParseSpecifierQualifierList(DS, AS, DSC);
if (OwnedType)
- *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0;
+ *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr;
// Parse the abstract-declarator, if present.
Declarator DeclaratorInfo(DS, Context);
@@ -150,14 +150,14 @@
SourceLocation AttrNameLoc = ConsumeToken();
if (Tok.isNot(tok::l_paren)) {
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_GNU);
continue;
}
// Handle "parameterized" attributes
if (!LateAttrs || !isAttributeLateParsed(*AttrName)) {
- ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, 0,
+ ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr,
SourceLocation(), AttributeList::AS_GNU, D);
continue;
}
@@ -254,14 +254,14 @@
if (T.isUsable())
Attrs.addNewTypeAttr(&AttrName,
- SourceRange(AttrNameLoc, Parens.getCloseLocation()), 0,
- AttrNameLoc, T.get(), AttributeList::AS_GNU);
+ SourceRange(AttrNameLoc, Parens.getCloseLocation()),
+ nullptr, AttrNameLoc, T.get(), AttributeList::AS_GNU);
else
Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),
- 0, AttrNameLoc, 0, 0, AttributeList::AS_GNU);
+ nullptr, AttrNameLoc, nullptr, 0, AttributeList::AS_GNU);
}
-void Parser::ParseAttributeArgsCommon(
+unsigned Parser::ParseAttributeArgsCommon(
IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
@@ -302,7 +302,7 @@
ExprResult ArgExpr(ParseAssignmentExpression());
if (ArgExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
- return;
+ return 0;
}
ArgExprs.push_back(ArgExpr.release());
// Eat the comma, move to the next argument
@@ -318,6 +318,8 @@
if (EndLoc)
*EndLoc = RParen;
+
+ return static_cast<unsigned>(ArgExprs.size());
}
/// Parse the arguments to a parameterized GNU attribute or
@@ -392,6 +394,8 @@
return false;
}
+ SourceLocation OpenParenLoc = Tok.getLocation();
+
if (AttrName->getName() == "property") {
// The property declspec is more complex in that it can take one or two
// assignment expressions as a parameter, but the lhs of the assignment
@@ -406,7 +410,7 @@
AK_Put = 0,
AK_Get = 1 // indices into AccessorNames
};
- IdentifierInfo *AccessorNames[] = {0, 0};
+ IdentifierInfo *AccessorNames[] = {nullptr, nullptr};
bool HasInvalidAccessor = false;
// Parse the accessor specifications.
@@ -415,7 +419,8 @@
if (!Tok.is(tok::identifier)) {
// If the user wrote a completely empty list, use a special diagnostic.
if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&
- AccessorNames[AK_Put] == 0 && AccessorNames[AK_Get] == 0) {
+ AccessorNames[AK_Put] == nullptr &&
+ AccessorNames[AK_Get] == nullptr) {
Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter);
break;
}
@@ -475,7 +480,7 @@
if (Kind == AK_Invalid) {
// Just drop invalid accessors.
- } else if (AccessorNames[Kind] != NULL) {
+ } else if (AccessorNames[Kind] != nullptr) {
// Complain about the repeated accessor, ignore it, and keep parsing.
Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr;
} else {
@@ -498,15 +503,24 @@
// Only add the property attribute if it was well-formed.
if (!HasInvalidAccessor)
- Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, 0, SourceLocation(),
+ Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(),
AccessorNames[AK_Get], AccessorNames[AK_Put],
AttributeList::AS_Declspec);
T.skipToEnd();
return !HasInvalidAccessor;
}
- ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
- SourceLocation(), AttributeList::AS_Declspec);
+ unsigned NumArgs =
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
+ SourceLocation(), AttributeList::AS_Declspec);
+
+ // If this attribute's args were parsed, and it was expected to have
+ // arguments but none were provided, emit a diagnostic.
+ const AttributeList *Attr = Attrs.getList();
+ if (Attr && Attr->getMaxArgs() && !NumArgs) {
+ Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName;
+ return false;
+ }
return true;
}
@@ -570,7 +584,7 @@
<< AttrName->getName();
if (!AttrHandled)
- Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Declspec);
}
T.consumeClose();
@@ -585,7 +599,7 @@
Tok.is(tok::kw___sptr) || Tok.is(tok::kw___uptr)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Keyword);
}
}
@@ -595,7 +609,7 @@
while (Tok.is(tok::kw___pascal)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Keyword);
}
}
@@ -605,7 +619,7 @@
while (Tok.is(tok::kw___kernel)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Keyword);
}
}
@@ -613,7 +627,7 @@
void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = Tok.getLocation();
- Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Keyword);
}
@@ -887,7 +901,7 @@
// Record this attribute
attrs.addNew(&Availability,
SourceRange(AvailabilityLoc, T.getCloseLocation()),
- 0, AvailabilityLoc,
+ nullptr, AvailabilityLoc,
Platform,
Changes[Introduced],
Changes[Deprecated],
@@ -931,7 +945,7 @@
}
// Parse optional class method name.
- IdentifierLoc *ClassMethod = 0;
+ IdentifierLoc *ClassMethod = nullptr;
if (Tok.is(tok::identifier)) {
ClassMethod = ParseIdentifierLoc();
if (!TryConsumeToken(tok::colon)) {
@@ -950,7 +964,7 @@
}
// Parse optional instance method name.
- IdentifierLoc *InstanceMethod = 0;
+ IdentifierLoc *InstanceMethod = nullptr;
if (Tok.is(tok::identifier))
InstanceMethod = ParseIdentifierLoc();
else if (Tok.isNot(tok::r_paren)) {
@@ -969,12 +983,11 @@
// Record this attribute
attrs.addNew(&ObjCBridgeRelated,
SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),
- 0, ObjCBridgeRelatedLoc,
+ nullptr, ObjCBridgeRelatedLoc,
RelatedClass,
ClassMethod,
InstanceMethod,
AttributeList::AS_GNU);
-
}
// Late Parsed Attributes:
@@ -1081,7 +1094,8 @@
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
- 0, SourceLocation(), AttributeList::AS_GNU, 0);
+ nullptr, SourceLocation(), AttributeList::AS_GNU,
+ nullptr);
if (HasFunScope) {
Actions.ActOnExitFunctionContext();
@@ -1094,7 +1108,8 @@
// If there are multiple decls, then the decl cannot be within the
// function scope.
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
- 0, SourceLocation(), AttributeList::AS_GNU, 0);
+ nullptr, SourceLocation(), AttributeList::AS_GNU,
+ nullptr);
}
} else {
Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
@@ -1171,7 +1186,7 @@
}
if (!T.consumeClose()) {
- Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, 0, AttrNameLoc,
+ Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, nullptr, AttrNameLoc,
ArgumentKind, MatchingCType.release(),
LayoutCompatible, MustBeNull,
AttributeList::AS_GNU);
@@ -1276,8 +1291,8 @@
// parsing c none objective-c decls.
ObjCDeclContextSwitch ObjCDC(*this);
- Decl *SingleDecl = 0;
- Decl *OwnedType = 0;
+ Decl *SingleDecl = nullptr;
+ Decl *OwnedType = nullptr;
switch (Tok.getKind()) {
case tok::kw_template:
case tok::kw_export:
@@ -1607,7 +1622,8 @@
}
SmallVector<Decl *, 8> DeclsInGroup;
- Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D);
+ Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(
+ D, ParsedTemplateInfo(), FRI);
if (LateParsedAttrs.size() > 0)
ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false);
D.complete(FirstDecl);
@@ -1713,18 +1729,18 @@
/// According to the standard grammar, =default and =delete are function
/// definitions, but that definitely doesn't fit with the parser here.
///
-Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
- const ParsedTemplateInfo &TemplateInfo) {
+Decl *Parser::ParseDeclarationAfterDeclarator(
+ Declarator &D, const ParsedTemplateInfo &TemplateInfo) {
if (ParseAsmAttributesAfterDeclarator(D))
- return 0;
+ return nullptr;
return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);
}
-Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
- const ParsedTemplateInfo &TemplateInfo) {
+Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
+ Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {
// Inform the current actions module that we just parsed this declarator.
- Decl *ThisDecl = 0;
+ Decl *ThisDecl = nullptr;
switch (TemplateInfo.Kind) {
case ParsedTemplateInfo::NonTemplate:
ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -1747,7 +1763,7 @@
getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);
if (ThisRes.isInvalid()) {
SkipUntil(tok::semi, StopBeforeMatch);
- return 0;
+ return nullptr;
}
ThisDecl = ThisRes.get();
} else {
@@ -1771,8 +1787,8 @@
// Recover as if it were an explicit specialization.
TemplateParameterLists FakedParamLists;
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
- LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
+ 0, LAngleLoc));
ThisDecl =
Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);
@@ -1787,7 +1803,7 @@
// Parse declarator '=' initializer.
// If a '==' or '+=' is found, suggest a fixit to '='.
if (isTokenEqualOrEqualTypo()) {
- ConsumeToken();
+ SourceLocation EqualLoc = ConsumeToken();
if (Tok.is(tok::kw_delete)) {
if (D.isFunctionDeclarator())
@@ -1811,18 +1827,34 @@
Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
Actions.FinalizeDeclaration(ThisDecl);
cutOffParsing();
- return 0;
+ return nullptr;
}
ExprResult Init(ParseInitializer());
+ // If this is the only decl in (possibly) range based for statement,
+ // our best guess is that the user meant ':' instead of '='.
+ if (Tok.is(tok::r_paren) && FRI && D.isFirstDeclarator()) {
+ Diag(EqualLoc, diag::err_single_decl_assign_in_for_range)
+ << FixItHint::CreateReplacement(EqualLoc, ":");
+ // We are trying to stop parser from looking for ';' in this for
+ // statement, therefore preventing spurious errors to be issued.
+ FRI->ColonLoc = EqualLoc;
+ Init = ExprError();
+ FRI->RangeExpr = Init;
+ }
+
if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
ExitScope();
}
if (Init.isInvalid()) {
- SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
+ SmallVector<tok::TokenKind, 2> StopTokens;
+ StopTokens.push_back(tok::comma);
+ if (D.getContext() == Declarator::ForContext)
+ StopTokens.push_back(tok::r_paren);
+ SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);
Actions.ActOnInitializerError(ThisDecl);
} else
Actions.AddInitializerToDecl(ThisDecl, Init.take(),
@@ -1988,7 +2020,7 @@
///
bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
- AccessSpecifier AS, DeclSpecContext DSC,
+ AccessSpecifier AS, DeclSpecContext DSC,
ParsedAttributesWithRange &Attrs) {
assert(Tok.is(tok::identifier) && "should have identifier");
@@ -2035,8 +2067,8 @@
// This is a common problem in C (saying 'foo' instead of 'struct foo').
//
// C++ doesn't need this, and isTagName doesn't take SS.
- if (SS == 0) {
- const char *TagName = 0, *FixitTagName = 0;
+ if (SS == nullptr) {
+ const char *TagName = nullptr, *FixitTagName = nullptr;
tok::TokenKind TagKind = tok::unknown;
switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) {
@@ -2092,15 +2124,14 @@
// x(int n); // 'x' is not a type
// x (*p)[]; // 'x' is a type
//
- // Since we're in an error case (or the rare 'implicit int in C++' MS
- // extension), we can afford to perform a tentative parse to determine
- // which case we're in.
+ // Since we're in an error case, we can afford to perform a tentative
+ // parse to determine which case we're in.
TentativeParsingAction PA(*this);
ConsumeToken();
TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);
PA.Revert();
- if (TPR != TPResult::False()) {
+ if (TPR != TPResult::False) {
// The identifier is followed by a parenthesized declarator.
// It's supposed to be a type.
break;
@@ -2264,7 +2295,7 @@
ArgsVector ArgExprs;
ArgExprs.push_back(ArgExpr.release());
- Attrs.addNew(KWName, KWLoc, 0, KWLoc, ArgExprs.data(), 1,
+ Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1,
AttributeList::AS_Keyword, EllipsisLoc);
}
@@ -2420,7 +2451,7 @@
const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
while (1) {
bool isInvalid = false;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID = 0;
SourceLocation Loc = Tok.getLocation();
@@ -2726,7 +2757,7 @@
// it must be an implicit int or an error.
if (!TypeRep) {
ParsedAttributesWithRange Attrs(AttrFactory);
- if (ParseImplicitInt(DS, 0, TemplateInfo, AS, DSContext, Attrs)) {
+ if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) {
if (!Attrs.empty()) {
AttrsLastTime = true;
attrs.takeAllFrom(Attrs);
@@ -2787,7 +2818,7 @@
// GNU attributes support.
case tok::kw___attribute:
- ParseGNUAttributes(DS.getAttributes(), 0, LateAttrs);
+ ParseGNUAttributes(DS.getAttributes(), nullptr, LateAttrs);
continue;
// Microsoft declspec support.
@@ -2800,8 +2831,8 @@
isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID);
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = Tok.getLocation();
- DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
- AttributeList::AS_Keyword);
+ DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc,
+ nullptr, 0, AttributeList::AS_Keyword);
break;
}
@@ -3495,7 +3526,7 @@
}
// If an identifier is present, consume and remember it.
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
SourceLocation NameLoc;
if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
@@ -3534,13 +3565,13 @@
TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind());
// If the next token starts an expression, we know we're parsing a
// bit-field. This is the common case.
- if (TPR == TPResult::True())
+ if (TPR == TPResult::True)
PossibleBitfield = true;
// If the next token starts a type-specifier-seq, it may be either a
// a fixed underlying type or the start of a function-style cast in C++;
// lookahead one more token to see if it's obvious that we have a
// fixed underlying type.
- else if (TPR == TPResult::False() &&
+ else if (TPR == TPResult::False &&
GetLookAheadToken(2).getKind() == tok::semi) {
// Consume the ':'.
ConsumeToken();
@@ -3560,7 +3591,7 @@
// FIXME: The standard is not entirely clear on how to disambiguate in
// this case.
if ((getLangOpts().CPlusPlus &&
- isCXXDeclarationSpecifier(TPResult::True()) != TPResult::True()) ||
+ isCXXDeclarationSpecifier(TPResult::True) != TPResult::True) ||
(!getLangOpts().CPlusPlus && !isDeclarationSpecifier(true))) {
// We'll parse this as a bitfield later.
PossibleBitfield = true;
@@ -3669,7 +3700,7 @@
bool Owned = false;
bool IsDependent = false;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
StartLoc, SS, Name, NameLoc, attrs.getList(),
@@ -3687,9 +3718,8 @@
return;
}
- TypeResult Type = Actions.ActOnDependentTag(getCurScope(), DeclSpec::TST_enum,
- TUK, SS, Name, StartLoc,
- NameLoc);
+ TypeResult Type = Actions.ActOnDependentTag(
+ getCurScope(), DeclSpec::TST_enum, TUK, SS, Name, StartLoc, NameLoc);
if (Type.isInvalid()) {
DS.SetTypeSpecError();
return;
@@ -3750,7 +3780,7 @@
SmallVector<Decl *, 32> EnumConstantDecls;
- Decl *LastEnumConstDecl = 0;
+ Decl *LastEnumConstDecl = nullptr;
// Parse the enumerator-list.
while (Tok.isNot(tok::r_brace)) {
@@ -4350,7 +4380,7 @@
while (1) {
bool isInvalid = false;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID = 0;
SourceLocation Loc = Tok.getLocation();
@@ -4758,7 +4788,7 @@
// Once we're past the identifier, if the scope was bad, mark the
// whole declarator bad.
D.getCXXScopeSpec().isInvalid()) {
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
D.setInvalidType(true);
} else {
// Parsed the unqualified-id; update range information and move along.
@@ -4773,6 +4803,7 @@
"There's a C++-specific check for tok::identifier above");
assert(Tok.getIdentifierInfo() && "Not an identifier?");
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ D.SetRangeEnd(Tok.getLocation());
ConsumeToken();
goto PastIdentifier;
} else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) {
@@ -4782,7 +4813,7 @@
!isCXX11VirtSpecifier(Tok)) {
Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
<< FixItHint::CreateRemoval(Tok.getLocation());
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
ConsumeToken();
goto PastIdentifier;
}
@@ -4809,7 +4840,7 @@
} else if (D.mayOmitIdentifier()) {
// This could be something simple like "int" (in which case the declarator
// portion is empty), if an abstract-declarator is allowed.
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
// The grammar for abstract-pack-declarator does not allow grouping parens.
// FIXME: Revisit this once core issue 1488 is resolved.
@@ -4821,7 +4852,8 @@
LLVM_BUILTIN_TRAP;
if (D.getContext() == Declarator::MemberContext)
Diag(Tok, diag::err_expected_member_name_or_semi)
- << D.getDeclSpec().getSourceRange();
+ << (D.getDeclSpec().isEmpty() ? SourceRange()
+ : D.getDeclSpec().getSourceRange());
else if (getLangOpts().CPlusPlus) {
if (Tok.is(tok::period) || Tok.is(tok::arrow))
Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
@@ -4836,7 +4868,7 @@
}
} else
Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_paren;
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
D.setInvalidType(true);
}
@@ -4981,7 +5013,7 @@
// argument list. Recognize that this declarator will never have an
// identifier (and remember where it would have been), then call into
// ParseFunctionDeclarator to handle of argument list.
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
// Enter function-declaration scope, limiting any declarators to the
// function prototype scope, including parameter declarators.
@@ -5167,7 +5199,7 @@
DynamicExceptionRanges.data(),
DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
- NoexceptExpr.get() : 0,
+ NoexceptExpr.get() : nullptr,
StartLoc, LocalEndLoc, D,
TrailingReturnType),
FnAttrs, EndLoc);
@@ -5245,7 +5277,7 @@
// Remember this identifier in ParamInfo.
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
Tok.getLocation(),
- 0));
+ nullptr));
}
// Eat the identifier.
@@ -5335,11 +5367,11 @@
// DefArgToks is used when the parsing of default arguments needs
// to be delayed.
- CachedTokens *DefArgToks = 0;
+ CachedTokens *DefArgToks = nullptr;
// If no parameter was specified, verify that *something* was specified,
// otherwise we have a missing type and identifier.
- if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 &&
+ if (DS.isEmpty() && ParmDeclarator.getIdentifier() == nullptr &&
ParmDeclarator.getNumTypeObjects() == 0) {
// Completely missing, emit error.
Diag(DSStart, diag::err_missing_param);
@@ -5368,7 +5400,7 @@
if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) {
delete DefArgToks;
- DefArgToks = 0;
+ DefArgToks = nullptr;
Actions.ActOnParamDefaultArgumentError(Param);
} else {
// Mark the end of the default argument so that we know when to
@@ -5448,7 +5480,7 @@
MaybeParseCXX11Attributes(attrs);
// Remember that we parsed the empty array type.
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr,
T.getOpenLocation(),
T.getCloseLocation()),
attrs, T.getCloseLocation());
@@ -5576,7 +5608,7 @@
return;
}
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
@@ -5599,7 +5631,7 @@
return;
}
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
@@ -5635,7 +5667,7 @@
DS.setTypeofParensRange(T.getRange());
DS.SetRangeEnd(T.getCloseLocation());
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec,
DiagID, Result.release(),
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index cef748f..ddecd75 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -64,11 +64,11 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceDecl(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
SourceLocation IdentLoc;
- IdentifierInfo *Ident = 0;
+ IdentifierInfo *Ident = nullptr;
std::vector<SourceLocation> ExtraIdentLoc;
std::vector<IdentifierInfo*> ExtraIdent;
std::vector<SourceLocation> ExtraNamespaceLoc;
@@ -93,11 +93,11 @@
}
if (Tok.is(tok::equal)) {
- if (Ident == 0) {
+ if (!Ident) {
Diag(Tok, diag::err_expected) << tok::identifier;
// Skip to end of the definition and eat the ';'.
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
if (!attrs.empty())
Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
@@ -120,7 +120,7 @@
else
Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
- return 0;
+ return nullptr;
}
if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||
@@ -132,7 +132,7 @@
}
Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);
SkipUntil(tok::r_brace);
- return 0;
+ return nullptr;
}
if (!ExtraIdent.empty()) {
@@ -246,7 +246,7 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceAliasDecl(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
CXXScopeSpec SS;
@@ -257,7 +257,7 @@
Diag(Tok, diag::err_expected_namespace_name);
// Skip to end of the definition and eat the ';'.
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
// Parse identifier.
@@ -287,7 +287,7 @@
ParseScope LinkageScope(this, Scope::DeclScope);
Decl *LinkageSpec =
Lang.isInvalid()
- ? 0
+ ? nullptr
: Actions.ActOnStartLinkageSpecification(
getCurScope(), DS.getSourceRange().getBegin(), Lang.take(),
Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());
@@ -306,7 +306,7 @@
ParseExternalDeclaration(attrs, &DS);
return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
getCurScope(), LinkageSpec, SourceLocation())
- : 0;
+ : nullptr;
}
DS.abort();
@@ -356,7 +356,7 @@
T.consumeClose();
return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
getCurScope(), LinkageSpec, T.getCloseLocation())
- : 0;
+ : nullptr;
}
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
@@ -375,7 +375,7 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteUsing(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
// 'using namespace' means this is a using-directive.
@@ -421,14 +421,14 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteUsingDirective(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
- IdentifierInfo *NamespcName = 0;
+ IdentifierInfo *NamespcName = nullptr;
SourceLocation IdentLoc = SourceLocation();
// Parse namespace-name.
@@ -437,7 +437,7 @@
// If there was invalid namespace name, skip to end of decl, and eat ';'.
SkipUntil(tok::semi);
// FIXME: Are there cases, when we would like to call ActOnUsingDirective?
- return 0;
+ return nullptr;
}
// Parse identifier.
@@ -494,15 +494,16 @@
HasTypenameKeyword = true;
// Parse nested-name-specifier.
- IdentifierInfo *LastII = 0;
+ IdentifierInfo *LastII = nullptr;
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false,
- /*MayBePseudoDtor=*/0, /*IsTypename=*/false,
+ /*MayBePseudoDtor=*/nullptr,
+ /*IsTypename=*/false,
/*LastII=*/&LastII);
// Check nested-name specifier.
if (SS.isInvalid()) {
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
SourceLocation TemplateKWLoc;
@@ -531,7 +532,7 @@
/*AllowConstructorName=*/ true, ParsedType(),
TemplateKWLoc, Name)) {
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
ParsedAttributesWithRange Attrs(AttrFactory);
@@ -578,7 +579,7 @@
Diag(Range.getBegin(), diag::err_alias_declaration_specialization)
<< SpecKind << Range;
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
// Name must be an identifier.
@@ -586,7 +587,7 @@
Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier);
// No removal fixit: can't recover from this.
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
} else if (HasTypenameKeyword)
Diag(TypenameLoc, diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SourceRange(TypenameLoc,
@@ -595,7 +596,7 @@
Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SS.getRange());
- TypeAlias = ParseTypeName(0, TemplateInfo.Kind ?
+ TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind ?
Declarator::AliasTemplateContext :
Declarator::AliasDeclContext, AS, OwnedType,
&Attrs);
@@ -628,7 +629,7 @@
// Unfortunately, we have to bail out instead of recovering by
// ignoring the parameters, just in case the nested name specifier
// depends on the parameters.
- return 0;
+ return nullptr;
}
// "typename" keyword is allowed for identifiers only,
@@ -643,7 +644,7 @@
if (IsAliasDecl) {
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
MultiTemplateParamsArg TemplateParamsArg(
- TemplateParams ? TemplateParams->data() : 0,
+ TemplateParams ? TemplateParams->data() : nullptr,
TemplateParams ? TemplateParams->size() : 0);
return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
UsingLoc, Name, Attrs.getList(),
@@ -679,31 +680,31 @@
if (T.consumeOpen()) {
Diag(Tok, diag::err_expected) << tok::l_paren;
SkipMalformedDecl();
- return 0;
+ return nullptr;
}
ExprResult AssertExpr(ParseConstantExpression());
if (AssertExpr.isInvalid()) {
SkipMalformedDecl();
- return 0;
+ return nullptr;
}
if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
if (!isTokenStringLiteral()) {
Diag(Tok, diag::err_expected_string_literal)
<< /*Source='static_assert'*/1;
SkipMalformedDecl();
- return 0;
+ return nullptr;
}
ExprResult AssertMessage(ParseStringLiteralExpression());
if (AssertMessage.isInvalid()) {
SkipMalformedDecl();
- return 0;
+ return nullptr;
}
T.consumeClose();
@@ -768,7 +769,7 @@
// C++11 [dcl.type.simple]p4:
// The operand of the decltype specifier is an unevaluated operand.
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
- 0, /*IsDecltype=*/true);
+ nullptr,/*IsDecltype=*/true);
Result = ParseExpression();
if (Result.isInvalid()) {
DS.SetTypeSpecError();
@@ -809,7 +810,7 @@
}
assert(!Result.isInvalid());
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
// Check for duplicate type specifiers (e.g. "int decltype(a)").
@@ -865,7 +866,7 @@
if (T.getCloseLocation().isInvalid())
return;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec,
DiagID, Result.release(),
@@ -995,7 +996,7 @@
}
// We have an identifier; check whether it is actually a type.
- IdentifierInfo *CorrectedII = 0;
+ IdentifierInfo *CorrectedII = nullptr;
ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true,
false, ParsedType(),
/*IsCtorOrDtorName=*/false,
@@ -1015,7 +1016,7 @@
DS.SetRangeEnd(EndLocation);
DS.getTypeSpecScope() = SS;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,
Actions.getASTContext().getPrintingPolicy());
@@ -1030,7 +1031,7 @@
Tok.is(tok::kw___virtual_inheritance)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Keyword);
}
}
@@ -1241,9 +1242,9 @@
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
// Parse the (optional) class name or simple-template-id.
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
SourceLocation NameLoc;
- TemplateIdAnnotation *TemplateId = 0;
+ TemplateIdAnnotation *TemplateId = nullptr;
if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
@@ -1272,14 +1273,14 @@
if (TemplateParams && TemplateParams->size() > 1) {
TemplateParams->pop_back();
} else {
- TemplateParams = 0;
+ TemplateParams = nullptr;
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
= ParsedTemplateInfo::NonTemplate;
}
} else if (TemplateInfo.Kind
== ParsedTemplateInfo::ExplicitInstantiation) {
// Pretend this is just a forward declaration.
- TemplateParams = 0;
+ TemplateParams = nullptr;
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
= ParsedTemplateInfo::NonTemplate;
const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
@@ -1521,7 +1522,7 @@
if (TUK == Sema::TUK_Friend) {
Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation);
- TemplateParams = 0;
+ TemplateParams = nullptr;
} else {
SourceLocation LAngleLoc =
PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
@@ -1534,25 +1535,19 @@
// "template<>", so that we treat this construct as a class
// template specialization.
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
- LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
+ 0, LAngleLoc));
TemplateParams = &FakedParamLists;
}
}
// Build the class template specialization.
- TagOrTempResult
- = Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK,
- StartLoc, DS.getModulePrivateSpecLoc(), SS,
- TemplateId->Template,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc,
- attrs.getList(),
- MultiTemplateParamsArg(
- TemplateParams? &(*TemplateParams)[0] : 0,
- TemplateParams? TemplateParams->size() : 0));
+ TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
+ getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),
+ *TemplateId, attrs.getList(),
+ MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
+ : nullptr,
+ TemplateParams ? TemplateParams->size() : 0));
}
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Sema::TUK_Declaration) {
@@ -1578,7 +1573,8 @@
TagType, StartLoc, SS,
Name, NameLoc, attrs.getList(),
MultiTemplateParamsArg(
- TemplateParams? &(*TemplateParams)[0] : 0,
+ TemplateParams? &(*TemplateParams)[0]
+ : nullptr,
TemplateParams? TemplateParams->size() : 0));
} else {
if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
@@ -1590,7 +1586,7 @@
// recover by ignoring the 'template' keyword.
Diag(Tok, diag::err_template_defn_explicit_instantiation)
<< 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
- TemplateParams = 0;
+ TemplateParams = nullptr;
}
bool IsDependent = false;
@@ -1633,7 +1629,7 @@
ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
}
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
bool Result;
if (!TypeResult.isInvalid()) {
@@ -1805,7 +1801,7 @@
Decl *ThisDecl) {
// We just declared a member function. If this member function
// has any default arguments, we'll need to parse them later.
- LateParsedMethodDeclaration *LateMethod = 0;
+ LateParsedMethodDeclaration *LateMethod = nullptr;
DeclaratorChunk::FunctionTypeInfo &FTI
= DeclaratorInfo.getFunctionTypeInfo();
@@ -1880,7 +1876,7 @@
// C++ [class.mem]p8:
// A virt-specifier-seq shall contain at most one of each virt-specifier.
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))
Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier)
<< PrevSpec
@@ -2050,7 +2046,7 @@
/* HasUsingKeyword */ false,
SourceLocation(),
SS, Name,
- /* AttrList */ 0,
+ /* AttrList */ nullptr,
/* HasTypenameKeyword */ false,
SourceLocation());
return;
@@ -2139,7 +2135,8 @@
return;
MultiTemplateParamsArg TemplateParams(
- TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+ TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data()
+ : nullptr,
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
if (TryConsumeToken(tok::semi)) {
@@ -2288,7 +2285,7 @@
// this call will *not* return the created decl; It will return null.
// See Sema::ActOnCXXMemberDeclarator for details.
- NamedDecl *ThisDecl = 0;
+ NamedDecl *ThisDecl = nullptr;
if (DS.isFriendSpecified()) {
// C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
// to a friend declaration, that declaration shall be a definition.
@@ -2312,7 +2309,7 @@
VS, HasInClassInit);
if (VarTemplateDecl *VT =
- ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : 0)
+ ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : nullptr)
// Re-direct this decl to refer to the templated decl so that we can
// initialize it.
ThisDecl = VT->getTemplatedDecl();
@@ -2648,6 +2645,11 @@
continue;
}
+ if (Tok.is(tok::annot_pragma_ms_pragma)) {
+ HandlePragmaMSPragma();
+ continue;
+ }
+
// If we see a namespace here, a close brace was missing somewhere.
if (Tok.is(tok::kw_namespace)) {
DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
@@ -2863,7 +2865,7 @@
return true;
}
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
DeclSpec DS(AttrFactory);
SourceLocation IdLoc = Tok.getLocation();
if (Tok.is(tok::annot_decltype)) {
@@ -3159,7 +3161,7 @@
Loc = ConsumeToken();
return II;
}
- return 0;
+ return nullptr;
case tok::ampamp: // 'and'
case tok::pipe: // 'bitor'
@@ -3180,7 +3182,7 @@
Loc = ConsumeToken();
return &PP.getIdentifierTable().get(Spelling);
}
- return 0;
+ return nullptr;
}
}
@@ -3189,6 +3191,7 @@
switch (AttributeList::getKind(AttrName, ScopeName,
AttributeList::AS_CXX11)) {
case AttributeList::AT_CarriesDependency:
+ case AttributeList::AT_Deprecated:
case AttributeList::AT_FallThrough:
case AttributeList::AT_CXX11NoReturn: {
return true;
@@ -3220,6 +3223,7 @@
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc) {
assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
+ SourceLocation LParenLoc = Tok.getLocation();
// If the attribute isn't known, we will not attempt to parse any
// arguments.
@@ -3235,10 +3239,34 @@
// GNU-scoped attributes have some special cases to handle GNU-specific
// behaviors.
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
- ScopeLoc, AttributeList::AS_CXX11, 0);
- else
- ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
- ScopeLoc, AttributeList::AS_CXX11);
+ ScopeLoc, AttributeList::AS_CXX11, nullptr);
+ else {
+ unsigned NumArgs =
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, AttributeList::AS_CXX11);
+
+ const AttributeList *Attr = Attrs.getList();
+ if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
+ // If the attribute is a standard or built-in attribute and we are
+ // parsing an argument list, we need to determine whether this attribute
+ // was allowed to have an argument list (such as [[deprecated]]), and how
+ // many arguments were parsed (so we can diagnose on [[deprecated()]]).
+ if (Attr->getMaxArgs() && !NumArgs) {
+ // The attribute was allowed to have arguments, but none were provided
+ // even though the attribute parsed successfully. This is an error.
+ // FIXME: This is a good place for a fixit which removes the parens.
+ Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
+ return false;
+ } else if (!Attr->getMaxArgs()) {
+ // The attribute parsed successfully, but was not allowed to have any
+ // arguments. It doesn't matter whether any were provided -- the
+ // presence of the argument list (even if empty) is diagnosed.
+ Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
+ << AttrName;
+ return false;
+ }
+ }
+ }
return true;
}
@@ -3290,7 +3318,7 @@
continue;
SourceLocation ScopeLoc, AttrLoc;
- IdentifierInfo *ScopeName = 0, *AttrName = 0;
+ IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;
AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
if (!AttrName)
@@ -3319,20 +3347,15 @@
<< AttrName << SourceRange(SeenAttrs[AttrName]);
// Parse attribute arguments
- if (Tok.is(tok::l_paren)) {
- if (StandardAttr)
- Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
- << AttrName->getName();
-
+ if (Tok.is(tok::l_paren))
AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc,
ScopeName, ScopeLoc);
- }
if (!AttrParsed)
attrs.addNew(AttrName,
SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
AttrLoc),
- ScopeName, ScopeLoc, 0, 0, AttributeList::AS_CXX11);
+ ScopeName, ScopeLoc, nullptr, 0, AttributeList::AS_CXX11);
if (TryConsumeToken(tok::ellipsis))
Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
@@ -3473,7 +3496,7 @@
}
// Parse all the comma separated declarators.
- ParseCXXClassMemberDeclaration(CurAS, 0);
+ ParseCXXClassMemberDeclaration(CurAS, nullptr);
}
Braces.consumeClose();
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index ed9d72d..209b071 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -261,12 +261,12 @@
TernaryMiddle = ParseExpression();
if (TernaryMiddle.isInvalid()) {
LHS = ExprError();
- TernaryMiddle = 0;
+ TernaryMiddle = nullptr;
}
} else {
// Special case handling of "X ? Y : Z" where Y is empty:
// logical-OR-expression '?' ':' conditional-expression [GNU]
- TernaryMiddle = 0;
+ TernaryMiddle = nullptr;
Diag(Tok, diag::ext_gnu_conditional_expr);
}
@@ -637,18 +637,12 @@
// If this expression is limited to being a unary-expression, the parent can
// not start a cast expression.
ParenParseOption ParenExprType =
- (isUnaryExpression && !getLangOpts().CPlusPlus)? CompoundLiteral : CastExpr;
+ (isUnaryExpression && !getLangOpts().CPlusPlus) ? CompoundLiteral
+ : CastExpr;
ParsedType CastTy;
SourceLocation RParenLoc;
-
- {
- // The inside of the parens don't need to be a colon protected scope, and
- // isn't immediately a message send.
- ColonProtectionRAIIObject X(*this, false);
-
- Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
- isTypeCast == IsTypeCast, CastTy, RParenLoc);
- }
+ Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
+ isTypeCast == IsTypeCast, CastTy, RParenLoc);
switch (ParenExprType) {
case SimpleExpr: break; // Nothing else to do.
@@ -688,7 +682,7 @@
return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
case tok::annot_primary_expr:
- assert(Res.get() == 0 && "Stray primary-expression annotation?");
+ assert(Res.get() == nullptr && "Stray primary-expression annotation?");
Res = getExprAnnotation(Tok);
ConsumeToken();
break;
@@ -767,8 +761,8 @@
((Tok.is(tok::identifier) &&
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||
Tok.is(tok::code_completion))) {
- Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(),
- 0);
+ Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(),
+ nullptr);
break;
}
@@ -789,7 +783,7 @@
DeclSpec DS(AttrFactory);
DS.SetRangeStart(ILoc);
DS.SetRangeEnd(ILoc);
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
Actions.getASTContext().getPrintingPolicy());
@@ -799,10 +793,10 @@
DeclaratorInfo);
if (Ty.isInvalid())
break;
-
+
Res = ParseObjCMessageExpressionBody(SourceLocation(),
SourceLocation(),
- Ty.get(), 0);
+ Ty.get(), nullptr);
break;
}
}
@@ -835,6 +829,7 @@
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]
+ case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS]
case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
@@ -919,7 +914,7 @@
if (Tok.isNot(tok::identifier))
return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
- if (getCurScope()->getFnParent() == 0)
+ if (getCurScope()->getFnParent() == nullptr)
return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
@@ -954,7 +949,7 @@
DS.SetRangeStart(Tok.getLocation());
DS.SetRangeEnd(Tok.getLastLoc());
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(),
PrevSpec, DiagID, Type,
@@ -967,7 +962,7 @@
ConsumeToken();
Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
- Ty.get(), 0);
+ Ty.get(), nullptr);
break;
}
// Fall through
@@ -1272,8 +1267,8 @@
// '(' argument-expression-list[opt] ')'
tok::TokenKind OpKind = Tok.getKind();
InMessageExpressionRAIIObject InMessage(*this, false);
-
- Expr *ExecConfig = 0;
+
+ Expr *ExecConfig = nullptr;
BalancedDelimiterTracker PT(*this, tok::l_paren);
@@ -1437,7 +1432,8 @@
if (!LHS.isInvalid())
LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.take(), OpLoc,
OpKind, SS, TemplateKWLoc, Name,
- CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : 0,
+ CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
+ : nullptr,
Tok.is(tok::l_paren));
break;
}
@@ -1579,7 +1575,7 @@
if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) {
SourceLocation EllipsisLoc = ConsumeToken();
SourceLocation LParenLoc, RParenLoc;
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
SourceLocation NameLoc;
if (Tok.is(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -1926,6 +1922,7 @@
bool isTypeCast, ParsedType &CastTy,
SourceLocation &RParenLoc) {
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
+ ColonProtectionRAIIObject ColonProtection(*this, false);
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen())
return ExprError();
@@ -2001,6 +1998,7 @@
TypeResult Ty = ParseTypeName();
T.consumeClose();
+ ColonProtection.restore();
RParenLoc = T.getCloseLocation();
ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
@@ -2021,7 +2019,8 @@
// if stopIfCastExpr is false, we need to determine the context past the
// parens, so we defer to ParseCXXAmbiguousParenExpression for that.
if (isAmbiguousTypeId && !stopIfCastExpr) {
- ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T);
+ ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T,
+ ColonProtection);
RParenLoc = T.getCloseLocation();
return res;
}
@@ -2045,10 +2044,11 @@
}
Result = ParseObjCMessageExpressionBody(SourceLocation(),
SourceLocation(),
- Ty.get(), 0);
+ Ty.get(), nullptr);
} else {
// Match the ')'.
T.consumeClose();
+ ColonProtection.restore();
RParenLoc = T.getCloseLocation();
if (Tok.is(tok::l_brace)) {
ExprType = CompoundLiteral;
@@ -2077,7 +2077,7 @@
CastTy = Ty.get();
return ExprResult();
}
-
+
// Reject the cast of super idiom in ObjC.
if (Tok.is(tok::identifier) && getLangOpts().ObjC1 &&
Tok.getIdentifierInfo() == Ident_super &&
@@ -2124,7 +2124,8 @@
// Don't build a paren expression unless we actually match a ')'.
if (!Result.isInvalid() && Tok.is(tok::r_paren))
- Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take());
+ Result =
+ Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take());
}
// Match the ')'.
@@ -2181,7 +2182,8 @@
// Pass the set of string tokens, ready for concatenation, to the actions.
return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size(),
- AllowUserDefinedLiteral ? getCurScope() : 0);
+ AllowUserDefinedLiteral ? getCurScope()
+ : nullptr);
}
/// ParseGenericSelectionExpression - Parse a C11 generic-selection
@@ -2433,7 +2435,7 @@
// SetIdentifier sets the source range end, but in this case we're past
// that location.
SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
- ParamInfo.SetIdentifier(0, CaretLoc);
+ ParamInfo.SetIdentifier(nullptr, CaretLoc);
ParamInfo.SetRangeEnd(Tmp);
if (ParamInfo.isInvalidType()) {
// If there was an error parsing the arguments, they may have
@@ -2456,7 +2458,7 @@
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true,
/*IsAmbiguous=*/false,
/*RParenLoc=*/NoLoc,
- /*ArgInfo=*/0,
+ /*ArgInfo=*/nullptr,
/*NumArgs=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
@@ -2468,10 +2470,10 @@
/*MutableLoc=*/NoLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
- /*Exceptions=*/0,
- /*ExceptionRanges=*/0,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
- /*NoexceptExpr=*/0,
+ /*NoexceptExpr=*/nullptr,
CaretLoc, CaretLoc,
ParamInfo),
attrs, CaretLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index f10ca6a..ff19826 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -207,7 +207,7 @@
}
if (LastII)
- *LastII = 0;
+ *LastII = nullptr;
bool HasScopeSpecifier = false;
@@ -365,15 +365,15 @@
// Consume the template-id token.
ConsumeToken();
-
+
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
HasScopeSpecifier = true;
-
+
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
-
+
if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(),
SS,
TemplateId->TemplateKWLoc,
@@ -393,7 +393,6 @@
continue;
}
-
// The rest of the nested-name-specifier possibilities start with
// tok::identifier.
if (Tok.isNot(tok::identifier))
@@ -418,9 +417,8 @@
// error, but they probably meant something else strange so don't
// recover like this.
PP.LookAhead(1).is(tok::identifier)) {
- Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
+ Diag(Next, diag::err_unexpected_colon_in_nested_name_spec)
<< FixItHint::CreateReplacement(Next.getLocation(), "::");
-
// Recover as if the user wrote '::'.
Next.setKind(tok::coloncolon);
}
@@ -434,23 +432,52 @@
return false;
}
+ if (ColonIsSacred) {
+ const Token &Next2 = GetLookAheadToken(2);
+ if (Next2.is(tok::kw_private) || Next2.is(tok::kw_protected) ||
+ Next2.is(tok::kw_public) || Next2.is(tok::kw_virtual)) {
+ Diag(Next2, diag::err_unexpected_token_in_nested_name_spec)
+ << Next2.getName()
+ << FixItHint::CreateReplacement(Next.getLocation(), ":");
+ Token ColonColon;
+ PP.Lex(ColonColon);
+ ColonColon.setKind(tok::colon);
+ PP.EnterToken(ColonColon);
+ break;
+ }
+ }
+
if (LastII)
*LastII = &II;
// We have an identifier followed by a '::'. Lookup this name
// as the name in a nested-name-specifier.
+ Token Identifier = Tok;
SourceLocation IdLoc = ConsumeToken();
assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
"NextToken() not working properly!");
+ Token ColonColon = Tok;
SourceLocation CCLoc = ConsumeToken();
CheckForLParenAfterColonColon();
- HasScopeSpecifier = true;
+ bool IsCorrectedToColon = false;
+ bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr;
if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc,
- ObjectType, EnteringContext, SS))
+ ObjectType, EnteringContext, SS,
+ false, CorrectionFlagPtr)) {
+ // Identifier is not recognized as a nested name, but we can have
+ // mistyped '::' instead of ':'.
+ if (CorrectionFlagPtr && IsCorrectedToColon) {
+ ColonColon.setKind(tok::colon);
+ PP.EnterToken(Tok);
+ PP.EnterToken(ColonColon);
+ Tok = Identifier;
+ break;
+ }
SS.SetInvalid(SourceRange(IdLoc, CCLoc));
-
+ }
+ HasScopeSpecifier = true;
continue;
}
@@ -740,7 +767,7 @@
!Intro.Captures.empty())) {
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
- ConsumeCodeCompletionToken();
+ cutOffParsing();
break;
}
@@ -757,7 +784,7 @@
else
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
- ConsumeCodeCompletionToken();
+ cutOffParsing();
break;
}
@@ -766,7 +793,7 @@
// Parse capture.
LambdaCaptureKind Kind = LCK_ByCopy;
SourceLocation Loc;
- IdentifierInfo* Id = 0;
+ IdentifierInfo *Id = nullptr;
SourceLocation EllipsisLoc;
ExprResult Init;
@@ -781,7 +808,7 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/true);
- ConsumeCodeCompletionToken();
+ cutOffParsing();
break;
}
}
@@ -837,8 +864,8 @@
// [..., x = expr
//
// We need to find the end of the following expression in order to
- // determine whether this is an Obj-C message send's receiver, or a
- // lambda init-capture.
+ // determine whether this is an Obj-C message send's receiver, a
+ // C99 designator, or a lambda init-capture.
//
// Parse the expression to find where it ends, and annotate it back
// onto the tokens. We would have parsed this expression the same way
@@ -1065,7 +1092,7 @@
DynamicExceptionRanges.data(),
DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
- NoexceptExpr.get() : 0,
+ NoexceptExpr.get() : nullptr,
LParenLoc, FunLocalRangeEnd, D,
TrailingReturnType),
Attr, DeclEndLoc);
@@ -1117,7 +1144,7 @@
D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
/*isAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
- /*Params=*/0,
+ /*Params=*/nullptr,
/*NumParams=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
@@ -1129,10 +1156,10 @@
MutableLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
- /*Exceptions=*/0,
- /*ExceptionRanges=*/0,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
- /*NoexceptExpr=*/0,
+ /*NoexceptExpr=*/nullptr,
DeclLoc, DeclEndLoc, D,
TrailingReturnType),
Attr, DeclEndLoc);
@@ -1174,7 +1201,7 @@
///
ExprResult Parser::ParseCXXCasts() {
tok::TokenKind Kind = Tok.getKind();
- const char *CastName = 0; // For error messages
+ const char *CastName = nullptr; // For error messages
switch (Kind) {
default: llvm_unreachable("Unknown C++ cast!");
@@ -1390,7 +1417,7 @@
assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
CCLoc = ConsumeToken();
} else {
- FirstTypeName.setIdentifier(0, SourceLocation());
+ FirstTypeName.setIdentifier(nullptr, SourceLocation());
}
// Parse the tilde.
@@ -1462,7 +1489,7 @@
case tok::r_brace:
case tok::colon:
case tok::comma:
- return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, 0);
+ return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, nullptr);
default:
ExprResult Expr(ParseAssignmentExpression());
@@ -1581,7 +1608,7 @@
// Parse the expression.
ExprOut = ParseExpression(); // expression
- DeclOut = 0;
+ DeclOut = nullptr;
if (ExprOut.isInvalid())
return true;
@@ -1969,7 +1996,7 @@
TemplateId->Operator = OO_None;
TemplateId->TemplateNameLoc = Id.StartLocation;
} else {
- TemplateId->Name = 0;
+ TemplateId->Name = nullptr;
TemplateId->Operator = Id.OperatorFunctionId.Operator;
TemplateId->TemplateNameLoc = Id.StartLocation;
}
@@ -2174,7 +2201,7 @@
// Grab the literal operator's suffix, which will be either the next token
// or a ud-suffix from the string literal.
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
SourceLocation SuffixLoc;
if (!Literal.getUDSuffix().empty()) {
II = &PP.getIdentifierTable().get(Literal.getUDSuffix());
@@ -2235,8 +2262,8 @@
// Parse the conversion-declarator, which is merely a sequence of
// ptr-operators.
Declarator D(DS, Declarator::ConversionIdContext);
- ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
-
+ ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr);
+
// Finish up the type.
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D);
if (Ty.isInvalid())
@@ -2392,10 +2419,10 @@
Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
(TemplateSpecified || Tok.is(tok::less)))
return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
- 0, SourceLocation(),
+ nullptr, SourceLocation(),
EnteringContext, ObjectType,
Result, TemplateSpecified);
-
+
return false;
}
@@ -2834,7 +2861,7 @@
switch (ATT) {
case ATT_ArrayRank: {
T.consumeClose();
- return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL,
+ return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), nullptr,
T.getCloseLocation());
}
case ATT_ArrayExtent: {
@@ -2882,7 +2909,8 @@
ExprResult
Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ParsedType &CastTy,
- BalancedDelimiterTracker &Tracker) {
+ BalancedDelimiterTracker &Tracker,
+ ColonProtectionRAIIObject &ColonProt) {
assert(getLangOpts().CPlusPlus && "Should only be called for C++!");
assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
assert(isTypeIdInParens() && "Not a type-id!");
@@ -2931,6 +2959,7 @@
// Try parsing the cast-expression that may follow.
// If it is not a cast-expression, NotCastExpr will be true and no token
// will be consumed.
+ ColonProt.restore();
Result = ParseCastExpression(false/*isUnaryExpression*/,
false/*isAddressofOperand*/,
NotCastExpr,
@@ -2956,17 +2985,24 @@
if (ParseAs >= CompoundLiteral) {
// Parse the type declarator.
DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS);
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
- ParseDeclarator(DeclaratorInfo);
+ {
+ ColonProtectionRAIIObject InnerColonProtection(*this);
+ ParseSpecifierQualifierList(DS);
+ ParseDeclarator(DeclaratorInfo);
+ }
// Match the ')'.
Tracker.consumeClose();
+ ColonProt.restore();
if (ParseAs == CompoundLiteral) {
ExprType = CompoundLiteral;
- TypeResult Ty = ParseTypeName();
- return ParseCompoundLiteralExpression(Ty.get(),
+ if (DeclaratorInfo.isInvalidType())
+ return ExprError();
+
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ return ParseCompoundLiteralExpression(Ty.get(),
Tracker.getOpenLocation(),
Tracker.getCloseLocation());
}
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 44053f1..163b35a 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -66,45 +66,29 @@
}
// Parse up to (at most) the token after the closing ']' to determine
- // whether this is a C99 designator or a lambda.
+ // whether this is a C99 designator or a lambda.
TentativeParsingAction Tentative(*this);
- ConsumeBracket();
- while (true) {
- switch (Tok.getKind()) {
- case tok::equal:
- case tok::amp:
- case tok::identifier:
- case tok::kw_this:
- // These tokens can occur in a capture list or a constant-expression.
- // Keep looking.
- ConsumeToken();
- continue;
-
- case tok::comma:
- // Since a comma cannot occur in a constant-expression, this must
- // be a lambda.
- Tentative.Revert();
- return false;
-
- case tok::r_square: {
- // Once we hit the closing square bracket, we look at the next
- // token. If it's an '=', this is a designator. Otherwise, it's a
- // lambda expression. This decision favors lambdas over the older
- // GNU designator syntax, which allows one to omit the '=', but is
- // consistent with GCC.
- ConsumeBracket();
- tok::TokenKind Kind = Tok.getKind();
- Tentative.Revert();
- return Kind == tok::equal;
- }
-
- default:
- // Anything else cannot occur in a lambda capture list, so it
- // must be a designator.
- Tentative.Revert();
- return true;
- }
+
+ LambdaIntroducer Intro;
+ bool SkippedInits = false;
+ Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits));
+
+ if (DiagID) {
+ // If this can't be a lambda capture list, it's a designator.
+ Tentative.Revert();
+ return true;
}
+
+ // Once we hit the closing square bracket, we look at the next
+ // token. If it's an '=', this is a designator. Otherwise, it's a
+ // lambda expression. This decision favors lambdas over the older
+ // GNU designator syntax, which allows one to omit the '=', but is
+ // consistent with GCC.
+ tok::TokenKind Kind = Tok.getKind();
+ // FIXME: If we didn't skip any inits, parse the lambda from here
+ // rather than throwing away then reparsing the LambdaIntroducer.
+ Tentative.Revert();
+ return Kind == tok::equal;
}
static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
@@ -235,7 +219,7 @@
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
ConsumeToken(),
ParsedType(),
- 0);
+ nullptr);
}
// Parse the receiver, which is either a type or an expression.
@@ -253,7 +237,7 @@
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
ParsedType::getFromOpaquePtr(TypeOrExpr),
- 0);
+ nullptr);
}
// If the receiver was an expression, we still don't know
@@ -280,7 +264,7 @@
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
ConsumeToken(),
ParsedType(),
- 0);
+ nullptr);
ConsumeToken(); // the identifier
if (!ReceiverType) {
SkipUntil(tok::r_square, StopAtSemi);
@@ -290,7 +274,7 @@
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
ReceiverType,
- 0);
+ nullptr);
case Sema::ObjCInstanceMessage:
// Fall through; we'll just parse the expression and
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 776dbd6..2878aa0 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -51,8 +51,8 @@
cutOffParsing();
return DeclGroupPtrTy();
}
-
- Decl *SingleDecl = 0;
+
+ Decl *SingleDecl = nullptr;
switch (Tok.getObjCKeywordID()) {
case tok::objc_class:
return ParseObjCAtClassDeclaration(AtLoc);
@@ -83,11 +83,11 @@
return ParseModuleImport(AtLoc);
Diag(AtLoc, diag::err_atimport);
SkipUntil(tok::semi);
- return Actions.ConvertDeclToDeclGroup(0);
+ return Actions.ConvertDeclToDeclGroup(nullptr);
default:
Diag(AtLoc, diag::err_unexpected_at);
SkipUntil(tok::semi);
- SingleDecl = 0;
+ SingleDecl = nullptr;
break;
}
return Actions.ConvertDeclToDeclGroup(SingleDecl);
@@ -109,7 +109,7 @@
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
- return Actions.ConvertDeclToDeclGroup(0);
+ return Actions.ConvertDeclToDeclGroup(nullptr);
}
ClassNames.push_back(Tok.getIdentifierInfo());
ClassLocs.push_back(Tok.getLocation());
@@ -121,7 +121,7 @@
// Consume the ';'.
if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))
- return Actions.ConvertDeclToDeclGroup(0);
+ return Actions.ConvertDeclToDeclGroup(nullptr);
return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
ClassLocs.data(),
@@ -187,7 +187,7 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
MaybeSkipAttributes(tok::objc_interface);
@@ -195,7 +195,7 @@
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected)
<< tok::identifier; // missing class or category name.
- return 0;
+ return nullptr;
}
// We have a class or category name - consume it.
@@ -208,11 +208,11 @@
T.consumeOpen();
SourceLocation categoryLoc;
- IdentifierInfo *categoryId = 0;
+ IdentifierInfo *categoryId = nullptr;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
cutOffParsing();
- return 0;
+ return nullptr;
}
// For ObjC2, the category name is optional (not an error).
@@ -223,13 +223,13 @@
else if (!getLangOpts().ObjC2) {
Diag(Tok, diag::err_expected)
<< tok::identifier; // missing category name.
- return 0;
+ return nullptr;
}
T.consumeClose();
if (T.getCloseLocation().isInvalid())
- return 0;
-
+ return nullptr;
+
if (!attrs.empty()) { // categories don't support attributes.
Diag(nameLoc, diag::err_objc_no_attributes_on_category);
attrs.clear();
@@ -242,7 +242,7 @@
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
LAngleLoc, EndProtoLoc))
- return 0;
+ return nullptr;
Decl *CategoryType =
Actions.ActOnStartCategoryInterface(AtLoc,
@@ -260,7 +260,7 @@
return CategoryType;
}
// Parse a class interface.
- IdentifierInfo *superClassId = 0;
+ IdentifierInfo *superClassId = nullptr;
SourceLocation superClassLoc;
if (Tok.is(tok::colon)) { // a super class is specified.
@@ -270,13 +270,13 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected)
<< tok::identifier; // missing super class name.
- return 0;
+ return nullptr;
}
superClassId = Tok.getIdentifierInfo();
superClassLoc = ConsumeToken();
@@ -288,7 +288,7 @@
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
LAngleLoc, EndProtoLoc))
- return 0;
+ return nullptr;
if (Tok.isNot(tok::less))
Actions.ActOnTypedefedProtocols(ProtocolRefs, superClassId, superClassLoc);
@@ -330,7 +330,7 @@
}
void invoke(ParsingFieldDeclarator &FD) override {
- if (FD.D.getIdentifier() == 0) {
+ if (FD.D.getIdentifier() == nullptr) {
P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
<< FD.D.getSourceRange();
return;
@@ -577,7 +577,7 @@
const IdentifierInfo *II = Tok.getIdentifierInfo();
// If this is not an identifier at all, bail out early.
- if (II == 0) {
+ if (!II) {
T.consumeClose();
return;
}
@@ -698,7 +698,7 @@
switch (Tok.getKind()) {
default:
- return 0;
+ return nullptr;
case tok::ampamp:
case tok::ampequal:
case tok::amp:
@@ -717,7 +717,7 @@
SelectorLoc = ConsumeToken();
return II;
}
- return 0;
+ return nullptr;
}
case tok::identifier:
@@ -845,7 +845,7 @@
}
DS.setObjCDeclQualifier(Qual);
ConsumeToken();
- II = 0;
+ II = nullptr;
break;
}
@@ -866,7 +866,7 @@
// Clear out the next pointer. We're really completely
// destroying the internal invariants of the declarator here,
// but it doesn't matter because we're done with it.
- cur->setNext(0);
+ cur->setNext(nullptr);
attrs.add(cur);
}
}
@@ -897,7 +897,8 @@
ParsedAttributes *paramAttrs) {
assert(context == Declarator::ObjCParameterContext ||
context == Declarator::ObjCResultContext);
- assert((paramAttrs != 0) == (context == Declarator::ObjCParameterContext));
+ assert((paramAttrs != nullptr) ==
+ (context == Declarator::ObjCParameterContext));
assert(Tok.is(tok::l_paren) && "expected (");
@@ -994,14 +995,15 @@
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
/*ReturnType=*/ ParsedType());
cutOffParsing();
- return 0;
+ return nullptr;
}
// Parse the return type if present.
ParsedType ReturnType;
ObjCDeclSpec DSRet;
if (Tok.is(tok::l_paren))
- ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, 0);
+ ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext,
+ nullptr);
// If attributes exist before the method, parse them.
ParsedAttributes methodAttrs(AttrFactory);
@@ -1012,7 +1014,7 @@
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
ReturnType);
cutOffParsing();
- return 0;
+ return nullptr;
}
// Now parse the selector.
@@ -1025,7 +1027,7 @@
<< SourceRange(mLoc, Tok.getLocation());
// Skip until we get a ; or @.
SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
- return 0;
+ return nullptr;
}
SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
@@ -1038,7 +1040,7 @@
Decl *Result
= Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
mType, DSRet, ReturnType,
- selLoc, Sel, 0,
+ selLoc, Sel, nullptr,
CParamInfo.data(), CParamInfo.size(),
methodAttrs.getList(), MethodImplKind,
false, MethodDefinition);
@@ -1069,7 +1071,7 @@
// If attributes exist before the argument name, parse them.
// Regardless, collect all the attributes we've parsed so far.
- ArgInfo.ArgAttrs = 0;
+ ArgInfo.ArgAttrs = nullptr;
if (getLangOpts().ObjC2) {
MaybeParseGNUAttributes(paramAttrs);
ArgInfo.ArgAttrs = paramAttrs.getList();
@@ -1083,7 +1085,7 @@
/*AtParameterName=*/true,
ReturnType, KeyIdents);
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
@@ -1110,7 +1112,7 @@
/*AtParameterName=*/false,
ReturnType, KeyIdents);
cutOffParsing();
- return 0;
+ return nullptr;
}
// Check for another keyword selector.
@@ -1152,7 +1154,7 @@
CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
ParmDecl.getIdentifierLoc(),
Param,
- 0));
+ nullptr));
}
// FIXME: Add support for optional parameter list...
@@ -1161,8 +1163,8 @@
MaybeParseGNUAttributes(methodAttrs);
if (KeyIdents.size() == 0)
- return 0;
-
+ return nullptr;
+
Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
&KeyIdents[0]);
Decl *Result
@@ -1255,7 +1257,7 @@
// for code rewriting tools that need to be aware of the empty list.
Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
AllIvarDecls,
- T.getOpenLocation(), T.getCloseLocation(), 0);
+ T.getOpenLocation(), T.getCloseLocation(), nullptr);
}
/// objc-class-instance-variables:
@@ -1510,13 +1512,13 @@
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken(); // consume class or category name
- Decl *ObjCImpDecl = 0;
+ Decl *ObjCImpDecl = nullptr;
if (Tok.is(tok::l_paren)) {
// we have a category implementation.
ConsumeParen();
SourceLocation categoryLoc, rparenLoc;
- IdentifierInfo *categoryId = 0;
+ IdentifierInfo *categoryId = nullptr;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
@@ -1551,7 +1553,7 @@
} else {
// We have a class implementation
SourceLocation superClassLoc;
- IdentifierInfo *superClassId = 0;
+ IdentifierInfo *superClassId = nullptr;
if (TryConsumeToken(tok::colon)) {
// We have a super class
if (Tok.isNot(tok::identifier)) {
@@ -1619,7 +1621,7 @@
<< Sema::OCK_Implementation;
}
}
- P.CurParsedObjCImpl = 0;
+ P.CurParsedObjCImpl = nullptr;
assert(LateParsedObjCMethods.empty());
}
@@ -1656,13 +1658,13 @@
ConsumeToken(); // consume compatibility_alias
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected) << tok::identifier;
- return 0;
+ return nullptr;
}
IdentifierInfo *aliasId = Tok.getIdentifierInfo();
SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected) << tok::identifier;
- return 0;
+ return nullptr;
}
IdentifierInfo *classId = Tok.getIdentifierInfo();
SourceLocation classLoc = ConsumeToken(); // consume class-name;
@@ -1691,16 +1693,16 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_synthesized_property_name);
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
-
- IdentifierInfo *propertyIvar = 0;
+
+ IdentifierInfo *propertyIvar = nullptr;
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
SourceLocation propertyIvarLoc;
@@ -1709,7 +1711,7 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
@@ -1726,7 +1728,7 @@
ConsumeToken(); // consume ','
}
ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");
- return 0;
+ return nullptr;
}
/// property-dynamic:
@@ -1744,26 +1746,26 @@
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false,
- propertyId, 0, SourceLocation());
+ propertyId, nullptr, SourceLocation());
if (Tok.isNot(tok::comma))
break;
ConsumeToken(); // consume ','
}
ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");
- return 0;
+ return nullptr;
}
/// objc-throw-statement:
@@ -1874,7 +1876,7 @@
SourceLocation AtCatchFinallyLoc = ConsumeToken();
if (Tok.isObjCAtKeyword(tok::objc_catch)) {
- Decl *FirstPart = 0;
+ Decl *FirstPart = nullptr;
ConsumeToken(); // consume catch
if (Tok.is(tok::l_paren)) {
ConsumeParen();
@@ -2033,13 +2035,13 @@
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
- return 0;
+ return nullptr;
}
if (!MDecl) {
ConsumeBrace();
SkipUntil(tok::r_brace);
- return 0;
+ return nullptr;
}
// Allow the rest of sema to find private method decl implementations.
@@ -2097,7 +2099,7 @@
SourceLocation OpLoc = ConsumeToken();
if (!Tok.is(tok::numeric_constant)) {
- const char *Symbol = 0;
+ const char *Symbol = nullptr;
switch (Kind) {
case tok::minus: Symbol = "-"; break;
case tok::plus: Symbol = "+"; break;
@@ -2152,7 +2154,7 @@
return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));
default:
- if (Tok.getIdentifierInfo() == 0)
+ if (Tok.getIdentifierInfo() == nullptr)
return ExprError(Diag(AtLoc, diag::err_unexpected_at));
switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
@@ -2163,13 +2165,13 @@
case tok::objc_selector:
return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
default: {
- const char *str = 0;
+ const char *str = nullptr;
if (GetLookAheadToken(1).is(tok::l_brace)) {
char ch = Tok.getIdentifierInfo()->getNameStart()[0];
str =
ch == 't' ? "try"
: (ch == 'f' ? "finally"
- : (ch == 'a' ? "autoreleasepool" : 0));
+ : (ch == 'a' ? "autoreleasepool" : nullptr));
}
if (str) {
SourceLocation kwLoc = Tok.getLocation();
@@ -2342,11 +2344,11 @@
if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
- ParsedType(), 0);
+ ParsedType(), nullptr);
// Parse the receiver, which is either a type or an expression.
bool IsExpr;
- void *TypeOrExpr = NULL;
+ void *TypeOrExpr = nullptr;
if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
SkipUntil(tok::r_square, StopAtSemi);
return ExprError();
@@ -2359,7 +2361,7 @@
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
ParsedType::getFromOpaquePtr(TypeOrExpr),
- 0);
+ nullptr);
}
if (Tok.is(tok::identifier)) {
@@ -2372,7 +2374,7 @@
ReceiverType)) {
case Sema::ObjCSuperMessage:
return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
- ParsedType(), 0);
+ ParsedType(), nullptr);
case Sema::ObjCClassMessage:
if (!ReceiverType) {
@@ -2383,8 +2385,8 @@
ConsumeToken(); // the type name
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
- ReceiverType, 0);
-
+ ReceiverType, nullptr);
+
case Sema::ObjCInstanceMessage:
// Fall through to parse an expression.
break;
@@ -2867,7 +2869,7 @@
while (1) {
if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.
++nColons;
- KeyIdents.push_back(0);
+ KeyIdents.push_back(nullptr);
} else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.
return ExprError();
++nColons;
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index f1b6107..5916098 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -11,8 +11,9 @@
///
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTConsumer.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
@@ -62,7 +63,6 @@
case OMPD_parallel:
case OMPD_simd:
case OMPD_task:
- case NUM_OPENMP_DIRECTIVES:
Diag(Tok, diag::err_omp_unexpected_directive)
<< getOpenMPDirectiveName(DKind);
break;
@@ -85,8 +85,8 @@
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<Expr *, 5> Identifiers;
SmallVector<OMPClause *, 5> Clauses;
- SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES>
- FirstClauses(NUM_OPENMP_CLAUSES);
+ SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
+ FirstClauses(OMPC_unknown + 1);
const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
Scope::OpenMPDirectiveScope;
SourceLocation Loc = ConsumeToken(), EndLoc;
@@ -148,7 +148,7 @@
{
// The body is a block scope like in Lambdas and Blocks.
Sema::CompoundScopeRAII CompoundScope(Actions);
- Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1);
+ Actions.ActOnOpenMPRegionStart(DKind, Loc, getCurScope());
Actions.ActOnStartOfCompoundStmt();
// Parse statement
AssociatedStmt = ParseStatement();
@@ -176,7 +176,6 @@
SkipUntil(tok::annot_pragma_openmp_end);
break;
case OMPD_task:
- case NUM_OPENMP_DIRECTIVES:
Diag(Tok, diag::err_omp_unexpected_directive)
<< getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end);
@@ -258,11 +257,12 @@
///
/// clause:
/// if-clause | num_threads-clause | safelen-clause | default-clause |
-/// private-clause | firstprivate-clause | shared-clause
+/// private-clause | firstprivate-clause | shared-clause | linear-clause |
+/// collapse-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
- OMPClause *Clause = 0;
+ OMPClause *Clause = nullptr;
bool ErrorFound = false;
// Check if clause is allowed for the given directive.
if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
@@ -275,11 +275,13 @@
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_collapse:
// OpenMP [2.5, Restrictions]
// At most one if clause can appear on the directive.
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
- // Only one safelen clause can appear on a simd directive.
+ // Only one safelen clause can appear on a simd directive.
+ // Only one collapse clause can appear on a simd directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
@@ -288,9 +290,12 @@
Clause = ParseOpenMPSingleExprClause(CKind);
break;
case OMPC_default:
+ case OMPC_proc_bind:
// OpenMP [2.14.3.1, Restrictions]
// Only a single default clause may be specified on a parallel, task or
// teams directive.
+ // OpenMP [2.5, parallel Construct, Restrictions]
+ // At most one proc_bind clause can appear on the directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
@@ -301,6 +306,7 @@
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_linear:
case OMPC_copyin:
Clause = ParseOpenMPVarListClause(CKind);
break;
@@ -310,13 +316,12 @@
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
case OMPC_threadprivate:
- case NUM_OPENMP_CLAUSES:
Diag(Tok, diag::err_omp_unexpected_clause)
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
}
- return ErrorFound ? 0 : Clause;
+ return ErrorFound ? nullptr : Clause;
}
/// \brief Parsing of OpenMP clauses with single expressions like 'if',
@@ -332,13 +337,16 @@
/// safelen-clause:
/// 'safelen' '(' expression ')'
///
+/// collapse-clause:
+/// 'collapse' '(' expression ')'
+///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
getOpenMPClauseName(Kind)))
- return 0;
+ return nullptr;
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
@@ -347,18 +355,21 @@
T.consumeClose();
if (Val.isInvalid())
- return 0;
+ return nullptr;
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.take(), Loc,
T.getOpenLocation(),
T.getCloseLocation());
}
-/// \brief Parsing of simple OpenMP clauses like 'default'.
+/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause:
/// 'default' '(' 'none' | 'shared' ')
///
+/// proc_bind-clause:
+/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
+///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
@@ -366,11 +377,11 @@
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
getOpenMPClauseName(Kind)))
- return 0;
+ return nullptr;
- unsigned Type = Tok.isAnnotation() ?
- unsigned(OMPC_DEFAULT_unknown) :
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
+ unsigned Type =
+ getOpenMPSimpleClauseType(Kind,
+ Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
SourceLocation TypeLoc = Tok.getLocation();
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))
@@ -392,20 +403,25 @@
/// 'firstprivate' '(' list ')'
/// shared-clause:
/// 'shared' '(' list ')'
+/// linear-clause:
+/// 'linear' '(' list [ ':' linear-step ] ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
+ SourceLocation ColonLoc = SourceLocation();
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
getOpenMPClauseName(Kind)))
- return 0;
+ return nullptr;
SmallVector<Expr *, 5> Vars;
bool IsComma = true;
- while (IsComma || (Tok.isNot(tok::r_paren) &&
+ const bool MayHaveTail = (Kind == OMPC_linear);
+ while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
+ ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
// Parse variable
ExprResult VarExpr = ParseAssignmentExpression();
if (VarExpr.isUsable()) {
@@ -416,21 +432,34 @@
}
// Skip ',' if any
IsComma = Tok.is(tok::comma);
- if (IsComma) {
+ if (IsComma)
ConsumeToken();
- } else if (Tok.isNot(tok::r_paren) &&
- Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::err_omp_expected_punc)
- << getOpenMPClauseName(Kind);
- }
+ else if (Tok.isNot(tok::r_paren) &&
+ Tok.isNot(tok::annot_pragma_openmp_end) &&
+ (!MayHaveTail || Tok.isNot(tok::colon)))
+ Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind);
+ }
+
+ // Parse ':' linear-step
+ Expr *TailExpr = nullptr;
+ const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
+ if (MustHaveTail) {
+ ColonLoc = Tok.getLocation();
+ ConsumeToken();
+ ExprResult Tail = ParseAssignmentExpression();
+ if (Tail.isUsable())
+ TailExpr = Tail.take();
+ else
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
}
// Parse ')'.
T.consumeClose();
- if (Vars.empty())
- return 0;
+ if (Vars.empty() || (MustHaveTail && !TailExpr))
+ return nullptr;
- return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
- Tok.getLocation());
+ return Actions.ActOnOpenMPVarListClause(Kind, Vars, TailExpr, Loc, LOpen,
+ ColonLoc, Tok.getLocation());
}
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 29e1771..787d3f0 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "RAIIObjectsForParser.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
@@ -124,6 +125,22 @@
Token &FirstToken) override;
};
+struct PragmaMSPragma : public PragmaHandler {
+ explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
+struct PragmaOptimizeHandler : public PragmaHandler {
+ PragmaOptimizeHandler(Sema &S)
+ : PragmaHandler("optimize"), Actions(S) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
} // end namespace
void Parser::initializePragmaHandlers() {
@@ -175,7 +192,22 @@
PP.AddPragmaHandler(MSPointersToMembers.get());
MSVtorDisp.reset(new PragmaMSVtorDisp());
PP.AddPragmaHandler(MSVtorDisp.get());
+ MSInitSeg.reset(new PragmaMSPragma("init_seg"));
+ PP.AddPragmaHandler(MSInitSeg.get());
+ MSDataSeg.reset(new PragmaMSPragma("data_seg"));
+ PP.AddPragmaHandler(MSDataSeg.get());
+ MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
+ PP.AddPragmaHandler(MSBSSSeg.get());
+ MSConstSeg.reset(new PragmaMSPragma("const_seg"));
+ PP.AddPragmaHandler(MSConstSeg.get());
+ MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
+ PP.AddPragmaHandler(MSCodeSeg.get());
+ MSSection.reset(new PragmaMSPragma("section"));
+ PP.AddPragmaHandler(MSSection.get());
}
+
+ OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
+ PP.AddPragmaHandler("clang", OptimizeHandler.get());
}
void Parser::resetPragmaHandlers() {
@@ -214,10 +246,25 @@
MSPointersToMembers.reset();
PP.RemovePragmaHandler(MSVtorDisp.get());
MSVtorDisp.reset();
+ PP.RemovePragmaHandler(MSInitSeg.get());
+ MSInitSeg.reset();
+ PP.RemovePragmaHandler(MSDataSeg.get());
+ MSDataSeg.reset();
+ PP.RemovePragmaHandler(MSBSSSeg.get());
+ MSBSSSeg.reset();
+ PP.RemovePragmaHandler(MSConstSeg.get());
+ MSConstSeg.reset();
+ PP.RemovePragmaHandler(MSCodeSeg.get());
+ MSCodeSeg.reset();
+ PP.RemovePragmaHandler(MSSection.get());
+ MSSection.reset();
}
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
FPContractHandler.reset();
+
+ PP.RemovePragmaHandler("clang", OptimizeHandler.get());
+ OptimizeHandler.reset();
}
/// \brief Handle the annotation token produced for #pragma unused(...)
@@ -400,6 +447,145 @@
Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
}
+void Parser::HandlePragmaMSPragma() {
+ assert(Tok.is(tok::annot_pragma_ms_pragma));
+ // Grab the tokens out of the annotation and enter them into the stream.
+ auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
+ PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
+ SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
+ assert(Tok.isAnyIdentifier());
+ llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName();
+ PP.Lex(Tok); // pragma kind
+ // Figure out which #pragma we're dealing with. The switch has no default
+ // because lex shouldn't emit the annotation token for unrecognized pragmas.
+ typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation);
+ PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
+ .Case("data_seg", &Parser::HandlePragmaMSSegment)
+ .Case("bss_seg", &Parser::HandlePragmaMSSegment)
+ .Case("const_seg", &Parser::HandlePragmaMSSegment)
+ .Case("code_seg", &Parser::HandlePragmaMSSegment)
+ .Case("section", &Parser::HandlePragmaMSSection)
+ .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
+ if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) {
+ PP.Diag(PragmaLocation, DiagID) << PragmaName;
+ while (Tok.isNot(tok::eof))
+ PP.Lex(Tok);
+ PP.Lex(Tok);
+ }
+}
+
+unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ if (Tok.isNot(tok::l_paren))
+ return diag::warn_pragma_expected_lparen;
+ PP.Lex(Tok); // (
+ // Parsing code for pragma section
+ if (Tok.isNot(tok::string_literal))
+ return diag::warn_pragma_expected_section_name;
+ StringLiteral *SegmentName =
+ cast<StringLiteral>(ParseStringLiteralExpression().get());
+ int SectionFlags = 0;
+ while (Tok.is(tok::comma)) {
+ PP.Lex(Tok); // ,
+ if (!Tok.isAnyIdentifier())
+ return diag::warn_pragma_expected_action_or_r_paren;
+ Sema::PragmaSectionFlag Flag =
+ llvm::StringSwitch<Sema::PragmaSectionFlag>(
+ Tok.getIdentifierInfo()->getName())
+ .Case("read", Sema::PSF_Read)
+ .Case("write", Sema::PSF_Write)
+ .Case("execute", Sema::PSF_Execute)
+ .Case("shared", Sema::PSF_Invalid)
+ .Case("nopage", Sema::PSF_Invalid)
+ .Case("nocache", Sema::PSF_Invalid)
+ .Case("discard", Sema::PSF_Invalid)
+ .Case("remove", Sema::PSF_Invalid)
+ .Default(Sema::PSF_None);
+ if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
+ PP.Diag(PragmaLocation, Flag == Sema::PSF_None ?
+ diag::warn_pragma_invalid_specific_action :
+ diag::warn_pragma_unsupported_action)
+ << PragmaName << Tok.getIdentifierInfo()->getName();
+ while (Tok.isNot(tok::eof))
+ PP.Lex(Tok);
+ PP.Lex(Tok);
+ return 0;
+ }
+ SectionFlags |= Flag;
+ PP.Lex(Tok); // Identifier
+ }
+ if (Tok.isNot(tok::r_paren))
+ return diag::warn_pragma_expected_rparen;
+ PP.Lex(Tok); // )
+ if (Tok.isNot(tok::eof))
+ return diag::warn_pragma_extra_tokens_at_eol;
+ PP.Lex(Tok); // eof
+ Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
+ return 0;
+}
+
+unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ if (Tok.isNot(tok::l_paren))
+ return diag::warn_pragma_expected_lparen;
+ PP.Lex(Tok); // (
+ Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
+ llvm::StringRef SlotLabel;
+ if (Tok.isAnyIdentifier()) {
+ llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName();
+ if (PushPop == "push")
+ Action = Sema::PSK_Push;
+ else if (PushPop == "pop")
+ Action = Sema::PSK_Pop;
+ else
+ return diag::warn_pragma_expected_section_push_pop_or_name;
+ if (Action != Sema::PSK_Reset) {
+ PP.Lex(Tok); // push | pop
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok); // ,
+ // If we've got a comma, we either need a label or a string.
+ if (Tok.isAnyIdentifier()) {
+ SlotLabel = Tok.getIdentifierInfo()->getName();
+ PP.Lex(Tok); // identifier
+ if (Tok.is(tok::comma))
+ PP.Lex(Tok);
+ else if (Tok.isNot(tok::r_paren))
+ return diag::warn_pragma_expected_punc;
+ }
+ } else if (Tok.isNot(tok::r_paren))
+ return diag::warn_pragma_expected_punc;
+ }
+ }
+ // Grab the string literal for our section name.
+ StringLiteral *SegmentName = nullptr;
+ if (Tok.isNot(tok::r_paren)) {
+ if (Tok.isNot(tok::string_literal))
+ return Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
+ diag::warn_pragma_expected_section_name :
+ diag::warn_pragma_expected_section_label_or_name :
+ diag::warn_pragma_expected_section_push_pop_or_name;
+ SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get());
+ // Setting section "" has no effect
+ if (SegmentName->getLength())
+ Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
+ }
+ if (Tok.isNot(tok::r_paren))
+ return diag::warn_pragma_expected_rparen;
+ PP.Lex(Tok); // )
+ if (Tok.isNot(tok::eof))
+ return diag::warn_pragma_extra_tokens_at_eol;
+ PP.Lex(Tok); // eof
+ Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
+ SegmentName, PragmaName);
+ return 0;
+}
+
+unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ return PP.getDiagnostics().getCustomDiagID(
+ DiagnosticsEngine::Error, "'#pragma %0' not implemented.");
+}
+
// #pragma GCC visibility comes in two variants:
// 'push' '(' [visibility] ')'
// 'pop'
@@ -415,7 +601,7 @@
const IdentifierInfo *VisType;
if (PushPop && PushPop->isStr("pop")) {
- VisType = 0;
+ VisType = nullptr;
} else if (PushPop && PushPop->isStr("push")) {
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::l_paren)) {
@@ -475,7 +661,7 @@
}
Sema::PragmaPackKind Kind = Sema::PPK_Default;
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
Token Alignment;
Alignment.startToken();
SourceLocation LParenLoc = Tok.getLocation();
@@ -1063,7 +1249,7 @@
} else if (Tok.is(tok::r_paren)) {
// #pragma pointers_to_members(full_generality) implicitly specifies
// virtual_inheritance.
- Arg = 0;
+ Arg = nullptr;
RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
} else {
PP.Diag(Tok.getLocation(), diag::err_expected_punc)
@@ -1204,6 +1390,33 @@
PP.EnterToken(AnnotTok);
}
+/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
+/// an annotation token.
+void PragmaMSPragma::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ Token EoF, AnnotTok;
+ EoF.startToken();
+ EoF.setKind(tok::eof);
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_pragma);
+ AnnotTok.setLocation(Tok.getLocation());
+ SmallVector<Token, 8> TokenVector;
+ // Suck up all of the tokens before the eod.
+ for (; Tok.isNot(tok::eod); PP.Lex(Tok))
+ TokenVector.push_back(Tok);
+ // Add a sentinal EoF token to the end of the list.
+ TokenVector.push_back(EoF);
+ // We must allocate this array with new because EnterTokenStream is going to
+ // delete it later.
+ Token *TokenArray = new Token[TokenVector.size()];
+ std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
+ auto Value = new (PP.getPreprocessorAllocator())
+ std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
+ AnnotTok.setAnnotationValue(Value);
+ PP.EnterToken(AnnotTok);
+}
+
/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
///
/// The syntax is:
@@ -1334,3 +1547,40 @@
Actions.ActOnPragmaMSComment(Kind, ArgumentString);
}
+
+// #pragma clang optimize off
+// #pragma clang optimize on
+void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &FirstToken) {
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.is(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_missing_argument);
+ return;
+ }
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ // The only accepted values are 'on' or 'off'.
+ bool IsOn = false;
+ if (II->isStr("on")) {
+ IsOn = true;
+ } else if (!II->isStr("off")) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+
+ Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
+}
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 7254eb3..9d44f51 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -26,12 +26,15 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -112,7 +115,7 @@
ParenBraceBracketBalancer BalancerRAIIObj(*this);
ParsedAttributesWithRange Attrs(AttrFactory);
- MaybeParseCXX11Attributes(Attrs, 0, /*MightBeObjCMessageSend*/ true);
+ MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true);
StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts,
OnlyStatement, TrailingElseLoc, Attrs);
@@ -162,7 +165,7 @@
Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
bool OnlyStatement, SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs) {
- const char *SemiError = 0;
+ const char *SemiError = nullptr;
StmtResult Res;
// Cases in this switch statement should fall through if the parser expects
@@ -350,6 +353,10 @@
HandlePragmaMSPointersToMembers();
return StmtEmpty();
+ case tok::annot_pragma_ms_pragma:
+ ProhibitAttributes(Attrs);
+ HandlePragmaMSPragma();
+ return StmtEmpty();
}
// If we reached this code, the statement must end in a semicolon.
@@ -541,7 +548,7 @@
// can't handle GNU attributes), so only call it in the one case where
// GNU attributes are allowed.
SubStmt = ParseStatementOrDeclarationAfterAttributes(
- Stmts, /*OnlyStmts*/ true, 0, TempAttrs);
+ Stmts, /*OnlyStmts*/ true, nullptr, TempAttrs);
if (!TempAttrs.empty() && !SubStmt.isInvalid())
SubStmt = Actions.ProcessStmtAttributes(
SubStmt.get(), TempAttrs.getList(), TempAttrs.Range);
@@ -598,13 +605,14 @@
// DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
// gets updated each time a new case is parsed, and whose body is unset so
// far. When parsing 'case 4', this is the 'case 3' node.
- Stmt *DeepestParsedCaseStmt = 0;
+ Stmt *DeepestParsedCaseStmt = nullptr;
// While we have case statements, eat and stack them.
SourceLocation ColonLoc;
do {
SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() :
ConsumeToken(); // eat the 'case'.
+ ColonLoc = SourceLocation();
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCase(getCurScope());
@@ -617,11 +625,21 @@
/// expression.
ColonProtectionRAIIObject ColonProtection(*this);
- ExprResult LHS(MissingCase ? Expr : ParseConstantExpression());
- MissingCase = false;
- if (LHS.isInvalid()) {
- SkipUntil(tok::colon, StopAtSemi);
- return StmtError();
+ ExprResult LHS;
+ if (!MissingCase) {
+ LHS = ParseConstantExpression();
+ if (LHS.isInvalid()) {
+ // If constant-expression is parsed unsuccessfully, recover by skipping
+ // current case statement (moving to the colon that ends it).
+ if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) {
+ TryConsumeToken(tok::colon, ColonLoc);
+ continue;
+ }
+ return StmtError();
+ }
+ } else {
+ LHS = Expr;
+ MissingCase = false;
}
// GNU case range extension.
@@ -631,7 +649,10 @@
Diag(DotDotDotLoc, diag::ext_gnu_case_range);
RHS = ParseConstantExpression();
if (RHS.isInvalid()) {
- SkipUntil(tok::colon, StopAtSemi);
+ if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) {
+ TryConsumeToken(tok::colon, ColonLoc);
+ continue;
+ }
return StmtError();
}
}
@@ -639,8 +660,9 @@
ColonProtection.restore();
if (TryConsumeToken(tok::colon, ColonLoc)) {
- } else if (TryConsumeToken(tok::semi, ColonLoc)) {
- // Treat "case blah;" as a typo for "case blah:".
+ } else if (TryConsumeToken(tok::semi, ColonLoc) ||
+ TryConsumeToken(tok::coloncolon, ColonLoc)) {
+ // Treat "case blah;" or "case blah::" as a typo for "case blah:".
Diag(ColonLoc, diag::err_expected_after)
<< "'case'" << tok::colon
<< FixItHint::CreateReplacement(ColonLoc, ":");
@@ -676,8 +698,6 @@
// Handle all case statements.
} while (Tok.is(tok::kw_case));
- assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
-
// If we found a non-case statement, start by parsing it.
StmtResult SubStmt;
@@ -685,19 +705,23 @@
SubStmt = ParseStatement();
} else {
// Nicely diagnose the common error "switch (X) { case 4: }", which is
- // not valid.
- SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
- Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
- << FixItHint::CreateInsertion(AfterColonLoc, " ;");
- SubStmt = true;
+ // not valid. If ColonLoc doesn't point to a valid text location, there was
+ // another parsing error, so avoid producing extra diagnostics.
+ if (ColonLoc.isValid()) {
+ SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
+ Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
+ << FixItHint::CreateInsertion(AfterColonLoc, " ;");
+ }
+ SubStmt = StmtError();
}
- // Broken sub-stmt shouldn't prevent forming the case statement properly.
- if (SubStmt.isInvalid())
- SubStmt = Actions.ActOnNullStmt(SourceLocation());
-
// Install the body into the most deeply-nested case.
- Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
+ if (DeepestParsedCaseStmt) {
+ // Broken sub-stmt shouldn't prevent forming the case statement properly.
+ if (SubStmt.isInvalid())
+ SubStmt = Actions.ActOnNullStmt(SourceLocation());
+ Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
+ }
// Return the top level parsed statement tree.
return TopLevelCase;
@@ -828,6 +852,9 @@
case tok::annot_pragma_ms_pointers_to_members:
HandlePragmaMSPointersToMembers();
break;
+ case tok::annot_pragma_ms_pragma:
+ HandlePragmaMSPragma();
+ break;
default:
checkForPragmas = false;
break;
@@ -916,7 +943,8 @@
ConsumeToken();
ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs, 0, /*MightBeObjCMessageSend*/ true);
+ MaybeParseCXX11Attributes(attrs, nullptr,
+ /*MightBeObjCMessageSend*/ true);
// If this is the start of a declaration, parse it as such.
if (isDeclarationStatement()) {
@@ -984,7 +1012,7 @@
ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean);
else {
ExprResult = ParseExpression();
- DeclResult = 0;
+ DeclResult = nullptr;
// If required, convert to a boolean value.
if (!ExprResult.isInvalid() && ConvertToBoolean)
@@ -1054,7 +1082,7 @@
// Parse the condition.
ExprResult CondExp;
- Decl *CondVar = 0;
+ Decl *CondVar = nullptr;
if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))
return StmtError();
@@ -1130,8 +1158,8 @@
// make turn the invalid one into a null stmt to avoid dropping the other
// part. If both are invalid, return error.
if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
- (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
- (ThenStmt.get() == 0 && ElseStmt.isInvalid())) {
+ (ThenStmt.isInvalid() && ElseStmt.get() == nullptr) ||
+ (ThenStmt.get() == nullptr && ElseStmt.isInvalid())) {
// Both invalid, or one is invalid and other is non-present: return error.
return StmtError();
}
@@ -1181,7 +1209,7 @@
// Parse the condition.
ExprResult Cond;
- Decl *CondVar = 0;
+ Decl *CondVar = nullptr;
if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false))
return StmtError();
@@ -1222,15 +1250,6 @@
InnerScope.Exit();
SwitchScope.Exit();
- if (Body.isInvalid()) {
- // FIXME: Remove the case statement list from the Switch statement.
-
- // Put the synthesized null statement on the same line as the end of switch
- // condition.
- SourceLocation SynthesizedNullStmtLocation = Cond.get()->getLocEnd();
- Body = Actions.ActOnNullStmt(SynthesizedNullStmtLocation);
- }
-
return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
}
@@ -1273,7 +1292,7 @@
// Parse the condition.
ExprResult Cond;
- Decl *CondVar = 0;
+ Decl *CondVar = nullptr;
if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true))
return StmtError();
@@ -1439,7 +1458,7 @@
ExprResult Collection;
ForRangeInit ForRangeInit;
FullExprArg ThirdPart(Actions);
- Decl *SecondVar = 0;
+ Decl *SecondVar = nullptr;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(),
@@ -1468,12 +1487,10 @@
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
StmtVector Stmts;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext,
- DeclEnd, attrs, false,
- MightBeForRangeStmt ?
- &ForRangeInit : 0);
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(
+ Stmts, Declarator::ForContext, DeclEnd, attrs, false,
+ MightBeForRangeStmt ? &ForRangeInit : nullptr);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
-
if (ForRangeInit.ParsedForRangeDecl()) {
Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_for_range : diag::ext_for_range);
@@ -1739,7 +1756,7 @@
return StmtError();
}
}
- return Actions.ActOnReturnStmt(ReturnLoc, R.take());
+ return Actions.ActOnReturnStmt(ReturnLoc, R.take(), getCurScope());
}
namespace {
@@ -1769,7 +1786,7 @@
bool IsUnevaluatedContext) override {
// Collect the desired tokens.
SmallVector<Token, 16> LineToks;
- const Token *FirstOrigToken = 0;
+ const Token *FirstOrigToken = nullptr;
findTokensForString(LineBuf, LineToks, FirstOrigToken);
unsigned NumConsumedToks;
@@ -2137,7 +2154,7 @@
const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple();
llvm::Triple::ArchType ArchTy = TheTriple.getArch();
const std::string &TT = TheTriple.getTriple();
- const llvm::Target *TheTarget = 0;
+ const llvm::Target *TheTarget = nullptr;
bool UnsupportedArch = (ArchTy != llvm::Triple::x86 &&
ArchTy != llvm::Triple::x86_64);
if (UnsupportedArch) {
@@ -2166,7 +2183,7 @@
std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
// Get the instruction descriptor.
- const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
+ std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
std::unique_ptr<llvm::MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TT, "", ""));
@@ -2182,11 +2199,14 @@
std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
std::unique_ptr<llvm::MCAsmParser> Parser(
createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
- std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
- TheTarget->createMCAsmParser(*STI, *Parser, *MII));
- llvm::MCInstPrinter *IP =
- TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
+ // FIXME: init MCOptions from sanitizer flags here.
+ llvm::MCTargetOptions MCOptions;
+ std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
+ TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
+
+ std::unique_ptr<llvm::MCInstPrinter> IP(
+ TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI));
// Change to the Intel dialect.
Parser->setAssemblerDialect(1);
@@ -2208,7 +2228,7 @@
SmallVector<std::string, 4> Clobbers;
if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR,
NumOutputs, NumInputs, OpExprs, Constraints,
- Clobbers, MII, IP, Callback))
+ Clobbers, MII.get(), IP.get(), Callback))
return StmtError();
// Filter out "fpsw". Clang doesn't accept it, and it always lists flags and
@@ -2313,7 +2333,7 @@
// We have a simple asm expression like 'asm("foo")'.
T.consumeClose();
return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
- /*NumOutputs*/ 0, /*NumInputs*/ 0, 0,
+ /*NumOutputs*/ 0, /*NumInputs*/ 0, nullptr,
Constraints, Exprs, AsmString.take(),
Clobbers, T.getCloseLocation());
}
@@ -2420,7 +2440,7 @@
Names.push_back(II);
T.consumeClose();
} else
- Names.push_back(0);
+ Names.push_back(nullptr);
ExprResult Constraint(ParseAsmStringLiteral());
if (Constraint.isInvalid()) {
@@ -2652,7 +2672,7 @@
// exception-declaration is equivalent to '...' or a parameter-declaration
// without default arguments.
- Decl *ExceptionDecl = 0;
+ Decl *ExceptionDecl = nullptr;
if (Tok.isNot(tok::ellipsis)) {
ParsedAttributesWithRange Attributes(AttrFactory);
MaybeParseCXX11Attributes(Attributes);
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 777fd01..d8fbe0c 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -107,7 +107,7 @@
SourceLocation TemplateLoc;
if (!TryConsumeToken(tok::kw_template, TemplateLoc)) {
Diag(Tok.getLocation(), diag::err_expected_template);
- return 0;
+ return nullptr;
}
// Parse the '<' template-parameter-list '>'
@@ -118,7 +118,7 @@
// Skip until the semi-colon or a }.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
TryConsumeToken(tok::semi);
- return 0;
+ return nullptr;
}
ParamLists.push_back(
@@ -170,7 +170,7 @@
// We are parsing a member template.
ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
&DiagsFromTParams);
- return 0;
+ return nullptr;
}
ParsedAttributesWithRange prefixAttrs(AttrFactory);
@@ -214,7 +214,7 @@
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
- return 0;
+ return nullptr;
}
LateParsedAttrList LateParsedAttrs(true);
@@ -250,8 +250,8 @@
// Recover as if it were an explicit specialization.
TemplateParameterLists FakedParamLists;
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
- LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
+ 0, LAngleLoc));
return ParseFunctionDefinition(
DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists,
@@ -485,7 +485,7 @@
// Grab the template parameter name (if given)
SourceLocation NameLoc;
- IdentifierInfo* ParamName = 0;
+ IdentifierInfo *ParamName = nullptr;
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
@@ -495,7 +495,7 @@
// don't consume this token.
} else {
Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
- return 0;
+ return nullptr;
}
// Grab a default argument (if available).
@@ -504,7 +504,7 @@
SourceLocation EqualLoc;
ParsedType DefaultArg;
if (TryConsumeToken(tok::equal, EqualLoc))
- DefaultArg = ParseTypeName(/*Range=*/0,
+ DefaultArg = ParseTypeName(/*Range=*/nullptr,
Declarator::TemplateTypeArgContext).get();
return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis,
@@ -532,7 +532,7 @@
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
RAngleLoc)) {
- return 0;
+ return nullptr;
}
}
@@ -566,7 +566,7 @@
// Get the identifier, if given.
SourceLocation NameLoc;
- IdentifierInfo* ParamName = 0;
+ IdentifierInfo *ParamName = nullptr;
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
@@ -576,7 +576,7 @@
// don't consume this token.
} else {
Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
- return 0;
+ return nullptr;
}
TemplateParameterList *ParamList =
@@ -626,7 +626,7 @@
ParseDeclarator(ParamDecl);
if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
Diag(Tok.getLocation(), diag::err_expected_template_parameter);
- return 0;
+ return nullptr;
}
// If there is a default value, parse it.
@@ -919,7 +919,7 @@
TemplateId->Name = TemplateName.Identifier;
TemplateId->Operator = OO_None;
} else {
- TemplateId->Name = 0;
+ TemplateId->Name = nullptr;
TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
}
TemplateId->SS = SS;
@@ -1086,7 +1086,7 @@
// Therefore, we initially try to parse a type-id.
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
SourceLocation Loc = Tok.getLocation();
- TypeResult TypeArg = ParseTypeName(/*Range=*/0,
+ TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr,
Declarator::TemplateTypeArgContext);
if (TypeArg.isInvalid())
return ParsedTemplateArgument();
@@ -1144,7 +1144,7 @@
return true;
// See whether we have declaration specifiers, which indicate a type.
- while (isCXXDeclarationSpecifier() == TPResult::True())
+ while (isCXXDeclarationSpecifier() == TPResult::True)
ConsumeToken();
// If we have a '>' or a ',' then this is a template argument list.
@@ -1161,6 +1161,7 @@
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
// Template argument lists are constant-evaluation contexts.
EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated);
+ ColonProtectionRAIIObject ColonProtection(*this, false);
do {
ParsedTemplateArgument Arg = ParseTemplateArgument();
@@ -1238,7 +1239,7 @@
// Get the list of DeclContexts to reenter.
SmallVector<DeclContext*, 4> DeclContextsToReenter;
- DeclContext *DD = FunD->getLexicalParent();
+ DeclContext *DD = FunD;
while (DD && !DD->isTranslationUnit()) {
DeclContextsToReenter.push_back(DD);
DD = DD->getLexicalParent();
@@ -1248,37 +1249,16 @@
SmallVectorImpl<DeclContext *>::reverse_iterator II =
DeclContextsToReenter.rbegin();
for (; II != DeclContextsToReenter.rend(); ++II) {
- if (ClassTemplatePartialSpecializationDecl *MD =
- dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
- TemplateParamScopeStack.push_back(
- new ParseScope(this, Scope::TemplateParamScope));
- Actions.ActOnReenterTemplateScope(getCurScope(), MD);
- ++CurTemplateDepthTracker;
- } else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
- bool IsClassTemplate = MD->getDescribedClassTemplate() != 0;
- TemplateParamScopeStack.push_back(
- new ParseScope(this, Scope::TemplateParamScope,
- /*ManageScope*/IsClassTemplate));
- Actions.ActOnReenterTemplateScope(getCurScope(),
- MD->getDescribedClassTemplate());
- if (IsClassTemplate)
- ++CurTemplateDepthTracker;
+ TemplateParamScopeStack.push_back(new ParseScope(this,
+ Scope::TemplateParamScope));
+ unsigned NumParamLists =
+ Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II));
+ CurTemplateDepthTracker.addDepth(NumParamLists);
+ if (*II != FunD) {
+ TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
+ Actions.PushDeclContext(Actions.getCurScope(), *II);
}
- TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
- Actions.PushDeclContext(Actions.getCurScope(), *II);
}
- TemplateParamScopeStack.push_back(
- new ParseScope(this, Scope::TemplateParamScope));
-
- DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD);
- const unsigned DeclaratorNumTemplateParameterLists =
- (Declarator ? Declarator->getNumTemplateParameterLists() : 0);
- if (Declarator && DeclaratorNumTemplateParameterLists != 0) {
- Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
- CurTemplateDepthTracker.addDepth(DeclaratorNumTemplateParameterLists);
- }
- Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D);
- ++CurTemplateDepthTracker;
assert(!LPT.Toks.empty() && "Empty body!");
@@ -1313,13 +1293,13 @@
assert((!isa<FunctionTemplateDecl>(LPT.D) ||
cast<FunctionTemplateDecl>(LPT.D)
->getTemplateParameters()
- ->getDepth() < TemplateParameterDepth) &&
+ ->getDepth() == TemplateParameterDepth - 1) &&
"TemplateParameterDepth should be greater than the depth of "
"current template being instantiated!");
ParseFunctionStatementBody(LPT.D, FnScope);
Actions.UnmarkAsLateParsedTemplate(FunD);
} else
- Actions.ActOnFinishFunctionBody(LPT.D, 0);
+ Actions.ActOnFinishFunctionBody(LPT.D, nullptr);
}
// Exit scopes.
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 330e541..8514af2 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -101,15 +101,15 @@
// an ambiguity if the first decl-specifier is
// simple-type-specifier/typename-specifier followed by a '(', which may
// indicate a function-style cast expression.
- // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
+ // isCXXDeclarationSpecifier will return TPResult::Ambiguous only in such
// a case.
bool InvalidAsDeclaration = false;
- TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+ TPResult TPR = isCXXDeclarationSpecifier(TPResult::False,
&InvalidAsDeclaration);
- if (TPR != TPResult::Ambiguous())
- return TPR != TPResult::False(); // Returns true for TPResult::True() or
- // TPResult::Error().
+ if (TPR != TPResult::Ambiguous)
+ return TPR != TPResult::False; // Returns true for TPResult::True or
+ // TPResult::Error.
// FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
// and so gets some cases wrong. We can't carry on if we've already seen
@@ -131,15 +131,15 @@
PA.Revert();
// In case of an error, let the declaration parsing code handle it.
- if (TPR == TPResult::Error())
+ if (TPR == TPResult::Error)
return true;
// Declarations take precedence over expressions.
- if (TPR == TPResult::Ambiguous())
- TPR = TPResult::True();
+ if (TPR == TPResult::Ambiguous)
+ TPR = TPResult::True;
- assert(TPR == TPResult::True() || TPR == TPResult::False());
- return TPR == TPResult::True();
+ assert(TPR == TPResult::True || TPR == TPResult::False);
+ return TPR == TPResult::True;
}
/// Try to consume a token sequence that we've already identified as
@@ -157,10 +157,10 @@
case tok::kw___underlying_type: {
ConsumeToken();
if (Tok.isNot(tok::l_paren))
- return TPResult::Error();
+ return TPResult::Error;
ConsumeParen();
if (!SkipUntil(tok::r_paren))
- return TPResult::Error();
+ return TPResult::Error;
break;
}
@@ -184,23 +184,23 @@
if (Tok.is(tok::l_square)) {
ConsumeBracket();
if (!SkipUntil(tok::r_square))
- return TPResult::Error();
+ return TPResult::Error;
} else {
ConsumeToken();
if (Tok.isNot(tok::l_paren))
- return TPResult::Error();
+ return TPResult::Error;
ConsumeParen();
if (!SkipUntil(tok::r_paren))
- return TPResult::Error();
+ return TPResult::Error;
}
}
if (TryAnnotateCXXScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
if (Tok.is(tok::annot_cxxscope))
ConsumeToken();
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
- return TPResult::Error();
+ return TPResult::Error;
ConsumeToken();
break;
@@ -215,7 +215,7 @@
break;
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// simple-declaration:
@@ -227,29 +227,29 @@
/// attribute-specifier-seqopt type-specifier-seq declarator
///
Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
- if (TryConsumeDeclarationSpecifier() == TPResult::Error())
- return TPResult::Error();
+ if (TryConsumeDeclarationSpecifier() == TPResult::Error)
+ return TPResult::Error;
// Two decl-specifiers in a row conclusively disambiguate this as being a
// simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
// overwhelmingly common case that the next token is a '('.
if (Tok.isNot(tok::l_paren)) {
TPResult TPR = isCXXDeclarationSpecifier();
- if (TPR == TPResult::Ambiguous())
- return TPResult::True();
- if (TPR == TPResult::True() || TPR == TPResult::Error())
+ if (TPR == TPResult::Ambiguous)
+ return TPResult::True;
+ if (TPR == TPResult::True || TPR == TPResult::Error)
return TPR;
- assert(TPR == TPResult::False());
+ assert(TPR == TPResult::False);
}
TPResult TPR = TryParseInitDeclaratorList();
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
- return TPResult::False();
+ return TPResult::False;
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// Tentatively parse an init-declarator-list in order to disambiguate it from
@@ -283,23 +283,23 @@
while (1) {
// declarator
TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
// [GNU] simple-asm-expr[opt] attributes[opt]
if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
- return TPResult::True();
+ return TPResult::True;
// initializer[opt]
if (Tok.is(tok::l_paren)) {
// Parse through the parens.
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
} else if (Tok.is(tok::l_brace)) {
// A left-brace here is sufficient to disambiguate the parse; an
// expression can never be followed directly by a braced-init-list.
- return TPResult::True();
+ return TPResult::True;
} else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
// MSVC and g++ won't examine the rest of declarators if '=' is
// encountered; they just conclude that we have a declaration.
@@ -317,14 +317,14 @@
// in any other context 'in' is invalid after a declaration and parser
// issues the error regardless of outcome of this decision.
// FIXME: Change if above assumption does not hold.
- return TPResult::True();
+ return TPResult::True;
}
if (!TryConsumeToken(tok::comma))
break;
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// isCXXConditionDeclaration - Disambiguates between a declaration or an
@@ -342,9 +342,9 @@
///
bool Parser::isCXXConditionDeclaration() {
TPResult TPR = isCXXDeclarationSpecifier();
- if (TPR != TPResult::Ambiguous())
- return TPR != TPResult::False(); // Returns true for TPResult::True() or
- // TPResult::Error().
+ if (TPR != TPResult::Ambiguous)
+ return TPR != TPResult::False; // Returns true for TPResult::True or
+ // TPResult::Error.
// FIXME: Add statistics about the number of ambiguous statements encountered
// and how they were resolved (number of declarations+number of expressions).
@@ -362,25 +362,25 @@
TPR = TryParseDeclarator(false/*mayBeAbstract*/);
// In case of an error, let the declaration parsing code handle it.
- if (TPR == TPResult::Error())
- TPR = TPResult::True();
+ if (TPR == TPResult::Error)
+ TPR = TPResult::True;
- if (TPR == TPResult::Ambiguous()) {
+ if (TPR == TPResult::Ambiguous) {
// '='
// [GNU] simple-asm-expr[opt] attributes[opt]
if (Tok.is(tok::equal) ||
Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
- TPR = TPResult::True();
+ TPR = TPResult::True;
else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))
- TPR = TPResult::True();
+ TPR = TPResult::True;
else
- TPR = TPResult::False();
+ TPR = TPResult::False;
}
PA.Revert();
- assert(TPR == TPResult::True() || TPR == TPResult::False());
- return TPR == TPResult::True();
+ assert(TPR == TPResult::True || TPR == TPResult::False);
+ return TPR == TPResult::True;
}
/// \brief Determine whether the next set of tokens contains a type-id.
@@ -412,9 +412,9 @@
// in its syntactic context shall be considered a type-id.
TPResult TPR = isCXXDeclarationSpecifier();
- if (TPR != TPResult::Ambiguous())
- return TPR != TPResult::False(); // Returns true for TPResult::True() or
- // TPResult::Error().
+ if (TPR != TPResult::Ambiguous)
+ return TPR != TPResult::False; // Returns true for TPResult::True or
+ // TPResult::Error.
// FIXME: Add statistics about the number of ambiguous statements encountered
// and how they were resolved (number of declarations+number of expressions).
@@ -432,14 +432,14 @@
TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
// In case of an error, let the declaration parsing code handle it.
- if (TPR == TPResult::Error())
- TPR = TPResult::True();
+ if (TPR == TPResult::Error)
+ TPR = TPResult::True;
- if (TPR == TPResult::Ambiguous()) {
+ if (TPR == TPResult::Ambiguous) {
// We are supposed to be inside parens, so if after the abstract declarator
// we encounter a ')' this is a type-id, otherwise it's an expression.
if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
- TPR = TPResult::True();
+ TPR = TPResult::True;
isAmbiguous = true;
// We are supposed to be inside a template argument, so if after
@@ -448,17 +448,17 @@
} else if (Context == TypeIdAsTemplateArgument &&
(Tok.is(tok::greater) || Tok.is(tok::comma) ||
(getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) {
- TPR = TPResult::True();
+ TPR = TPResult::True;
isAmbiguous = true;
} else
- TPR = TPResult::False();
+ TPR = TPResult::False;
}
PA.Revert();
- assert(TPR == TPResult::True() || TPR == TPResult::False());
- return TPR == TPResult::True();
+ assert(TPR == TPResult::True || TPR == TPResult::False);
+ return TPR == TPResult::True;
}
/// \brief Returns true if this is a C++11 attribute-specifier. Per
@@ -624,7 +624,7 @@
while (true) {
if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
if (TryAnnotateCXXScopeToken(true))
- return TPResult::Error();
+ return TPResult::Error;
if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
Tok.is(tok::ampamp) ||
@@ -636,7 +636,7 @@
Tok.is(tok::kw_restrict))
ConsumeToken();
} else {
- return TPResult::True();
+ return TPResult::True;
}
}
}
@@ -671,20 +671,20 @@
ConsumeBracket();
ConsumeBracket();
}
- return TPResult::True();
+ return TPResult::True;
#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \
case tok::Token:
#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly)
#include "clang/Basic/OperatorKinds.def"
ConsumeToken();
- return TPResult::True();
+ return TPResult::True;
case tok::l_square:
if (NextToken().is(tok::r_square)) {
ConsumeBracket();
ConsumeBracket();
- return TPResult::True();
+ return TPResult::True;
}
break;
@@ -692,7 +692,7 @@
if (NextToken().is(tok::r_paren)) {
ConsumeParen();
ConsumeParen();
- return TPResult::True();
+ return TPResult::True;
}
break;
@@ -712,24 +712,24 @@
if (Tok.is(tok::identifier))
ConsumeToken();
else
- return TPResult::Error();
+ return TPResult::Error;
}
- return TPResult::True();
+ return TPResult::True;
}
// Maybe this is a conversion-function-id.
bool AnyDeclSpecifiers = false;
while (true) {
TPResult TPR = isCXXDeclarationSpecifier();
- if (TPR == TPResult::Error())
+ if (TPR == TPResult::Error)
return TPR;
- if (TPR == TPResult::False()) {
+ if (TPR == TPResult::False) {
if (!AnyDeclSpecifiers)
- return TPResult::Error();
+ return TPResult::Error;
break;
}
- if (TryConsumeDeclarationSpecifier() == TPResult::Error())
- return TPResult::Error();
+ if (TryConsumeDeclarationSpecifier() == TPResult::Error)
+ return TPResult::Error;
AnyDeclSpecifiers = true;
}
return TryParsePtrOperatorSeq();
@@ -793,8 +793,8 @@
// declarator:
// direct-declarator
// ptr-operator declarator
- if (TryParsePtrOperatorSeq() == TPResult::Error())
- return TPResult::Error();
+ if (TryParsePtrOperatorSeq() == TPResult::Error)
+ return TPResult::Error;
// direct-declarator:
// direct-abstract-declarator:
@@ -811,8 +811,8 @@
else if (Tok.is(tok::identifier))
TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
if (Tok.is(tok::kw_operator)) {
- if (TryParseOperatorId() == TPResult::Error())
- return TPResult::Error();
+ if (TryParseOperatorId() == TPResult::Error)
+ return TPResult::Error;
} else
ConsumeToken();
} else if (Tok.is(tok::l_paren)) {
@@ -825,7 +825,7 @@
// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
// exception-specification[opt]
TPResult TPR = TryParseFunctionDeclarator();
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
} else {
// '(' declarator ')'
@@ -838,20 +838,20 @@
Tok.is(tok::kw___fastcall) ||
Tok.is(tok::kw___thiscall) ||
Tok.is(tok::kw___unaligned))
- return TPResult::True(); // attributes indicate declaration
+ return TPResult::True; // attributes indicate declaration
TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
if (Tok.isNot(tok::r_paren))
- return TPResult::False();
+ return TPResult::False;
ConsumeParen();
}
} else if (!mayBeAbstract) {
- return TPResult::False();
+ return TPResult::False;
}
while (1) {
- TPResult TPR(TPResult::Ambiguous());
+ TPResult TPR(TPResult::Ambiguous);
// abstract-declarator: ...
if (Tok.is(tok::ellipsis))
@@ -877,11 +877,11 @@
break;
}
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
Parser::TPResult
@@ -936,13 +936,14 @@
case tok::kw___real:
case tok::kw___FUNCTION__:
case tok::kw___FUNCDNAME__:
+ case tok::kw___FUNCSIG__:
case tok::kw_L__FUNCTION__:
case tok::kw___PRETTY_FUNCTION__:
case tok::kw___uuidof:
#define TYPE_TRAIT(N,Spelling,K) \
case tok::kw_##Spelling:
#include "clang/Basic/TokenKinds.def"
- return TPResult::True();
+ return TPResult::True;
// Obviously starts a type-specifier-seq:
case tok::kw_char:
@@ -988,13 +989,13 @@
case tok::kw___pixel:
case tok::kw__Atomic:
case tok::kw___unknown_anytype:
- return TPResult::False();
+ return TPResult::False;
default:
break;
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
@@ -1003,16 +1004,16 @@
!= TentativelyDeclaredIdentifiers.end();
}
-/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
-/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
-/// be either a decl-specifier or a function-style cast, and TPResult::Error()
+/// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration
+/// specifier, TPResult::False if it is not, TPResult::Ambiguous if it could
+/// be either a decl-specifier or a function-style cast, and TPResult::Error
/// if a parsing error was found and reported.
///
/// If HasMissingTypename is provided, a name with a dependent scope specifier
/// will be treated as ambiguous if the 'typename' keyword is missing. If this
/// happens, *HasMissingTypename will be set to 'true'. This will also be used
/// as an indicator that undeclared identifiers (which will trigger a later
-/// parse error) should be treated as types. Returns TPResult::Ambiguous() in
+/// parse error) should be treated as types. Returns TPResult::Ambiguous in
/// such cases.
///
/// decl-specifier:
@@ -1116,12 +1117,12 @@
// Check for need to substitute AltiVec __vector keyword
// for "vector" identifier.
if (TryAltiVecVectorToken())
- return TPResult::True();
+ return TPResult::True;
const Token &Next = NextToken();
// In 'foo bar', 'foo' is always a type name outside of Objective-C.
if (!getLangOpts().ObjC1 && Next.is(tok::identifier))
- return TPResult::True();
+ return TPResult::True;
if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
// Determine whether this is a valid expression. If not, we will hit
@@ -1134,15 +1135,15 @@
switch (TryAnnotateName(false /* no nested name specifier */,
&TypoCorrection)) {
case ANK_Error:
- return TPResult::Error();
+ return TPResult::Error;
case ANK_TentativeDecl:
- return TPResult::False();
+ return TPResult::False;
case ANK_TemplateName:
// A bare type template-name which can't be a template template
// argument is an error, and was probably intended to be a type.
- return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
+ return GreaterThanIsOperator ? TPResult::True : TPResult::False;
case ANK_Unresolved:
- return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False();
+ return HasMissingTypename ? TPResult::Ambiguous : TPResult::False;
case ANK_Success:
break;
}
@@ -1154,12 +1155,12 @@
// since it will annotate as a primary expression, and we want to use the
// "missing 'typename'" logic.
if (TryAnnotateTypeOrScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
// If annotation failed, assume it's a non-type.
// FIXME: If this happens due to an undeclared identifier, treat it as
// ambiguous.
if (Tok.is(tok::identifier))
- return TPResult::False();
+ return TPResult::False;
}
// We annotated this token as something. Recurse to handle whatever we got.
@@ -1170,21 +1171,21 @@
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
case tok::coloncolon: { // ::foo::bar
const Token &Next = NextToken();
if (Next.is(tok::kw_new) || // ::new
Next.is(tok::kw_delete)) // ::delete
- return TPResult::False();
+ return TPResult::False;
}
// Fall through.
case tok::kw_decltype:
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
// decl-specifier:
@@ -1241,7 +1242,7 @@
case tok::kw_restrict:
case tok::kw__Complex:
case tok::kw___attribute:
- return TPResult::True();
+ return TPResult::True;
// Microsoft
case tok::kw___declspec:
@@ -1256,20 +1257,20 @@
case tok::kw___ptr32:
case tok::kw___forceinline:
case tok::kw___unaligned:
- return TPResult::True();
+ return TPResult::True;
// Borland
case tok::kw___pascal:
- return TPResult::True();
+ return TPResult::True;
// AltiVec
case tok::kw___vector:
- return TPResult::True();
+ return TPResult::True;
case tok::annot_template_id: {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (TemplateId->Kind != TNK_Type_template)
- return TPResult::False();
+ return TPResult::False;
CXXScopeSpec SS;
AnnotateTemplateIdTokenAsType();
assert(Tok.is(tok::annot_typename));
@@ -1279,7 +1280,7 @@
case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
// We've already annotated a scope; try to annotate a type.
if (TryAnnotateTypeOrScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
if (!Tok.is(tok::annot_typename)) {
// If the next token is an identifier or a type qualifier, then this
// can't possibly be a valid expression either.
@@ -1293,37 +1294,37 @@
ConsumeToken();
ConsumeToken();
bool isIdentifier = Tok.is(tok::identifier);
- TPResult TPR = TPResult::False();
+ TPResult TPR = TPResult::False;
if (!isIdentifier)
TPR = isCXXDeclarationSpecifier(BracedCastResult,
HasMissingTypename);
PA.Revert();
if (isIdentifier ||
- TPR == TPResult::True() || TPR == TPResult::Error())
- return TPResult::Error();
+ TPR == TPResult::True || TPR == TPResult::Error)
+ return TPResult::Error;
if (HasMissingTypename) {
// We can't tell whether this is a missing 'typename' or a valid
// expression.
*HasMissingTypename = true;
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
} else {
// Try to resolve the name. If it doesn't exist, assume it was
// intended to name a type and keep disambiguating.
switch (TryAnnotateName(false /* SS is not dependent */)) {
case ANK_Error:
- return TPResult::Error();
+ return TPResult::Error;
case ANK_TentativeDecl:
- return TPResult::False();
+ return TPResult::False;
case ANK_TemplateName:
// A bare type template-name which can't be a template template
// argument is an error, and was probably intended to be a type.
- return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
+ return GreaterThanIsOperator ? TPResult::True : TPResult::False;
case ANK_Unresolved:
- return HasMissingTypename ? TPResult::Ambiguous()
- : TPResult::False();
+ return HasMissingTypename ? TPResult::Ambiguous
+ : TPResult::False;
case ANK_Success:
// Annotated it, check again.
assert(Tok.isNot(tok::annot_cxxscope) ||
@@ -1333,7 +1334,7 @@
}
}
}
- return TPResult::False();
+ return TPResult::False;
}
// If that succeeded, fallthrough into the generic simple-type-id case.
@@ -1369,16 +1370,16 @@
PA.Revert();
- if (TPR == TPResult::Error())
- return TPResult::Error();
+ if (TPR == TPResult::Error)
+ return TPResult::Error;
if (isFollowedByParen)
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
return BracedCastResult;
- return TPResult::True();
+ return TPResult::True;
}
case tok::kw_char:
@@ -1399,7 +1400,7 @@
case tok::kw_void:
case tok::annot_decltype:
if (NextToken().is(tok::l_paren))
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
// This is a function-style cast in all cases we disambiguate other than
// one:
@@ -1411,14 +1412,14 @@
return BracedCastResult;
if (isStartOfObjCClassMessageMissingOpenBracket())
- return TPResult::False();
+ return TPResult::False;
- return TPResult::True();
+ return TPResult::True;
// GNU typeof support.
case tok::kw_typeof: {
if (NextToken().isNot(tok::l_paren))
- return TPResult::True();
+ return TPResult::True;
TentativeParsingAction PA(*this);
@@ -1428,28 +1429,28 @@
PA.Revert();
- if (TPR == TPResult::Error())
- return TPResult::Error();
+ if (TPR == TPResult::Error)
+ return TPResult::Error;
if (isFollowedByParen)
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
return BracedCastResult;
- return TPResult::True();
+ return TPResult::True;
}
// C++0x type traits support
case tok::kw___underlying_type:
- return TPResult::True();
+ return TPResult::True;
// C11 _Atomic
case tok::kw__Atomic:
- return TPResult::True();
+ return TPResult::True;
default:
- return TPResult::False();
+ return TPResult::False;
}
}
@@ -1515,9 +1516,9 @@
// Parse through the parens after 'typeof'.
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// [ObjC] protocol-qualifiers:
@@ -1527,7 +1528,7 @@
ConsumeToken();
do {
if (Tok.isNot(tok::identifier))
- return TPResult::Error();
+ return TPResult::Error;
ConsumeToken();
if (Tok.is(tok::comma)) {
@@ -1537,11 +1538,11 @@
if (Tok.is(tok::greater)) {
ConsumeToken();
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
} while (false);
- return TPResult::Error();
+ return TPResult::Error;
}
/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
@@ -1570,9 +1571,9 @@
ConsumeParen();
bool InvalidAsDeclaration = false;
TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration);
- if (TPR == TPResult::Ambiguous()) {
+ if (TPR == TPResult::Ambiguous) {
if (Tok.isNot(tok::r_paren))
- TPR = TPResult::False();
+ TPR = TPResult::False;
else {
const Token &Next = NextToken();
if (Next.is(tok::amp) || Next.is(tok::ampamp) ||
@@ -1584,20 +1585,20 @@
// The next token cannot appear after a constructor-style initializer,
// and can appear next in a function definition. This must be a function
// declarator.
- TPR = TPResult::True();
+ TPR = TPResult::True;
else if (InvalidAsDeclaration)
// Use the absence of 'typename' as a tie-breaker.
- TPR = TPResult::False();
+ TPR = TPResult::False;
}
}
PA.Revert();
- if (IsAmbiguous && TPR == TPResult::Ambiguous())
+ if (IsAmbiguous && TPR == TPResult::Ambiguous)
*IsAmbiguous = true;
// In case of an error, let the declaration parsing code handle it.
- return TPR != TPResult::False();
+ return TPR != TPResult::False;
}
/// parameter-declaration-clause:
@@ -1622,7 +1623,7 @@
bool VersusTemplateArgument) {
if (Tok.is(tok::r_paren))
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
// parameter-declaration-list[opt] '...'[opt]
// parameter-declaration-list ',' '...'
@@ -1636,15 +1637,15 @@
if (Tok.is(tok::ellipsis)) {
ConsumeToken();
if (Tok.is(tok::r_paren))
- return TPResult::True(); // '...)' is a sign of a function declarator.
+ return TPResult::True; // '...)' is a sign of a function declarator.
else
- return TPResult::False();
+ return TPResult::False;
}
// An attribute-specifier-seq here is a sign of a function declarator.
if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
/*OuterMightBeMessageSend*/true))
- return TPResult::True();
+ return TPResult::True;
ParsedAttributes attrs(AttrFactory);
MaybeParseMicrosoftAttributes(attrs);
@@ -1652,43 +1653,43 @@
// decl-specifier-seq
// A parameter-declaration's initializer must be preceded by an '=', so
// decl-specifier-seq '{' is not a parameter in C++11.
- TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+ TPResult TPR = isCXXDeclarationSpecifier(TPResult::False,
InvalidAsDeclaration);
- if (VersusTemplateArgument && TPR == TPResult::True()) {
+ if (VersusTemplateArgument && TPR == TPResult::True) {
// Consume the decl-specifier-seq. We have to look past it, since a
// type-id might appear here in a template argument.
bool SeenType = false;
do {
SeenType |= isCXXDeclarationSpecifierAType();
- if (TryConsumeDeclarationSpecifier() == TPResult::Error())
- return TPResult::Error();
+ if (TryConsumeDeclarationSpecifier() == TPResult::Error)
+ return TPResult::Error;
// If we see a parameter name, this can't be a template argument.
if (SeenType && Tok.is(tok::identifier))
- return TPResult::True();
+ return TPResult::True;
- TPR = isCXXDeclarationSpecifier(TPResult::False(),
+ TPR = isCXXDeclarationSpecifier(TPResult::False,
InvalidAsDeclaration);
- if (TPR == TPResult::Error())
+ if (TPR == TPResult::Error)
return TPR;
- } while (TPR != TPResult::False());
- } else if (TPR == TPResult::Ambiguous()) {
+ } while (TPR != TPResult::False);
+ } else if (TPR == TPResult::Ambiguous) {
// Disambiguate what follows the decl-specifier.
- if (TryConsumeDeclarationSpecifier() == TPResult::Error())
- return TPResult::Error();
+ if (TryConsumeDeclarationSpecifier() == TPResult::Error)
+ return TPResult::Error;
} else
return TPR;
// declarator
// abstract-declarator[opt]
TPR = TryParseDeclarator(true/*mayBeAbstract*/);
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
// [GNU] attributes[opt]
if (Tok.is(tok::kw___attribute))
- return TPResult::True();
+ return TPResult::True;
// If we're disambiguating a template argument in a default argument in
// a class definition versus a parameter declaration, an '=' here
@@ -1701,36 +1702,36 @@
// parameter-declaration-clause, and the last param is missing its default
// argument.
if (VersusTemplateArgument)
- return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True()
- : TPResult::False();
+ return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True
+ : TPResult::False;
if (Tok.is(tok::equal)) {
// '=' assignment-expression
// Parse through assignment-expression.
// FIXME: assignment-expression may contain an unparenthesized comma.
if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch))
- return TPResult::Error();
+ return TPResult::Error;
}
if (Tok.is(tok::ellipsis)) {
ConsumeToken();
if (Tok.is(tok::r_paren))
- return TPResult::True(); // '...)' is a sign of a function declarator.
+ return TPResult::True; // '...)' is a sign of a function declarator.
else
- return TPResult::False();
+ return TPResult::False;
}
if (!TryConsumeToken(tok::comma))
break;
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
/// parsing as a function declarator.
/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
-/// return TPResult::Ambiguous(), otherwise it will return either False() or
+/// return TPResult::Ambiguous, otherwise it will return either False() or
/// Error().
///
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
@@ -1744,15 +1745,15 @@
// The '(' is already parsed.
TPResult TPR = TryParseParameterDeclarationClause();
- if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
- TPR = TPResult::False();
+ if (TPR == TPResult::Ambiguous && Tok.isNot(tok::r_paren))
+ TPR = TPResult::False;
- if (TPR == TPResult::False() || TPR == TPResult::Error())
+ if (TPR == TPResult::False || TPR == TPResult::Error)
return TPR;
// Parse through the parens.
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
// cv-qualifier-seq
while (Tok.is(tok::kw_const) ||
@@ -1768,12 +1769,12 @@
if (Tok.is(tok::kw_throw)) {
ConsumeToken();
if (Tok.isNot(tok::l_paren))
- return TPResult::Error();
+ return TPResult::Error;
// Parse through the parens after 'throw'.
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
}
if (Tok.is(tok::kw_noexcept)) {
ConsumeToken();
@@ -1782,11 +1783,11 @@
// Find the matching rparen.
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
}
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// '[' constant-expression[opt] ']'
@@ -1794,7 +1795,7 @@
Parser::TPResult Parser::TryParseBracketDeclarator() {
ConsumeBracket();
if (!SkipUntil(tok::r_square, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 9936a5a..d28e046 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -56,10 +56,10 @@
SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies;
Tok.startToken();
Tok.setKind(tok::eof);
- Actions.CurScope = 0;
+ Actions.CurScope = nullptr;
NumCachedScopes = 0;
ParenCount = BracketCount = BraceCount = 0;
- CurParsedObjCImpl = 0;
+ CurParsedObjCImpl = nullptr;
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
@@ -136,7 +136,7 @@
}
SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
- const char *Spelling = 0;
+ const char *Spelling = nullptr;
if (EndLoc.isValid())
Spelling = tok::getPunctuatorSpelling(ExpectedTok);
@@ -365,8 +365,7 @@
// Inform the actions module that this scope is going away if there are any
// decls in it.
- if (!getCurScope()->decl_empty())
- Actions.ActOnPopScope(Tok.getLocation(), getCurScope());
+ Actions.ActOnPopScope(Tok.getLocation(), getCurScope());
Scope *OldScope = getCurScope();
Actions.CurScope = OldScope->getParent();
@@ -381,7 +380,7 @@
/// this object does nothing.
Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags,
bool ManageFlags)
- : CurScope(ManageFlags ? Self->getCurScope() : 0) {
+ : CurScope(ManageFlags ? Self->getCurScope() : nullptr) {
if (CurScope) {
OldFlags = CurScope->getFlags();
CurScope->setFlags(ScopeFlags);
@@ -403,8 +402,8 @@
Parser::~Parser() {
// If we still have scopes active, delete the scope tree.
delete getCurScope();
- Actions.CurScope = 0;
-
+ Actions.CurScope = nullptr;
+
// Free the scope cache.
for (unsigned i = 0, e = NumCachedScopes; i != e; ++i)
delete ScopeCache[i];
@@ -422,7 +421,7 @@
///
void Parser::Initialize() {
// Create the translation unit scope. Install it as the current scope.
- assert(getCurScope() == 0 && "A scope is already active?");
+ assert(getCurScope() == nullptr && "A scope is already active?");
EnterScope(Scope::DeclScope);
Actions.ActOnTranslationUnitScope(getCurScope());
@@ -437,10 +436,10 @@
ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
}
- Ident_instancetype = 0;
- Ident_final = 0;
- Ident_sealed = 0;
- Ident_override = 0;
+ Ident_instancetype = nullptr;
+ Ident_final = nullptr;
+ Ident_sealed = nullptr;
+ Ident_override = nullptr;
Ident_super = &PP.getIdentifierTable().get("super");
@@ -450,16 +449,18 @@
Ident_bool = &PP.getIdentifierTable().get("bool");
}
- Ident_introduced = 0;
- Ident_deprecated = 0;
- Ident_obsoleted = 0;
- Ident_unavailable = 0;
+ Ident_introduced = nullptr;
+ Ident_deprecated = nullptr;
+ Ident_obsoleted = nullptr;
+ Ident_unavailable = nullptr;
- Ident__except = 0;
-
- Ident__exception_code = Ident__exception_info = Ident__abnormal_termination = 0;
- Ident___exception_code = Ident___exception_info = Ident___abnormal_termination = 0;
- Ident_GetExceptionCode = Ident_GetExceptionInfo = Ident_AbnormalTermination = 0;
+ Ident__except = nullptr;
+
+ Ident__exception_code = Ident__exception_info = nullptr;
+ Ident__abnormal_termination = Ident___exception_code = nullptr;
+ Ident___exception_info = Ident___abnormal_termination = nullptr;
+ Ident_GetExceptionCode = Ident_GetExceptionInfo = nullptr;
+ Ident_AbnormalTermination = nullptr;
if(getLangOpts().Borland) {
Ident__exception_info = PP.getIdentifierInfo("_exception_info");
@@ -593,7 +594,7 @@
return DeclGroupPtrTy();
}
- Decl *SingleDecl = 0;
+ Decl *SingleDecl = nullptr;
switch (Tok.getKind()) {
case tok::annot_pragma_vis:
HandlePragmaVisibility();
@@ -631,6 +632,9 @@
case tok::annot_pragma_ms_vtordisp:
HandlePragmaMSVtorDisp();
return DeclGroupPtrTy();
+ case tok::annot_pragma_ms_pragma:
+ HandlePragmaMSPragma();
+ return DeclGroupPtrTy();
case tok::semi:
// Either a C++11 empty-declaration or attribute-declaration.
SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
@@ -858,7 +862,7 @@
DS.abort();
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID,
Actions.getASTContext().getPrintingPolicy()))
@@ -955,7 +959,7 @@
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
- return 0;
+ return nullptr;
}
// Check to make sure that any normal attributes are allowed to be on
@@ -1039,8 +1043,8 @@
if (TryConsumeToken(tok::equal)) {
assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
- Actions.ActOnFinishFunctionBody(Res, 0, false);
-
+ Actions.ActOnFinishFunctionBody(Res, nullptr, false);
+
bool Delete = false;
SourceLocation KWLoc;
if (TryConsumeToken(tok::kw_delete, KWLoc)) {
@@ -1081,7 +1085,7 @@
// Recover from error.
if (!Tok.is(tok::l_brace)) {
BodyScope.Exit();
- Actions.ActOnFinishFunctionBody(Res, 0);
+ Actions.ActOnFinishFunctionBody(Res, nullptr);
return Res;
}
} else
@@ -1357,7 +1361,7 @@
// jump back into scope specifier parsing).
Sema::NameClassification Classification
= Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next,
- IsAddressOfOperand, SS.isEmpty() ? CCC : 0);
+ IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr);
switch (Classification.getKind()) {
case Sema::NC_Error:
@@ -1511,7 +1515,7 @@
CXXScopeSpec SS;
if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(),
/*EnteringContext=*/false,
- 0, /*IsTypename*/true))
+ nullptr, /*IsTypename*/ true))
return true;
if (!SS.isSet()) {
if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id) ||
@@ -1594,7 +1598,7 @@
CXXScopeSpec &SS,
bool IsNewScope) {
if (Tok.is(tok::identifier)) {
- IdentifierInfo *CorrectedII = 0;
+ IdentifierInfo *CorrectedII = nullptr;
// Determine whether the identifier is a type name.
if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), getCurScope(),
@@ -1602,8 +1606,9 @@
NextToken().is(tok::period),
ParsedType(),
/*IsCtorOrDtorName=*/false,
- /*NonTrivialTypeSourceInfo*/true,
- NeedType ? &CorrectedII : NULL)) {
+ /*NonTrivialTypeSourceInfo*/ true,
+ NeedType ? &CorrectedII
+ : nullptr)) {
// A FixIt was applied as a result of typo correction
if (CorrectedII)
Tok.setIdentifierInfo(CorrectedII);
@@ -1893,8 +1898,7 @@
if (!Tok.is(tok::identifier)) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteModuleImport(ImportLoc, Path);
- ConsumeCodeCompletionToken();
- SkipUntil(tok::semi);
+ cutOffParsing();
return DeclGroupPtrTy();
}
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
index 711dc2a..4f5f3ab 100644
--- a/lib/Parse/RAIIObjectsForParser.h
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -50,7 +50,7 @@
public:
/// Begin suppressing access-like checks
SuppressAccessChecks(Parser &P, bool activate = true)
- : S(P.getActions()), DiagnosticPool(NULL) {
+ : S(P.getActions()), DiagnosticPool(nullptr) {
if (activate) {
State = S.PushParsingDeclaration(DiagnosticPool);
Active = true;
@@ -61,7 +61,7 @@
void done() {
assert(Active && "trying to end an inactive suppression");
- S.PopParsingDeclaration(State, NULL);
+ S.PopParsingDeclaration(State, nullptr);
Active = false;
}
@@ -93,7 +93,7 @@
public:
enum NoParent_t { NoParent };
ParsingDeclRAIIObject(Parser &P, NoParent_t _)
- : Actions(P.getActions()), DiagnosticPool(NULL) {
+ : Actions(P.getActions()), DiagnosticPool(nullptr) {
push();
}
@@ -109,7 +109,7 @@
/// RAII object (which is assumed to be the current top pool).
ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
: Actions(P.getActions()),
- DiagnosticPool(other ? other->DiagnosticPool.getParent() : NULL) {
+ DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
if (other) {
DiagnosticPool.steal(other->DiagnosticPool);
other->abort();
@@ -137,7 +137,7 @@
/// Signals that the context was completed without an appropriate
/// declaration being parsed.
void abort() {
- pop(0);
+ pop(nullptr);
}
void complete(Decl *D) {
@@ -148,7 +148,7 @@
/// Unregister this object from Sema, but remember all the
/// diagnostics that were emitted into it.
void abortAndRemember() {
- pop(0);
+ pop(nullptr);
}
private:
diff --git a/lib/Rewrite/Core/DeltaTree.cpp b/lib/Rewrite/Core/DeltaTree.cpp
index 7a7f15b..352fab0 100644
--- a/lib/Rewrite/Core/DeltaTree.cpp
+++ b/lib/Rewrite/Core/DeltaTree.cpp
@@ -216,9 +216,9 @@
DoSplit(*InsertRes);
if (InsertRes->Split.FileLoc > FileIndex)
- InsertRes->LHS->DoInsertion(FileIndex, Delta, 0 /*can't fail*/);
+ InsertRes->LHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/);
else
- InsertRes->RHS->DoInsertion(FileIndex, Delta, 0 /*can't fail*/);
+ InsertRes->RHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/);
return true;
}
diff --git a/lib/Rewrite/Core/RewriteRope.cpp b/lib/Rewrite/Core/RewriteRope.cpp
index fe7aa2d..ef8abfc 100644
--- a/lib/Rewrite/Core/RewriteRope.cpp
+++ b/lib/Rewrite/Core/RewriteRope.cpp
@@ -146,7 +146,7 @@
RopePieceBTreeLeaf **PrevLeaf, *NextLeaf;
public:
RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0),
- PrevLeaf(0), NextLeaf(0) {}
+ PrevLeaf(nullptr), NextLeaf(nullptr) {}
~RopePieceBTreeLeaf() {
if (PrevLeaf || NextLeaf)
removeFromLeafInOrder();
@@ -171,7 +171,7 @@
const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
- assert(PrevLeaf == 0 && NextLeaf == 0 && "Already in ordering");
+ assert(!PrevLeaf && !NextLeaf && "Already in ordering");
NextLeaf = Node->NextLeaf;
if (NextLeaf)
@@ -186,7 +186,7 @@
if (NextLeaf)
NextLeaf->PrevLeaf = PrevLeaf;
} else if (NextLeaf) {
- NextLeaf->PrevLeaf = 0;
+ NextLeaf->PrevLeaf = nullptr;
}
}
@@ -236,7 +236,7 @@
// specified offset so find it.
if (Offset == 0 || Offset == size()) {
// Fastpath for a common case. There is already a splitpoint at the end.
- return 0;
+ return nullptr;
}
// Find the piece that this offset lands in.
@@ -250,7 +250,7 @@
// If there is already a split point at the specified offset, just return
// success.
if (PieceOffs == Offset)
- return 0;
+ return nullptr;
// Otherwise, we need to split piece 'i' at Offset-PieceOffs. Convert Offset
// to being Piece relative.
@@ -296,7 +296,7 @@
Pieces[i] = R;
++NumPieces;
Size += R.size();
- return 0;
+ return nullptr;
}
// Otherwise, if this is leaf is full, split it in two halves. Since this
@@ -470,7 +470,7 @@
RopePieceBTreeNode *RopePieceBTreeInterior::split(unsigned Offset) {
// Figure out which child to split.
if (Offset == 0 || Offset == size())
- return 0; // If we have an exact offset, we're already split.
+ return nullptr; // If we have an exact offset, we're already split.
unsigned ChildOffset = 0;
unsigned i = 0;
@@ -479,12 +479,12 @@
// If already split there, we're done.
if (ChildOffset == Offset)
- return 0;
+ return nullptr;
// Otherwise, recursively split the child.
if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset-ChildOffset))
return HandleChildPiece(i, RHS);
- return 0; // Done!
+ return nullptr; // Done!
}
/// insert - Insert the specified ropepiece into this tree node at the
@@ -515,7 +515,7 @@
if (RopePieceBTreeNode *RHS = getChild(i)->insert(Offset-ChildOffs, R))
return HandleChildPiece(i, RHS);
- return 0;
+ return nullptr;
}
/// HandleChildPiece - A child propagated an insertion result up to us.
@@ -531,7 +531,7 @@
(getNumChildren()-i-1)*sizeof(Children[0]));
Children[i+1] = RHS;
++NumChildren;
- return 0;
+ return nullptr;
}
// Okay, this node is full. Split it in half, moving WidthFactor children to
@@ -678,10 +678,10 @@
while (CurNode && getCN(CurNode)->getNumPieces() == 0)
CurNode = getCN(CurNode)->getNextLeafInOrder();
- if (CurNode != 0)
+ if (CurNode)
CurPiece = &getCN(CurNode)->getPiece(0);
else // Empty tree, this is an end() iterator.
- CurPiece = 0;
+ CurPiece = nullptr;
CurChar = 0;
}
@@ -697,10 +697,10 @@
CurNode = getCN(CurNode)->getNextLeafInOrder();
while (CurNode && getCN(CurNode)->getNumPieces() == 0);
- if (CurNode != 0)
+ if (CurNode)
CurPiece = &getCN(CurNode)->getPiece(0);
else // Hit end().
- CurPiece = 0;
+ CurPiece = nullptr;
CurChar = 0;
}
@@ -788,9 +788,8 @@
// Otherwise, this was a small request but we just don't have space for it
// Make a new chunk and share it with later allocations.
- // If we had an old allocation, drop our reference to it.
- if (AllocBuffer && --AllocBuffer->RefCount == 0)
- delete [] (char*)AllocBuffer;
+ if (AllocBuffer)
+ AllocBuffer->dropRef();
unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
AllocBuffer = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
diff --git a/lib/Rewrite/Core/Rewriter.cpp b/lib/Rewrite/Core/Rewriter.cpp
index 08352a2..c0f87d2 100644
--- a/lib/Rewrite/Core/Rewriter.cpp
+++ b/lib/Rewrite/Core/Rewriter.cpp
@@ -340,7 +340,7 @@
// Get the new text.
std::string SStr;
llvm::raw_string_ostream S(SStr);
- To->printPretty(S, 0, PrintingPolicy(*LangOpts));
+ To->printPretty(S, nullptr, PrintingPolicy(*LangOpts));
const std::string &Str = S.str();
ReplaceText(From->getLocStart(), Size, Str);
@@ -350,7 +350,7 @@
std::string Rewriter::ConvertToString(Stmt *From) {
std::string SStr;
llvm::raw_string_ostream S(SStr);
- From->printPretty(S, 0, PrintingPolicy(*LangOpts));
+ From->printPretty(S, nullptr, PrintingPolicy(*LangOpts));
return S.str();
}
diff --git a/lib/Rewrite/Frontend/FrontendActions.cpp b/lib/Rewrite/Frontend/FrontendActions.cpp
index bf27efe..4394e99 100644
--- a/lib/Rewrite/Frontend/FrontendActions.cpp
+++ b/lib/Rewrite/Frontend/FrontendActions.cpp
@@ -34,7 +34,7 @@
StringRef InFile) {
if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
return CreateHTMLPrinter(OS, CI.getPreprocessor());
- return 0;
+ return nullptr;
}
FixItAction::FixItAction() {}
@@ -127,8 +127,8 @@
err = Rewriter.WriteFixedFiles(&RewrittenFiles);
FixAction->EndSourceFile();
- CI.setSourceManager(0);
- CI.setFileManager(0);
+ CI.setSourceManager(nullptr);
+ CI.setFileManager(nullptr);
} else {
err = true;
}
@@ -163,7 +163,7 @@
CI.getDiagnostics(), CI.getLangOpts(),
CI.getDiagnosticOpts().NoRewriteMacros);
}
- return 0;
+ return nullptr;
}
void RewriteMacrosAction::ExecuteAction() {
diff --git a/lib/Rewrite/Frontend/InclusionRewriter.cpp b/lib/Rewrite/Frontend/InclusionRewriter.cpp
index 058960d..aa7017b 100644
--- a/lib/Rewrite/Frontend/InclusionRewriter.cpp
+++ b/lib/Rewrite/Frontend/InclusionRewriter.cpp
@@ -88,7 +88,7 @@
/// Initializes an InclusionRewriter with a \p PP source and \p OS destination.
InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS,
bool ShowLineMarkers)
- : PP(PP), SM(PP.getSourceManager()), OS(OS), PredefinesBuffer(0),
+ : PP(PP), SM(PP.getSourceManager()), OS(OS), PredefinesBuffer(nullptr),
ShowLineMarkers(ShowLineMarkers),
LastInsertedFileChange(FileChanges.end()) {
// If we're in microsoft mode, use normal #line instead of line markers.
@@ -191,7 +191,7 @@
FileChangeMap::const_iterator I = FileChanges.find(Loc.getRawEncoding());
if (I != FileChanges.end())
return &I->second;
- return NULL;
+ return nullptr;
}
/// Detect the likely line ending style of \p FromFile by examining the first
@@ -200,7 +200,7 @@
// detect what line endings the file uses, so that added content does not mix
// the style
const char *Pos = strchr(FromFile.getBufferStart(), '\n');
- if (Pos == NULL)
+ if (!Pos)
return "\n";
if (Pos + 1 < FromFile.getBufferEnd() && Pos[1] == '\r')
return "\n\r";
@@ -250,6 +250,10 @@
do {
DirectiveLex.LexFromRawLexer(DirectiveToken);
} while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof));
+ if (&FromFile == PredefinesBuffer) {
+ // OutputContentUpTo() would not output anything anyway.
+ return;
+ }
OS << "#if 0 /* expanded by -frewrite-includes */" << EOL;
OutputContentUpTo(FromFile, NextToWrite,
SM.getFileOffset(DirectiveToken.getLocation()) + DirectiveToken.getLength(),
@@ -330,10 +334,11 @@
bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
const DirectoryLookup *CurDir;
const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
- Filename, SourceLocation(), isAngled, 0, CurDir,
- PP.getSourceManager().getFileEntryForID(FileId), 0, 0, 0, false);
+ Filename, SourceLocation(), isAngled, nullptr, CurDir,
+ PP.getSourceManager().getFileEntryForID(FileId), nullptr, nullptr,
+ nullptr, false);
- FileExists = File != 0;
+ FileExists = File != nullptr;
return true;
}
@@ -352,8 +357,11 @@
StringRef EOL = DetectEOL(FromFile);
- // Per the GNU docs: "1" indicates the start of a new file.
- WriteLineInfo(FileName, 1, FileType, EOL, " 1");
+ // Per the GNU docs: "1" indicates entering a new file.
+ if (FileId == SM.getMainFileID() || FileId == PP.getPredefinesFileID())
+ WriteLineInfo(FileName, 1, FileType, EOL, "");
+ else
+ WriteLineInfo(FileName, 1, FileType, EOL, " 1");
if (SM.getFileIDSize(FileId) == 0)
return false;
@@ -376,13 +384,15 @@
RawLex.LexFromRawLexer(RawToken);
if (RawToken.is(tok::raw_identifier))
PP.LookUpIdentifierInfo(RawToken);
- if (RawToken.getIdentifierInfo() != NULL) {
+ if (RawToken.getIdentifierInfo() != nullptr) {
switch (RawToken.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
case tok::pp_include_next:
case tok::pp_import: {
CommentOutDirective(RawLex, HashToken, FromFile, EOL, NextToWrite,
Line);
+ if (FileId != PP.getPredefinesFileID())
+ WriteLineInfo(FileName, Line - 1, FileType, EOL, "");
StringRef LineInfoExtra;
if (const FileChange *Change = FindFileChangeLocation(
HashToken.getLocation())) {
@@ -439,7 +449,8 @@
// Rewrite __has_include(x)
if (RawToken.getIdentifierInfo()->isStr("__has_include")) {
- if (!HandleHasInclude(FileId, RawLex, 0, RawToken, HasFile))
+ if (!HandleHasInclude(FileId, RawLex, nullptr, RawToken,
+ HasFile))
continue;
// Rewrite __has_include_next(x)
} else if (RawToken.getIdentifierInfo()->isStr(
@@ -514,13 +525,7 @@
InclusionRewriter *Rewrite = new InclusionRewriter(PP, *OS,
Opts.ShowLineMarkers);
PP.addPPCallbacks(Rewrite);
- // Ignore all pragmas, otherwise there will be warnings about unknown pragmas
- // (because there's nothing to handle them).
- PP.AddPragmaHandler(new EmptyPragmaHandler());
- // Ignore also all pragma in all namespaces created
- // in Preprocessor::RegisterBuiltinPragmas().
- PP.AddPragmaHandler("GCC", new EmptyPragmaHandler());
- PP.AddPragmaHandler("clang", new EmptyPragmaHandler());
+ PP.IgnorePragmas();
// First let the preprocessor process the entire file and call callbacks.
// Callbacks will record which #include's were actually performed.
diff --git a/lib/Rewrite/Frontend/RewriteModernObjC.cpp b/lib/Rewrite/Frontend/RewriteModernObjC.cpp
index 9066a5f..3cacbdd 100644
--- a/lib/Rewrite/Frontend/RewriteModernObjC.cpp
+++ b/lib/Rewrite/Frontend/RewriteModernObjC.cpp
@@ -280,7 +280,7 @@
// Get the new text.
std::string SStr;
llvm::raw_string_ostream S(SStr);
- New->printPretty(S, 0, PrintingPolicy(LangOpts));
+ New->printPretty(S, nullptr, PrintingPolicy(LangOpts));
const std::string &Str = S.str();
// If replacement succeeded or warning disabled return with no warning.
@@ -598,14 +598,14 @@
CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
CastKind Kind, Expr *E) {
TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
- return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo,
- SourceLocation(), SourceLocation());
+ return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, nullptr,
+ TInfo, SourceLocation(), SourceLocation());
}
bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
IdentifierInfo* II = &Context->Idents.get("load");
Selector LoadSel = Context->Selectors.getSelector(0, &II);
- return OD->getClassMethod(LoadSel) != 0;
+ return OD->getClassMethod(LoadSel) != nullptr;
}
StringLiteral *getStringLiteral(StringRef Str) {
@@ -686,30 +686,30 @@
Context = &context;
SM = &Context->getSourceManager();
TUDecl = Context->getTranslationUnitDecl();
- MsgSendFunctionDecl = 0;
- MsgSendSuperFunctionDecl = 0;
- MsgSendStretFunctionDecl = 0;
- MsgSendSuperStretFunctionDecl = 0;
- MsgSendFpretFunctionDecl = 0;
- GetClassFunctionDecl = 0;
- GetMetaClassFunctionDecl = 0;
- GetSuperClassFunctionDecl = 0;
- SelGetUidFunctionDecl = 0;
- CFStringFunctionDecl = 0;
- ConstantStringClassReference = 0;
- NSStringRecord = 0;
- CurMethodDef = 0;
- CurFunctionDef = 0;
- GlobalVarDecl = 0;
- GlobalConstructionExp = 0;
- SuperStructDecl = 0;
- ProtocolTypeDecl = 0;
- ConstantStringDecl = 0;
+ MsgSendFunctionDecl = nullptr;
+ MsgSendSuperFunctionDecl = nullptr;
+ MsgSendStretFunctionDecl = nullptr;
+ MsgSendSuperStretFunctionDecl = nullptr;
+ MsgSendFpretFunctionDecl = nullptr;
+ GetClassFunctionDecl = nullptr;
+ GetMetaClassFunctionDecl = nullptr;
+ GetSuperClassFunctionDecl = nullptr;
+ SelGetUidFunctionDecl = nullptr;
+ CFStringFunctionDecl = nullptr;
+ ConstantStringClassReference = nullptr;
+ NSStringRecord = nullptr;
+ CurMethodDef = nullptr;
+ CurFunctionDef = nullptr;
+ GlobalVarDecl = nullptr;
+ GlobalConstructionExp = nullptr;
+ SuperStructDecl = nullptr;
+ ProtocolTypeDecl = nullptr;
+ ConstantStringDecl = nullptr;
BcLabelCount = 0;
- SuperConstructorFunctionDecl = 0;
+ SuperConstructorFunctionDecl = nullptr;
NumObjCStringLiterals = 0;
- PropParentMap = 0;
- CurrentBody = 0;
+ PropParentMap = nullptr;
+ CurrentBody = nullptr;
DisableReplaceStmt = false;
objc_impl_method = false;
@@ -894,11 +894,11 @@
Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
Zero);
- FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get(D->getNameAsString()),
- IvarT, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
+ IvarT, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
FD->getType(), VK_LValue,
@@ -981,7 +981,7 @@
if (GenGetProperty) {
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
Getr += "typedef ";
- const FunctionType *FPRetType = 0;
+ const FunctionType *FPRetType = nullptr;
RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr,
FPRetType);
Getr += " _TYPE";
@@ -1266,7 +1266,7 @@
ObjCMethodDecl *OMD,
std::string &ResultStr) {
//fprintf(stderr,"In RewriteObjCMethodDecl\n");
- const FunctionType *FPRetType = 0;
+ const FunctionType *FPRetType = nullptr;
ResultStr += "\nstatic ";
RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);
ResultStr += " ";
@@ -1458,7 +1458,7 @@
DisableReplaceStmtScope S(*this);
// Rebuild the base expression if we have one.
- Base = 0;
+ Base = nullptr;
if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
Base = OldMsg->getInstanceReceiver();
Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
@@ -1479,7 +1479,7 @@
SmallVector<SourceLocation, 1> SelLocs;
OldMsg->getSelectorLocs(SelLocs);
- ObjCMessageExpr *NewMsg = 0;
+ ObjCMessageExpr *NewMsg = nullptr;
switch (OldMsg->getReceiverKind()) {
case ObjCMessageExpr::Class:
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
@@ -1539,7 +1539,7 @@
// Because the rewriter doesn't allow us to rewrite rewritten code,
// we need to suppress rewriting the sub-statements.
- Expr *Base = 0;
+ Expr *Base = nullptr;
SmallVector<Expr*, 1> Args;
{
DisableReplaceStmtScope S(*this);
@@ -1562,7 +1562,7 @@
// Intentionally empty.
SmallVector<SourceLocation, 1> SelLocs;
- ObjCMessageExpr *NewMsg = 0;
+ ObjCMessageExpr *NewMsg = nullptr;
switch (OldMsg->getReceiverKind()) {
case ObjCMessageExpr::Class:
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
@@ -1646,7 +1646,7 @@
buf += utostr(ObjCBcLabelNo.back());
ReplaceText(startLoc, strlen("break"), buf);
- return 0;
+ return nullptr;
}
void RewriteModernObjC::ConvertSourceLocationToLineDirective(
@@ -1676,7 +1676,7 @@
buf += utostr(ObjCBcLabelNo.back());
ReplaceText(startLoc, strlen("continue"), buf);
- return 0;
+ return nullptr;
}
/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
@@ -1875,7 +1875,7 @@
}
Stmts.pop_back();
ObjCBcLabelNo.pop_back();
- return 0;
+ return nullptr;
}
static void Write_RethrowObject(std::string &buf) {
@@ -1937,7 +1937,7 @@
ReplaceText(startRBraceLoc, 1, buf);
- return 0;
+ return nullptr;
}
void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
@@ -1959,8 +1959,8 @@
ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");
ReplaceText(S->getSubStmt()->getLocStart(), 1,
"{ __AtAutoreleasePool __autoreleasepool; ");
-
- return 0;
+
+ return nullptr;
}
Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
@@ -2061,7 +2061,7 @@
WarnAboutReturnGotoStmts(S->getTryBody());
}
- return 0;
+ return nullptr;
}
// This can't be done with ReplaceStmt(S, ThrowExpr), since
@@ -2093,7 +2093,7 @@
SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
if (S->getThrowExpr())
ReplaceText(semiLoc, 1, ");");
- return 0;
+ return nullptr;
}
Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
@@ -2136,7 +2136,7 @@
QualType pToFunc = Context->getPointerType(msgSendType);
ImplicitCastExpr *ICE =
ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
- DRE, 0, VK_RValue);
+ DRE, nullptr, VK_RValue);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
@@ -2212,7 +2212,7 @@
const char *startBuf = SM->getCharacterData(Loc);
const char *endBuf = SM->getCharacterData(EndLoc);
- const char *startRef = 0, *endRef = 0;
+ const char *startRef = nullptr, *endRef = nullptr;
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
// Get the locations of the startRef, endRef.
SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
@@ -2227,7 +2227,7 @@
void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
SourceLocation Loc;
QualType Type;
- const FunctionProtoType *proto = 0;
+ const FunctionProtoType *proto = nullptr;
if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
Loc = VD->getLocation();
Type = VD->getType();
@@ -2261,7 +2261,7 @@
const char *startBuf = endBuf;
while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
startBuf--; // scan backward (from the decl location) for return type.
- const char *startRef = 0, *endRef = 0;
+ const char *startRef = nullptr, *endRef = nullptr;
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
// Get the locations of the startRef, endRef.
SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
@@ -2283,7 +2283,7 @@
const char *endBuf = startBuf;
// scan forward (from the decl location) for argument types.
scanToNextArgument(endBuf);
- const char *startRef = 0, *endRef = 0;
+ const char *startRef = nullptr, *endRef = nullptr;
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
// Get the locations of the startRef, endRef.
SourceLocation LessLoc =
@@ -2352,8 +2352,8 @@
SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- SelGetUidIdent, getFuncType, 0,
- SC_Extern);
+ SelGetUidIdent, getFuncType,
+ nullptr, SC_Extern);
}
void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {
@@ -2451,7 +2451,7 @@
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType,
- 0, SC_Extern);
+ nullptr, SC_Extern);
}
// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
@@ -2469,7 +2469,7 @@
MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- msgSendIdent, msgSendType, 0,
+ msgSendIdent, msgSendType, nullptr,
SC_Extern);
}
@@ -2483,8 +2483,8 @@
MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- msgSendIdent, msgSendType, 0,
- SC_Extern);
+ msgSendIdent, msgSendType,
+ nullptr, SC_Extern);
}
// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
@@ -2502,8 +2502,8 @@
MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- msgSendIdent, msgSendType, 0,
- SC_Extern);
+ msgSendIdent, msgSendType,
+ nullptr, SC_Extern);
}
// SynthMsgSendSuperStretFunctionDecl -
@@ -2519,7 +2519,7 @@
SourceLocation(),
SourceLocation(),
msgSendIdent,
- msgSendType, 0,
+ msgSendType, nullptr,
SC_Extern);
}
@@ -2538,8 +2538,8 @@
MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- msgSendIdent, msgSendType, 0,
- SC_Extern);
+ msgSendIdent, msgSendType,
+ nullptr, SC_Extern);
}
// SynthGetClassFunctionDecl - Class objc_getClass(const char *name);
@@ -2552,8 +2552,8 @@
GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- getClassIdent, getClassType, 0,
- SC_Extern);
+ getClassIdent, getClassType,
+ nullptr, SC_Extern);
}
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
@@ -2568,7 +2568,7 @@
SourceLocation(),
SourceLocation(),
getSuperClassIdent,
- getClassType, 0,
+ getClassType, nullptr,
SC_Extern);
}
@@ -2583,7 +2583,7 @@
SourceLocation(),
SourceLocation(),
getClassIdent, getClassType,
- 0, SC_Extern);
+ nullptr, SC_Extern);
}
Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
@@ -2609,14 +2609,14 @@
// The pretty printer for StringLiteral handles escape characters properly.
std::string prettyBufS;
llvm::raw_string_ostream prettyBuf(prettyBufS);
- Exp->getString()->printPretty(prettyBuf, 0, PrintingPolicy(LangOpts));
+ Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));
Preamble += prettyBuf.str();
Preamble += ",";
Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(S),
- strType, 0, SC_Static);
+ strType, nullptr, SC_Static);
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue,
SourceLocation());
Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
@@ -2770,13 +2770,13 @@
Expr *NSArrayCallExpr =
new (Context) CallExpr(*Context, NSArrayDRE, InitExprs,
NSArrayFType, VK_LValue, SourceLocation());
-
- FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(),
+
+ FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("arr"),
- Context->getPointerType(Context->VoidPtrTy), 0,
- /*BitWidth=*/0, /*Mutable=*/true,
- ICIS_NoInit);
+ Context->getPointerType(Context->VoidPtrTy),
+ nullptr, /*BitWidth=*/nullptr,
+ /*Mutable=*/true, ICIS_NoInit);
MemberExpr *ArrayLiteralME =
new (Context) MemberExpr(NSArrayCallExpr, false, ARRFD,
SourceLocation(),
@@ -2907,13 +2907,13 @@
Expr *NSValueCallExpr =
new (Context) CallExpr(*Context, NSDictDRE, ValueExprs,
NSDictFType, VK_LValue, SourceLocation());
-
- FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(),
+
+ FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("arr"),
- Context->getPointerType(Context->VoidPtrTy), 0,
- /*BitWidth=*/0, /*Mutable=*/true,
- ICIS_NoInit);
+ Context->getPointerType(Context->VoidPtrTy),
+ nullptr, /*BitWidth=*/nullptr,
+ /*Mutable=*/true, ICIS_NoInit);
MemberExpr *DictLiteralValueME =
new (Context) MemberExpr(NSValueCallExpr, false, ARRFD,
SourceLocation(),
@@ -3045,9 +3045,9 @@
for (unsigned i = 0; i < 2; ++i) {
SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], 0,
- /*BitWidth=*/0,
+ SourceLocation(), nullptr,
+ FieldTypes[i], nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit));
}
@@ -3078,9 +3078,9 @@
ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
ConstantStringDecl,
SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], 0,
- /*BitWidth=*/0,
+ SourceLocation(), nullptr,
+ FieldTypes[i], nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/true,
ICIS_NoInit));
}
@@ -3231,19 +3231,19 @@
// AST for __Stretn(receiver, args).s;
IdentifierInfo *ID = &Context->Idents.get(name);
FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
- SourceLocation(), ID, castType, 0,
- SC_Extern, false, false);
+ SourceLocation(), ID, castType,
+ nullptr, SC_Extern, false, false);
DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue,
SourceLocation());
CallExpr *STCE = new (Context) CallExpr(*Context, DRE, MsgExprs,
castType, VK_LValue, SourceLocation());
-
- FieldDecl *FieldD = FieldDecl::Create(*Context, 0, SourceLocation(),
+
+ FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("s"),
- returnType, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
- ICIS_NoInit);
+ returnType, nullptr,
+ /*BitWidth=*/nullptr,
+ /*Mutable=*/true, ICIS_NoInit);
MemberExpr *ME = new (Context) MemberExpr(STCE, false, FieldD, SourceLocation(),
FieldD->getType(), VK_LValue,
OK_Ordinary);
@@ -3276,7 +3276,7 @@
// default to objc_msgSend().
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
// May need to use objc_msgSend_stret() as well.
- FunctionDecl *MsgSendStretFlavor = 0;
+ FunctionDecl *MsgSendStretFlavor = nullptr;
if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
QualType resultType = mDecl->getReturnType();
if (resultType->isRecordType())
@@ -3659,8 +3659,8 @@
Exp->getProtocol()->getNameAsString();
IdentifierInfo *ID = &Context->Idents.get(Name);
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
- SourceLocation(), ID, getProtocolType(), 0,
- SC_Extern);
+ SourceLocation(), ID, getProtocolType(),
+ nullptr, SC_Extern);
DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(),
VK_LValue, SourceLocation());
CastExpr *castExpr =
@@ -3834,8 +3834,8 @@
Type = Context->getBaseElementType(Type);
ObjCContainerDecl *IDecl =
dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());
-
- TagDecl *TD = 0;
+
+ TagDecl *TD = nullptr;
if (Type->isRecordType()) {
TD = Type->getAs<RecordType>()->getDecl();
}
@@ -3896,8 +3896,8 @@
RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(),
&Context->Idents.get(Ivar->getName()),
Ivar->getType(),
- 0, /*Expr *BW */Ivar->getBitWidth(), false,
- ICIS_NoInit));
+ nullptr, /*Expr *BW */Ivar->getBitWidth(),
+ false, ICIS_NoInit));
}
RD->completeDefinition();
return Context->getTagDeclType(RD);
@@ -4527,12 +4527,12 @@
std::string SStr;
llvm::raw_string_ostream constructorExprBuf(SStr);
- GlobalConstructionExp->printPretty(constructorExprBuf, 0,
- PrintingPolicy(LangOpts));
+ GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,
+ PrintingPolicy(LangOpts));
globalBuf += constructorExprBuf.str();
globalBuf += ";\n";
InsertText(FunLocStart, globalBuf);
- GlobalConstructionExp = 0;
+ GlobalConstructionExp = nullptr;
}
Blocks.clear();
@@ -4675,7 +4675,7 @@
Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
// Navigate to relevant type information.
- const BlockPointerType *CPT = 0;
+ const BlockPointerType *CPT = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
CPT = DRE->getType()->getAs<BlockPointerType>();
@@ -4746,11 +4746,11 @@
BlkCast);
//PE->dump();
- FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("FuncPtr"),
- Context->VoidPtrTy, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
FD->getType(), VK_LValue,
@@ -4793,12 +4793,12 @@
// for each DeclRefExp where BYREFVAR is name of the variable.
ValueDecl *VD = DeclRefExp->getDecl();
bool isArrow = DeclRefExp->refersToEnclosingLocal();
-
- FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+
+ FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("__forwarding"),
- Context->VoidPtrTy, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
FD, SourceLocation(),
@@ -4806,10 +4806,10 @@
OK_Ordinary);
StringRef Name = VD->getName();
- FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(),
+ FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
&Context->Idents.get(Name),
- Context->VoidPtrTy, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
DeclRefExp->getType(), VK_LValue, OK_Ordinary);
@@ -5214,7 +5214,7 @@
// struct __Block_byref_ND ND =
// {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
// initializer-if-any};
- bool hasInit = (ND->getInit() != 0);
+ bool hasInit = (ND->getInit() != nullptr);
// FIXME. rewriter does not support __block c++ objects which
// require construction.
if (hasInit)
@@ -5328,7 +5328,7 @@
IdentifierInfo *ID = &Context->Idents.get(name);
QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
- SourceLocation(), ID, FType, 0, SC_Extern,
+ SourceLocation(), ID, FType, nullptr, SC_Extern,
false, false);
}
@@ -5429,7 +5429,7 @@
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
SourceLocation(), SourceLocation(),
&Context->Idents.get(DescData.c_str()),
- Context->VoidPtrTy, 0,
+ Context->VoidPtrTy, nullptr,
SC_Static);
UnaryOperator *DescRefExpr =
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
@@ -5531,7 +5531,7 @@
FType, VK_LValue, SourceLocation());
if (GlobalBlockExpr) {
- assert (GlobalConstructionExp == 0 &&
+ assert (!GlobalConstructionExp &&
"SynthBlockInitExpr - GlobalConstructionExp must be null");
GlobalConstructionExp = NewRep;
NewRep = DRE;
@@ -5607,7 +5607,7 @@
// Rewrite the block body in place.
Stmt *SaveCurrentBody = CurrentBody;
CurrentBody = BE->getBody();
- PropParentMap = 0;
+ PropParentMap = nullptr;
// block literal on rhs of a property-dot-sytax assignment
// must be replaced by its synthesize ast so getRewrittenText
// works as expected. In this case, what actually ends up on RHS
@@ -5618,7 +5618,7 @@
RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
DisableReplaceStmt = saveDisableReplaceStmt;
CurrentBody = SaveCurrentBody;
- PropParentMap = 0;
+ PropParentMap = nullptr;
ImportedLocalExternalDecls.clear();
// Now we snarf the rewritten text and stash it away for later use.
std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
@@ -5838,16 +5838,16 @@
Body =
cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
FD->setBody(Body);
- CurrentBody = 0;
+ CurrentBody = nullptr;
if (PropParentMap) {
delete PropParentMap;
- PropParentMap = 0;
+ PropParentMap = nullptr;
}
// This synthesizes and inserts the block "impl" struct, invoke function,
// and any copy/dispose helper functions.
InsertBlockLiteralsWithinFunction(FD);
RewriteLineDirective(D);
- CurFunctionDef = 0;
+ CurFunctionDef = nullptr;
}
break;
}
@@ -5859,14 +5859,14 @@
Body =
cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
MD->setBody(Body);
- CurrentBody = 0;
+ CurrentBody = nullptr;
if (PropParentMap) {
delete PropParentMap;
- PropParentMap = 0;
+ PropParentMap = nullptr;
}
InsertBlockLiteralsWithinMethod(MD);
RewriteLineDirective(D);
- CurMethodDef = 0;
+ CurMethodDef = nullptr;
}
break;
}
@@ -5901,14 +5901,14 @@
GlobalVarDecl = VD;
CurrentBody = VD->getInit();
RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
- CurrentBody = 0;
+ CurrentBody = nullptr;
if (PropParentMap) {
delete PropParentMap;
- PropParentMap = 0;
+ PropParentMap = nullptr;
}
SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
- GlobalVarDecl = 0;
-
+ GlobalVarDecl = nullptr;
+
// This is needed for blocks.
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
RewriteCastExpr(CE);
@@ -6108,7 +6108,7 @@
Preamble += " int *isa;\n";
Preamble += " int flags;\n";
Preamble += " char *str;\n";
- Preamble += "#if __LLP64__\n";
+ Preamble += "#if _WIN64\n";
Preamble += " long long length;\n";
Preamble += "#else\n";
Preamble += " long length;\n";
@@ -7045,10 +7045,10 @@
// Protocol's property metadata.
SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(PDecl->properties());
Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,
- /* Container */0,
+ /* Container */nullptr,
"_OBJC_PROTOCOL_PROPERTIES_",
PDecl->getNameAsString());
-
+
// Writer out root metadata for current protocol: struct _protocol_t
Result += "\n";
if (LangOpts.MicrosoftExt)
@@ -7281,13 +7281,12 @@
Write__class_ro_t_initializer(Context, Result, flags,
InstanceStart, InstanceSize,
ClassMethods,
- 0,
- 0,
- 0,
+ nullptr,
+ nullptr,
+ nullptr,
"_OBJC_METACLASS_RO_$_",
CDecl->getNameAsString());
-
// Data for initializing _class_ro_t meta-data
flags = CLS;
if (classIsHidden)
@@ -7643,7 +7642,7 @@
dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
// lookup which class implements the instance variable.
- ObjCInterfaceDecl *clsDeclared = 0;
+ ObjCInterfaceDecl *clsDeclared = nullptr;
iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
clsDeclared);
assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
@@ -7664,7 +7663,8 @@
BaseExpr);
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(IvarOffsetName),
- Context->UnsignedLongTy, 0, SC_Extern);
+ Context->UnsignedLongTy, nullptr,
+ SC_Extern);
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false,
Context->UnsignedLongTy, VK_LValue,
SourceLocation());
@@ -7704,12 +7704,12 @@
Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
Zero);
- FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get(D->getNameAsString()),
- IvarT, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
- ICIS_NoInit);
+ IvarT, nullptr,
+ /*BitWidth=*/nullptr,
+ /*Mutable=*/true, ICIS_NoInit);
MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
FD->getType(), VK_LValue,
OK_Ordinary);
@@ -7733,13 +7733,12 @@
Exp);
if (D->isBitField()) {
- FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get(D->getNameAsString()),
- D->getType(), 0,
+ D->getType(), nullptr,
/*BitWidth=*/D->getBitWidth(),
- /*Mutable=*/true,
- ICIS_NoInit);
+ /*Mutable=*/true, ICIS_NoInit);
MemberExpr *ME = new (Context) MemberExpr(PE, /*isArrow*/false, FD, SourceLocation(),
FD->getType(), VK_LValue,
OK_Ordinary);
diff --git a/lib/Rewrite/Frontend/RewriteObjC.cpp b/lib/Rewrite/Frontend/RewriteObjC.cpp
index 80d6cc6..beadb93 100644
--- a/lib/Rewrite/Frontend/RewriteObjC.cpp
+++ b/lib/Rewrite/Frontend/RewriteObjC.cpp
@@ -229,7 +229,7 @@
// Get the new text.
std::string SStr;
llvm::raw_string_ostream S(SStr);
- New->printPretty(S, 0, PrintingPolicy(LangOpts));
+ New->printPretty(S, nullptr, PrintingPolicy(LangOpts));
const std::string &Str = S.str();
// If replacement succeeded or warning disabled return with no warning.
@@ -498,8 +498,8 @@
CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
CastKind Kind, Expr *E) {
TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
- return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo,
- SourceLocation(), SourceLocation());
+ return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, nullptr,
+ TInfo, SourceLocation(), SourceLocation());
}
StringLiteral *getStringLiteral(StringRef Str) {
@@ -609,30 +609,30 @@
Context = &context;
SM = &Context->getSourceManager();
TUDecl = Context->getTranslationUnitDecl();
- MsgSendFunctionDecl = 0;
- MsgSendSuperFunctionDecl = 0;
- MsgSendStretFunctionDecl = 0;
- MsgSendSuperStretFunctionDecl = 0;
- MsgSendFpretFunctionDecl = 0;
- GetClassFunctionDecl = 0;
- GetMetaClassFunctionDecl = 0;
- GetSuperClassFunctionDecl = 0;
- SelGetUidFunctionDecl = 0;
- CFStringFunctionDecl = 0;
- ConstantStringClassReference = 0;
- NSStringRecord = 0;
- CurMethodDef = 0;
- CurFunctionDef = 0;
- CurFunctionDeclToDeclareForBlock = 0;
- GlobalVarDecl = 0;
- SuperStructDecl = 0;
- ProtocolTypeDecl = 0;
- ConstantStringDecl = 0;
+ MsgSendFunctionDecl = nullptr;
+ MsgSendSuperFunctionDecl = nullptr;
+ MsgSendStretFunctionDecl = nullptr;
+ MsgSendSuperStretFunctionDecl = nullptr;
+ MsgSendFpretFunctionDecl = nullptr;
+ GetClassFunctionDecl = nullptr;
+ GetMetaClassFunctionDecl = nullptr;
+ GetSuperClassFunctionDecl = nullptr;
+ SelGetUidFunctionDecl = nullptr;
+ CFStringFunctionDecl = nullptr;
+ ConstantStringClassReference = nullptr;
+ NSStringRecord = nullptr;
+ CurMethodDef = nullptr;
+ CurFunctionDef = nullptr;
+ CurFunctionDeclToDeclareForBlock = nullptr;
+ GlobalVarDecl = nullptr;
+ SuperStructDecl = nullptr;
+ ProtocolTypeDecl = nullptr;
+ ConstantStringDecl = nullptr;
BcLabelCount = 0;
- SuperConstructorFunctionDecl = 0;
+ SuperConstructorFunctionDecl = nullptr;
NumObjCStringLiterals = 0;
- PropParentMap = 0;
- CurrentBody = 0;
+ PropParentMap = nullptr;
+ CurrentBody = nullptr;
DisableReplaceStmt = false;
objc_impl_method = false;
@@ -814,7 +814,7 @@
if (GenGetProperty) {
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
Getr += "typedef ";
- const FunctionType *FPRetType = 0;
+ const FunctionType *FPRetType = nullptr;
RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr,
FPRetType);
Getr += " _TYPE";
@@ -1068,7 +1068,7 @@
ObjCMethodDecl *OMD,
std::string &ResultStr) {
//fprintf(stderr,"In RewriteObjCMethodDecl\n");
- const FunctionType *FPRetType = 0;
+ const FunctionType *FPRetType = nullptr;
ResultStr += "\nstatic ";
RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);
ResultStr += " ";
@@ -1246,7 +1246,7 @@
DisableReplaceStmtScope S(*this);
// Rebuild the base expression if we have one.
- Base = 0;
+ Base = nullptr;
if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
Base = OldMsg->getInstanceReceiver();
Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
@@ -1263,7 +1263,7 @@
SmallVector<SourceLocation, 1> SelLocs;
OldMsg->getSelectorLocs(SelLocs);
- ObjCMessageExpr *NewMsg = 0;
+ ObjCMessageExpr *NewMsg = nullptr;
switch (OldMsg->getReceiverKind()) {
case ObjCMessageExpr::Class:
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
@@ -1323,7 +1323,7 @@
// Because the rewriter doesn't allow us to rewrite rewritten code,
// we need to suppress rewriting the sub-statements.
- Expr *Base = 0;
+ Expr *Base = nullptr;
{
DisableReplaceStmtScope S(*this);
@@ -1339,7 +1339,7 @@
SmallVector<SourceLocation, 1> SelLocs;
SmallVector<Expr*, 1> Args;
- ObjCMessageExpr *NewMsg = 0;
+ ObjCMessageExpr *NewMsg = nullptr;
switch (OldMsg->getReceiverKind()) {
case ObjCMessageExpr::Class:
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
@@ -1423,7 +1423,7 @@
buf += utostr(ObjCBcLabelNo.back());
ReplaceText(startLoc, strlen("break"), buf);
- return 0;
+ return nullptr;
}
/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
@@ -1440,7 +1440,7 @@
buf += utostr(ObjCBcLabelNo.back());
ReplaceText(startLoc, strlen("continue"), buf);
- return 0;
+ return nullptr;
}
/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
@@ -1636,7 +1636,7 @@
}
Stmts.pop_back();
ObjCBcLabelNo.pop_back();
- return 0;
+ return nullptr;
}
/// RewriteObjCSynchronizedStmt -
@@ -1697,7 +1697,7 @@
CK, syncExpr);
std::string syncExprBufS;
llvm::raw_string_ostream syncExprBuf(syncExprBufS);
- syncExpr->printPretty(syncExprBuf, 0, PrintingPolicy(LangOpts));
+ syncExpr->printPretty(syncExprBuf, nullptr, PrintingPolicy(LangOpts));
syncBuf += syncExprBuf.str();
syncBuf += ");";
@@ -1713,7 +1713,7 @@
if (hasReturns)
RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
- return 0;
+ return nullptr;
}
void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
@@ -1830,7 +1830,7 @@
buf += "}";
ReplaceText(lastCurlyLoc, 1, buf);
}
- Stmt *lastCatchBody = 0;
+ Stmt *lastCatchBody = nullptr;
for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
VarDecl *catchDecl = Catch->getCatchParamDecl();
@@ -1952,7 +1952,7 @@
// Now emit the final closing curly brace...
lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1);
InsertText(lastCurlyLoc, " } /* @try scope end */\n");
- return 0;
+ return nullptr;
}
// This can't be done with ReplaceStmt(S, ThrowExpr), since
@@ -1981,7 +1981,7 @@
assert((*semiBuf == ';') && "@throw: can't find ';'");
SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
ReplaceText(semiLoc, 1, ");");
- return 0;
+ return nullptr;
}
Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
@@ -2022,9 +2022,9 @@
// Now, we cast the reference to a pointer to the objc_msgSend type.
QualType pToFunc = Context->getPointerType(msgSendType);
- ImplicitCastExpr *ICE =
+ ImplicitCastExpr *ICE =
ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
- DRE, 0, VK_RValue);
+ DRE, nullptr, VK_RValue);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
@@ -2100,7 +2100,7 @@
const char *startBuf = SM->getCharacterData(Loc);
const char *endBuf = SM->getCharacterData(EndLoc);
- const char *startRef = 0, *endRef = 0;
+ const char *startRef = nullptr, *endRef = nullptr;
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
// Get the locations of the startRef, endRef.
SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
@@ -2115,7 +2115,7 @@
void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
SourceLocation Loc;
QualType Type;
- const FunctionProtoType *proto = 0;
+ const FunctionProtoType *proto = nullptr;
if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
Loc = VD->getLocation();
Type = VD->getType();
@@ -2145,7 +2145,7 @@
const char *startBuf = endBuf;
while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
startBuf--; // scan backward (from the decl location) for return type.
- const char *startRef = 0, *endRef = 0;
+ const char *startRef = nullptr, *endRef = nullptr;
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
// Get the locations of the startRef, endRef.
SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
@@ -2167,7 +2167,7 @@
const char *endBuf = startBuf;
// scan forward (from the decl location) for argument types.
scanToNextArgument(endBuf);
- const char *startRef = 0, *endRef = 0;
+ const char *startRef = nullptr, *endRef = nullptr;
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
// Get the locations of the startRef, endRef.
SourceLocation LessLoc =
@@ -2236,8 +2236,8 @@
SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- SelGetUidIdent, getFuncType, 0,
- SC_Extern);
+ SelGetUidIdent, getFuncType,
+ nullptr, SC_Extern);
}
void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
@@ -2314,7 +2314,7 @@
}
FdStr += ");\n";
InsertText(FunLocStart, FdStr);
- CurFunctionDeclToDeclareForBlock = 0;
+ CurFunctionDeclToDeclareForBlock = nullptr;
}
// SynthSuperConstructorFunctionDecl - id objc_super(id obj, id super);
@@ -2333,7 +2333,7 @@
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType,
- 0, SC_Extern);
+ nullptr, SC_Extern);
}
// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
@@ -2351,8 +2351,8 @@
MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- msgSendIdent, msgSendType, 0,
- SC_Extern);
+ msgSendIdent, msgSendType,
+ nullptr, SC_Extern);
}
// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
@@ -2373,8 +2373,8 @@
MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- msgSendIdent, msgSendType, 0,
- SC_Extern);
+ msgSendIdent, msgSendType,
+ nullptr, SC_Extern);
}
// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
@@ -2392,8 +2392,8 @@
MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- msgSendIdent, msgSendType, 0,
- SC_Extern);
+ msgSendIdent, msgSendType,
+ nullptr, SC_Extern);
}
// SynthMsgSendSuperStretFunctionDecl -
@@ -2417,7 +2417,7 @@
SourceLocation(),
SourceLocation(),
msgSendIdent,
- msgSendType, 0,
+ msgSendType, nullptr,
SC_Extern);
}
@@ -2436,8 +2436,8 @@
MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- msgSendIdent, msgSendType, 0,
- SC_Extern);
+ msgSendIdent, msgSendType,
+ nullptr, SC_Extern);
}
// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
@@ -2450,8 +2450,8 @@
GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SourceLocation(),
- getClassIdent, getClassType, 0,
- SC_Extern);
+ getClassIdent, getClassType,
+ nullptr, SC_Extern);
}
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
@@ -2466,7 +2466,7 @@
SourceLocation(),
SourceLocation(),
getSuperClassIdent,
- getClassType, 0,
+ getClassType, nullptr,
SC_Extern);
}
@@ -2481,7 +2481,7 @@
SourceLocation(),
SourceLocation(),
getClassIdent, getClassType,
- 0, SC_Extern);
+ nullptr, SC_Extern);
}
Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
@@ -2507,14 +2507,14 @@
// The pretty printer for StringLiteral handles escape characters properly.
std::string prettyBufS;
llvm::raw_string_ostream prettyBuf(prettyBufS);
- Exp->getString()->printPretty(prettyBuf, 0, PrintingPolicy(LangOpts));
+ Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));
Preamble += prettyBuf.str();
Preamble += ",";
Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(S),
- strType, 0, SC_Static);
+ strType, nullptr, SC_Static);
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue,
SourceLocation());
Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
@@ -2546,9 +2546,9 @@
for (unsigned i = 0; i < 2; ++i) {
SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], 0,
- /*BitWidth=*/0,
+ SourceLocation(), nullptr,
+ FieldTypes[i], nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false,
ICIS_NoInit));
}
@@ -2579,9 +2579,9 @@
ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
ConstantStringDecl,
SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], 0,
- /*BitWidth=*/0,
+ SourceLocation(), nullptr,
+ FieldTypes[i], nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/true,
ICIS_NoInit));
}
@@ -2649,7 +2649,7 @@
// default to objc_msgSend().
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
// May need to use objc_msgSend_stret() as well.
- FunctionDecl *MsgSendStretFlavor = 0;
+ FunctionDecl *MsgSendStretFlavor = nullptr;
if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
QualType resultType = mDecl->getReturnType();
if (resultType->isRecordType())
@@ -3062,8 +3062,8 @@
std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();
IdentifierInfo *ID = &Context->Idents.get(Name);
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
- SourceLocation(), ID, getProtocolType(), 0,
- SC_Extern);
+ SourceLocation(), ID, getProtocolType(),
+ nullptr, SC_Extern);
DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(),
VK_LValue, SourceLocation());
Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
@@ -3758,7 +3758,7 @@
Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
// Navigate to relevant type information.
- const BlockPointerType *CPT = 0;
+ const BlockPointerType *CPT = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
CPT = DRE->getType()->getAs<BlockPointerType>();
@@ -3829,11 +3829,11 @@
BlkCast);
//PE->dump();
- FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("FuncPtr"),
- Context->VoidPtrTy, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
FD->getType(), VK_LValue,
@@ -3876,12 +3876,12 @@
// for each DeclRefExp where BYREFVAR is name of the variable.
ValueDecl *VD = DeclRefExp->getDecl();
bool isArrow = DeclRefExp->refersToEnclosingLocal();
-
- FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+
+ FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
&Context->Idents.get("__forwarding"),
- Context->VoidPtrTy, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
FD, SourceLocation(),
@@ -3889,10 +3889,10 @@
OK_Ordinary);
StringRef Name = VD->getName();
- FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(),
+ FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
&Context->Idents.get(Name),
- Context->VoidPtrTy, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
+ Context->VoidPtrTy, nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
DeclRefExp->getType(), VK_LValue, OK_Ordinary);
@@ -4283,7 +4283,7 @@
// struct __Block_byref_ND ND =
// {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
// initializer-if-any};
- bool hasInit = (ND->getInit() != 0);
+ bool hasInit = (ND->getInit() != nullptr);
unsigned flags = 0;
if (HasCopyAndDispose)
flags |= BLOCK_HAS_COPY_DISPOSE;
@@ -4394,7 +4394,7 @@
IdentifierInfo *ID = &Context->Idents.get(name);
QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
- SourceLocation(), ID, FType, 0, SC_Extern,
+ SourceLocation(), ID, FType, nullptr, SC_Extern,
false, false);
}
@@ -4478,7 +4478,7 @@
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
SourceLocation(), SourceLocation(),
&Context->Idents.get(DescData.c_str()),
- Context->VoidPtrTy, 0,
+ Context->VoidPtrTy, nullptr,
SC_Static);
UnaryOperator *DescRefExpr =
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
@@ -4646,7 +4646,7 @@
// Rewrite the block body in place.
Stmt *SaveCurrentBody = CurrentBody;
CurrentBody = BE->getBody();
- PropParentMap = 0;
+ PropParentMap = nullptr;
// block literal on rhs of a property-dot-sytax assignment
// must be replaced by its synthesize ast so getRewrittenText
// works as expected. In this case, what actually ends up on RHS
@@ -4657,7 +4657,7 @@
RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
DisableReplaceStmt = saveDisableReplaceStmt;
CurrentBody = SaveCurrentBody;
- PropParentMap = 0;
+ PropParentMap = nullptr;
ImportedLocalExternalDecls.clear();
// Now we snarf the rewritten text and stash it away for later use.
std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
@@ -4854,16 +4854,16 @@
Body =
cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
FD->setBody(Body);
- CurrentBody = 0;
+ CurrentBody = nullptr;
if (PropParentMap) {
delete PropParentMap;
- PropParentMap = 0;
+ PropParentMap = nullptr;
}
// This synthesizes and inserts the block "impl" struct, invoke function,
// and any copy/dispose helper functions.
InsertBlockLiteralsWithinFunction(FD);
- CurFunctionDef = 0;
- CurFunctionDeclToDeclareForBlock = 0;
+ CurFunctionDef = nullptr;
+ CurFunctionDeclToDeclareForBlock = nullptr;
}
break;
}
@@ -4875,13 +4875,13 @@
Body =
cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
MD->setBody(Body);
- CurrentBody = 0;
+ CurrentBody = nullptr;
if (PropParentMap) {
delete PropParentMap;
- PropParentMap = 0;
+ PropParentMap = nullptr;
}
InsertBlockLiteralsWithinMethod(MD);
- CurMethodDef = 0;
+ CurMethodDef = nullptr;
}
break;
}
@@ -4916,14 +4916,14 @@
GlobalVarDecl = VD;
CurrentBody = VD->getInit();
RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
- CurrentBody = 0;
+ CurrentBody = nullptr;
if (PropParentMap) {
delete PropParentMap;
- PropParentMap = 0;
+ PropParentMap = nullptr;
}
SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
- GlobalVarDecl = 0;
-
+ GlobalVarDecl = nullptr;
+
// This is needed for blocks.
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
RewriteCastExpr(CE);
@@ -5473,7 +5473,7 @@
}
// Meta-class metadata generation.
- ObjCInterfaceDecl *RootClass = 0;
+ ObjCInterfaceDecl *RootClass = nullptr;
ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
while (SuperClass) {
RootClass = SuperClass;
@@ -5872,7 +5872,7 @@
dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
// lookup which class implements the instance variable.
- ObjCInterfaceDecl *clsDeclared = 0;
+ ObjCInterfaceDecl *clsDeclared = nullptr;
iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
clsDeclared);
assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
@@ -5913,7 +5913,7 @@
const ObjCInterfaceType *iFaceDecl =
dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
// lookup which class implements the instance variable.
- ObjCInterfaceDecl *clsDeclared = 0;
+ ObjCInterfaceDecl *clsDeclared = nullptr;
iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
clsDeclared);
assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 3e40485..7f2748e 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -89,8 +89,8 @@
SourceLocation Open = SilenceableCondVal.getBegin();
if (Open.isValid()) {
- SourceLocation Close = SilenceableCondVal.getEnd();
- Close = S.PP.getLocForEndOfToken(Close);
+ SourceLocation Close = SilenceableCondVal.getEnd();
+ Close = S.getLocForEndOfToken(Close);
if (Close.isValid()) {
S.Diag(Open, diag::note_unreachable_silence)
<< FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (")
@@ -117,6 +117,47 @@
reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC);
}
+/// \brief Warn on logical operator errors in CFGBuilder
+class LogicalErrorHandler : public CFGCallback {
+ Sema &S;
+
+public:
+ LogicalErrorHandler(Sema &S) : CFGCallback(), S(S) {}
+
+ static bool HasMacroID(const Expr *E) {
+ if (E->getExprLoc().isMacroID())
+ return true;
+
+ // Recurse to children.
+ for (ConstStmtRange SubStmts = E->children(); SubStmts; ++SubStmts)
+ if (*SubStmts)
+ if (const Expr *SubExpr = dyn_cast<Expr>(*SubStmts))
+ if (HasMacroID(SubExpr))
+ return true;
+
+ return false;
+ }
+
+ void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {
+ if (HasMacroID(B))
+ return;
+
+ SourceRange DiagRange = B->getSourceRange();
+ S.Diag(B->getExprLoc(), diag::warn_tautological_overlap_comparison)
+ << DiagRange << isAlwaysTrue;
+ }
+
+ void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue) {
+ if (HasMacroID(B))
+ return;
+
+ SourceRange DiagRange = B->getSourceRange();
+ S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always)
+ << DiagRange << isAlwaysTrue;
+ }
+};
+
+
//===----------------------------------------------------------------------===//
// Check for infinite self-recursion in functions
//===----------------------------------------------------------------------===//
@@ -149,11 +190,11 @@
// If the current state is FoundPathWithNoRecursiveCall, the successors
// will be either FoundPathWithNoRecursiveCall or FoundPath. To determine
// which, process all the Stmt's in this block to find any recursive calls.
- for (CFGBlock::iterator I = Block.begin(), E = Block.end(); I != E; ++I) {
- if (I->getKind() != CFGElement::Statement)
+ for (const auto &B : Block) {
+ if (B.getKind() != CFGElement::Statement)
continue;
- const CallExpr *CE = dyn_cast<CallExpr>(I->getAs<CFGStmt>()->getStmt());
+ const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
if (CE && CE->getCalleeDecl() &&
CE->getCalleeDecl()->getCanonicalDecl() == FD) {
@@ -200,7 +241,7 @@
return;
CFG *cfg = AC.getCFG();
- if (cfg == 0) return;
+ if (!cfg) return;
// If the exit block is unreachable, skip processing the function.
if (cfg->getExit().pred_empty())
@@ -241,7 +282,7 @@
/// will return.
static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
CFG *cfg = AC.getCFG();
- if (cfg == 0) return UnknownFallThrough;
+ if (!cfg) return UnknownFallThrough;
// The CFG leaves in dead things, and we don't want the dead code paths to
// confuse us, so we mark all live things first.
@@ -254,14 +295,13 @@
// When there are things remaining dead, and we didn't add EH edges
// from CallExprs to the catch clauses, we have to go back and
// mark them as live.
- for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
- CFGBlock &b = **I;
- if (!live[b.getBlockID()]) {
- if (b.pred_begin() == b.pred_end()) {
- if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
+ for (const auto *B : *cfg) {
+ if (!live[B->getBlockID()]) {
+ if (B->pred_begin() == B->pred_end()) {
+ if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator()))
// When not adding EH edges from calls, catch clauses
// can otherwise seem dead. Avoid noting them as dead.
- count += reachable_code::ScanReachableFromBlock(&b, live);
+ count += reachable_code::ScanReachableFromBlock(B, live);
continue;
}
}
@@ -413,8 +453,7 @@
diag::err_noreturn_block_has_return_expr;
D.diag_AlwaysFallThrough_ReturnsNonVoid =
diag::err_falloff_nonvoid_block;
- D.diag_NeverFallThroughOrReturn =
- diag::warn_suggest_noreturn_block;
+ D.diag_NeverFallThroughOrReturn = 0;
D.funMode = Block;
return D;
}
@@ -449,10 +488,7 @@
}
// For blocks / lambdas.
- return ReturnsVoid && !HasNoReturn
- && ((funMode == Lambda) ||
- D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
- == DiagnosticsEngine::Ignored);
+ return ReturnsVoid && !HasNoReturn;
}
};
@@ -589,7 +625,7 @@
if (VD->getLocEnd().isMacroID())
return false;
- SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
+ SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
// Suggest possible initialization (if any).
std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
@@ -885,8 +921,7 @@
// constants, covered enums, etc.
// These blocks can contain fall-through annotations, and we don't want to
// issue a warn_fallthrough_attr_unreachable for them.
- for (CFG::iterator I = Cfg->begin(), E = Cfg->end(); I != E; ++I) {
- const CFGBlock *B = *I;
+ for (const auto *B : *Cfg) {
const Stmt *L = B->getLabel();
if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B))
BlockQueue.push_back(B);
@@ -910,10 +945,7 @@
int UnannotatedCnt = 0;
AnnotatedCnt = 0;
- std::deque<const CFGBlock*> BlockQueue;
-
- std::copy(B.pred_begin(), B.pred_end(), std::back_inserter(BlockQueue));
-
+ std::deque<const CFGBlock*> BlockQueue(B.pred_begin(), B.pred_end());
while (!BlockQueue.empty()) {
const CFGBlock *P = BlockQueue.front();
BlockQueue.pop_front();
@@ -1001,7 +1033,7 @@
if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
return AS;
}
- return 0;
+ return nullptr;
}
static const Stmt *getLastStmt(const CFGBlock &B) {
@@ -1020,7 +1052,7 @@
if (!isa<SwitchCase>(SW->getSubStmt()))
return SW->getSubStmt();
- return 0;
+ return nullptr;
}
bool FoundSwitchStatements;
@@ -1110,13 +1142,8 @@
}
}
- const FallthroughMapper::AttrStmts &Fallthroughs = FM.getFallthroughStmts();
- for (FallthroughMapper::AttrStmts::const_iterator I = Fallthroughs.begin(),
- E = Fallthroughs.end();
- I != E; ++I) {
- S.Diag((*I)->getLocStart(), diag::warn_fallthrough_attr_invalid_placement);
- }
-
+ for (const auto *F : FM.getFallthroughStmts())
+ S.Diag(F->getLocStart(), diag::warn_fallthrough_attr_invalid_placement);
}
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
@@ -1242,12 +1269,10 @@
FunctionKind = Function;
// Iterate through the sorted problems and emit warnings for each.
- for (SmallVectorImpl<StmtUsesPair>::const_iterator I = UsesByStmt.begin(),
- E = UsesByStmt.end();
- I != E; ++I) {
- const Stmt *FirstRead = I->first;
- const WeakObjectProfileTy &Key = I->second->first;
- const WeakUseVector &Uses = I->second->second;
+ for (const auto &P : UsesByStmt) {
+ const Stmt *FirstRead = P.first;
+ const WeakObjectProfileTy &Key = P.second->first;
+ const WeakUseVector &Uses = P.second->second;
// For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy
// may not contain enough information to determine that these are different
@@ -1288,13 +1313,12 @@
<< FirstRead->getSourceRange();
// Print all the other accesses as notes.
- for (WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
- UI != UE; ++UI) {
- if (UI->getUseExpr() == FirstRead)
+ for (const auto &Use : Uses) {
+ if (Use.getUseExpr() == FirstRead)
continue;
- S.Diag(UI->getUseExpr()->getLocStart(),
+ S.Diag(Use.getUseExpr()->getLocStart(),
diag::note_arc_weak_also_accessed_here)
- << UI->getUseExpr()->getSourceRange();
+ << Use.getUseExpr()->getSourceRange();
}
}
}
@@ -1311,7 +1335,7 @@
UsesMap *uses;
public:
- UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
+ UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {}
~UninitValsDiagReporter() {
flushDiagnostics();
}
@@ -1340,9 +1364,9 @@
if (!uses)
return;
- for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
- const VarDecl *vd = i->first;
- const MappedType &V = i->second;
+ for (const auto &P : *uses) {
+ const VarDecl *vd = P.first;
+ const MappedType &V = P.second;
UsesVec *vec = V.getPointer();
bool hasSelfInit = V.getInt();
@@ -1367,10 +1391,9 @@
return a.getUser()->getLocStart() < b.getUser()->getLocStart();
});
- for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve;
- ++vi) {
+ for (const auto &U : *vec) {
// If we have self-init, downgrade all uses to 'may be uninitialized'.
- UninitUse Use = hasSelfInit ? UninitUse(vi->getUser(), false) : *vi;
+ UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
if (DiagnoseUninitializedUse(S, vd, Use))
// Skip further diagnostics for this variable. We try to warn only
@@ -1387,15 +1410,12 @@
private:
static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
- for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) {
- if (i->getKind() == UninitUse::Always ||
- i->getKind() == UninitUse::AfterCall ||
- i->getKind() == UninitUse::AfterDecl) {
- return true;
- }
+ return std::any_of(vec->begin(), vec->end(), [](const UninitUse &U) {
+ return U.getKind() == UninitUse::Always ||
+ U.getKind() == UninitUse::AfterCall ||
+ U.getKind() == UninitUse::AfterDecl;
+ });
}
- return false;
-}
};
}
@@ -1449,12 +1469,10 @@
/// and outputs them.
void emitDiagnostics() {
Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
- for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
- I != E; ++I) {
- S.Diag(I->first.first, I->first.second);
- const OptionalNotes &Notes = I->second;
- for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI)
- S.Diag(Notes[NoteI].first, Notes[NoteI].second);
+ for (const auto &Diag : Warnings) {
+ S.Diag(Diag.first.first, Diag.first.second);
+ for (const auto &Note : Diag.second)
+ S.Diag(Note.first, Note.second);
}
}
@@ -1609,16 +1627,10 @@
void emitDiagnostics() override {
Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
-
- for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
- I != E; ++I) {
-
- const OptionalNotes &Notes = I->second;
- S.Diag(I->first.first, I->first.second);
-
- for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) {
- S.Diag(Notes[NoteI].first, Notes[NoteI].second);
- }
+ for (const auto &Diag : Warnings) {
+ S.Diag(Diag.first.first, Diag.first.second);
+ for (const auto &Note : Diag.second)
+ S.Diag(Note.first, Note.second);
}
}
@@ -1733,14 +1745,9 @@
isEnabled(D, warn_use_in_invalid_state);
}
-static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
- for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = fscope->PossiblyUnreachableDiags.begin(),
- e = fscope->PossiblyUnreachableDiags.end();
- i != e; ++i) {
- const sema::PossiblyUnreachableDiag &D = *i;
+static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
+ for (const auto &D : fscope->PossiblyUnreachableDiags)
S.Diag(D.Loc, D.PD);
- }
}
void clang::sema::
@@ -1776,7 +1783,7 @@
assert(Body);
// Construct the analysis context with the specified CFG build options.
- AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D);
+ AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D);
// Don't generate EH edges for CallExprs as we'd like to avoid the n^2
// explosion for destructors that can result and the compile time hit.
@@ -1810,31 +1817,30 @@
.setAlwaysAdd(Stmt::AttributedStmtClass);
}
+ // Install the logical handler for -Wtautological-overlap-compare
+ std::unique_ptr<LogicalErrorHandler> LEH;
+ if (Diags.getDiagnosticLevel(diag::warn_tautological_overlap_comparison,
+ D->getLocStart())) {
+ LEH.reset(new LogicalErrorHandler(S));
+ AC.getCFGBuildOptions().Observer = LEH.get();
+ }
// Emit delayed diagnostics.
if (!fscope->PossiblyUnreachableDiags.empty()) {
bool analyzed = false;
// Register the expressions with the CFGBuilder.
- for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = fscope->PossiblyUnreachableDiags.begin(),
- e = fscope->PossiblyUnreachableDiags.end();
- i != e; ++i) {
- if (const Stmt *stmt = i->stmt)
- AC.registerForcedBlockExpression(stmt);
+ for (const auto &D : fscope->PossiblyUnreachableDiags) {
+ if (D.stmt)
+ AC.registerForcedBlockExpression(D.stmt);
}
if (AC.getCFG()) {
analyzed = true;
- for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = fscope->PossiblyUnreachableDiags.begin(),
- e = fscope->PossiblyUnreachableDiags.end();
- i != e; ++i)
- {
- const sema::PossiblyUnreachableDiag &D = *i;
+ for (const auto &D : fscope->PossiblyUnreachableDiags) {
bool processed = false;
- if (const Stmt *stmt = i->stmt) {
- const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
+ if (D.stmt) {
+ const CFGBlock *block = AC.getBlockForRegisteredExpression(D.stmt);
CFGReverseBlockReachabilityAnalysis *cra =
AC.getCFGReachablityAnalysis();
// FIXME: We should be able to assert that block is non-null, but
@@ -1956,6 +1962,13 @@
}
}
+ // If none of the previous checks caused a CFG build, trigger one here
+ // for -Wtautological-overlap-compare
+ if (Diags.getDiagnosticLevel(diag::warn_tautological_overlap_comparison,
+ D->getLocStart())) {
+ AC.getCFG();
+ }
+
// Collect statistics about the CFG if it was built.
if (S.CollectStats && AC.isCFGBuilt()) {
++NumFunctionsAnalyzed;
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 19be1cb..b2dc2d7 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -15,7 +15,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/STLExtras.h"
@@ -219,7 +218,7 @@
if (AnnotationNr < NumAnnotations)
return reinterpret_cast<const char * const*>(end())[AnnotationNr];
else
- return 0;
+ return nullptr;
}
@@ -248,8 +247,8 @@
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
if (C->Kind == CK_TypedText)
return C->Text;
-
- return 0;
+
+ return nullptr;
}
const char *CodeCompletionAllocator::CopyString(StringRef String) {
@@ -279,7 +278,7 @@
// If we already processed this DeclContext and assigned empty to it, the
// data pointer will be non-null.
- if (CachedParentName.data() != 0)
+ if (CachedParentName.data() != nullptr)
return StringRef();
// Find the interesting names.
@@ -406,7 +405,7 @@
else if (getKind() == CK_FunctionTemplate)
return FunctionTemplate->getTemplatedDecl();
else
- return 0;
+ return nullptr;
}
const FunctionType *
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 5c2006f..69415ce 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -1125,14 +1125,41 @@
ThreadHint = FixItHint::CreateRemoval(SCLoc);
}
- Diag(D, SCLoc, diag::err_friend_storage_spec)
+ Diag(D, SCLoc, diag::err_friend_decl_spec)
<< SpecName << StorageHint << ThreadHint;
ClearStorageClassSpecs();
}
+ // C++11 [dcl.fct.spec]p5:
+ // The virtual specifier shall be used only in the initial
+ // declaration of a non-static class member function;
+ // C++11 [dcl.fct.spec]p6:
+ // The explicit specifier shall be used only in the declaration of
+ // a constructor or conversion function within its class
+ // definition;
+ if (isFriendSpecified() && (isVirtualSpecified() || isExplicitSpecified())) {
+ StringRef Keyword;
+ SourceLocation SCLoc;
+
+ if (isVirtualSpecified()) {
+ Keyword = "virtual";
+ SCLoc = getVirtualSpecLoc();
+ } else {
+ Keyword = "explicit";
+ SCLoc = getExplicitSpecLoc();
+ }
+
+ FixItHint Hint = FixItHint::CreateRemoval(SCLoc);
+ Diag(D, SCLoc, diag::err_friend_decl_spec)
+ << Keyword << Hint;
+
+ FS_virtual_specified = FS_explicit_specified = false;
+ FS_virtualLoc = FS_explicitLoc = SourceLocation();
+ }
+
assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
-
+
// Okay, now we can infer the real type.
// TODO: return "auto function" and other bad things based on the real type.
diff --git a/lib/Sema/DelayedDiagnostic.cpp b/lib/Sema/DelayedDiagnostic.cpp
index 533b7ef..13a428c 100644
--- a/lib/Sema/DelayedDiagnostic.cpp
+++ b/lib/Sema/DelayedDiagnostic.cpp
@@ -40,7 +40,7 @@
DD.DeprecationData.Decl = D;
DD.DeprecationData.UnknownObjCClass = UnknownObjCClass;
DD.DeprecationData.ObjCProperty = ObjCProperty;
- char *MessageData = 0;
+ char *MessageData = nullptr;
if (Msg.size()) {
MessageData = new char [Msg.size()];
memcpy(MessageData, Msg.data(), Msg.size());
@@ -52,12 +52,13 @@
}
void DelayedDiagnostic::Destroy() {
- switch (Kind) {
+ switch (static_cast<DDKind>(Kind)) {
case Access:
getAccessData().~AccessedEntity();
break;
- case Deprecation:
+ case Deprecation:
+ case Unavailable:
delete [] DeprecationData.Message;
break;
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 705fb07..2a5bacf 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -45,7 +45,7 @@
unsigned int CurIndex;
public:
- IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {}
+ IdDeclInfoMap() : CurPool(nullptr), CurIndex(POOL_SIZE) {}
~IdDeclInfoMap() {
IdDeclInfoPool *Cur = CurPool;
@@ -151,7 +151,7 @@
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
- Name.setFETokenInfo(NULL);
+ Name.setFETokenInfo(nullptr);
IDI = &(*IdDeclInfos)[Name];
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
IDI->AddDecl(PrevD);
@@ -213,7 +213,7 @@
if (isDeclPtr(Ptr)) {
assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
- Name.setFETokenInfo(NULL);
+ Name.setFETokenInfo(nullptr);
return;
}
@@ -314,8 +314,8 @@
Name.setFETokenInfo(D);
return true;
}
-
- Name.setFETokenInfo(NULL);
+
+ Name.setFETokenInfo(nullptr);
IDI = &(*IdDeclInfos)[Name];
// If the existing declaration is not visible in translation unit scope,
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 1f5d682..f7d8788 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -32,6 +32,10 @@
class JumpScopeChecker {
Sema &S;
+ /// Permissive - True when recovering from errors, in which case precautions
+ /// are taken to handle incomplete scope information.
+ const bool Permissive;
+
/// GotoScope - This is a record that we use to keep track of all of the
/// scopes that are introduced by VLAs and other things that scope jumps like
/// gotos. This scope tree has nothing to do with the source scope tree,
@@ -85,8 +89,10 @@
};
} // end anonymous namespace
+#define CHECK_PERMISSIVE(x) (assert(Permissive || !(x)), (Permissive && (x)))
-JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
+JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s)
+ : S(s), Permissive(s.hasAnyUnrecoverableErrorsInThisFunction()) {
// Add a scope entry for function scope.
Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation()));
@@ -342,7 +348,7 @@
}
Stmt *SubStmt = *CI;
- if (SubStmt == 0) continue;
+ if (!SubStmt) continue;
// Cases, labels, and defaults aren't "scope parents". It's also
// important to handle these iteratively instead of recursively in
@@ -503,7 +509,8 @@
SwitchStmt *SS = cast<SwitchStmt>(Jump);
for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
- assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(SC)))
+ continue;
SourceLocation Loc;
if (CaseStmt *CS = dyn_cast<CaseStmt>(SC))
Loc = CS->getLocStart();
@@ -557,8 +564,8 @@
for (SmallVectorImpl<IndirectGotoStmt*>::iterator
I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) {
IndirectGotoStmt *IG = *I;
- assert(LabelAndGotoScopes.count(IG) &&
- "indirect jump didn't get added to scopes?");
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(IG)))
+ continue;
unsigned IGScope = LabelAndGotoScopes[IG];
IndirectGotoStmt *&Entry = JumpScopesMap[IGScope];
if (!Entry) Entry = IG;
@@ -577,8 +584,8 @@
I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end();
I != E; ++I) {
LabelDecl *TheLabel = *I;
- assert(LabelAndGotoScopes.count(TheLabel->getStmt()) &&
- "Referenced label didn't get added to scopes?");
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(TheLabel->getStmt())))
+ continue;
unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()];
LabelDecl *&Target = TargetScopes[LabelScope];
if (!Target) Target = TheLabel;
@@ -683,7 +690,8 @@
/// Produce note diagnostics for a jump into a protected scope.
void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes) {
- assert(!ToScopes.empty());
+ if (CHECK_PERMISSIVE(ToScopes.empty()))
+ return;
for (unsigned I = 0, E = ToScopes.size(); I != E; ++I)
if (Scopes[ToScopes[I]].InDiag)
S.Diag(Scopes[ToScopes[I]].Loc, Scopes[ToScopes[I]].InDiag);
@@ -694,7 +702,8 @@
unsigned JumpScope,
LabelDecl *Target,
unsigned TargetScope) {
- assert(JumpScope != TargetScope);
+ if (CHECK_PERMISSIVE(JumpScope == TargetScope))
+ return;
unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope);
bool Diagnosed = false;
@@ -731,10 +740,12 @@
void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
unsigned JumpDiagError, unsigned JumpDiagWarning,
unsigned JumpDiagCXX98Compat) {
- assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?");
- unsigned FromScope = LabelAndGotoScopes[From];
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(From)))
+ return;
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(To)))
+ return;
- assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?");
+ unsigned FromScope = LabelAndGotoScopes[From];
unsigned ToScope = LabelAndGotoScopes[To];
// Common case: exactly the same scope, which is fine.
diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index ad7627a..97237db 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -46,7 +46,12 @@
for(size_t i = 0; i < Sources.size(); ++i)
if (Decl *Result = Sources[i]->GetExternalDecl(ID))
return Result;
- return 0;
+ return nullptr;
+}
+
+void MultiplexExternalSemaSource::CompleteRedeclChain(const Decl *D) {
+ for (size_t i = 0; i < Sources.size(); ++i)
+ Sources[i]->CompleteRedeclChain(D);
}
Selector MultiplexExternalSemaSource::GetExternalSelector(uint32_t ID) {
@@ -70,7 +75,7 @@
for(size_t i = 0; i < Sources.size(); ++i)
if (Stmt *Result = Sources[i]->GetExternalDeclStmt(Offset))
return Result;
- return 0;
+ return nullptr;
}
CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers(
@@ -78,7 +83,7 @@
for(size_t i = 0; i < Sources.size(); ++i)
if (CXXBaseSpecifier *R = Sources[i]->GetExternalCXXBaseSpecifiers(Offset))
return R;
- return 0;
+ return nullptr;
}
bool MultiplexExternalSemaSource::
diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp
index 494768d..278b087 100644
--- a/lib/Sema/Scope.cpp
+++ b/lib/Sema/Scope.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/Scope.h"
+#include "clang/AST/Decl.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -27,7 +28,7 @@
} else {
// Control scopes do not contain the contents of nested function scopes for
// control flow purposes.
- BreakParent = ContinueParent = 0;
+ BreakParent = ContinueParent = nullptr;
}
if (parent) {
@@ -42,8 +43,8 @@
Depth = 0;
PrototypeDepth = 0;
PrototypeIndex = 0;
- MSLocalManglingParent = FnParent = BlockParent = 0;
- TemplateParamParent = 0;
+ MSLocalManglingParent = FnParent = BlockParent = nullptr;
+ TemplateParamParent = nullptr;
MSLocalManglingNumber = 1;
}
@@ -75,8 +76,9 @@
DeclsInScope.clear();
UsingDirectives.clear();
- Entity = 0;
+ Entity = nullptr;
ErrorTrap.reset();
+ NRVO.setPointerAndInt(nullptr, 0);
}
bool Scope::containedInPrototypeScope() const {
@@ -103,6 +105,21 @@
Flags |= FlagsToSet;
}
+void Scope::mergeNRVOIntoParent() {
+ if (VarDecl *Candidate = NRVO.getPointer()) {
+ if (isDeclScope(Candidate))
+ Candidate->setNRVOVariable(true);
+ }
+
+ if (getEntity())
+ return;
+
+ if (NRVO.getInt())
+ getParent()->setNoNRVO();
+ else if (NRVO.getPointer())
+ getParent()->addNRVOCandidate(NRVO.getPointer());
+}
+
void Scope::dump() const { dumpImpl(llvm::errs()); }
void Scope::dumpImpl(raw_ostream &OS) const {
@@ -176,4 +193,9 @@
OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
if (const DeclContext *DC = getEntity())
OS << "Entity : (clang::DeclContext*)" << DC << '\n';
+
+ if (NRVO.getInt())
+ OS << "NRVO not allowed";
+ else if (NRVO.getPointer())
+ OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
}
diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp
index 1e54c5a..d9b2ca3 100644
--- a/lib/Sema/ScopeInfo.cpp
+++ b/lib/Sema/ScopeInfo.cpp
@@ -51,7 +51,7 @@
FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
E = E->IgnoreParenCasts();
- const NamedDecl *D = 0;
+ const NamedDecl *D = nullptr;
bool IsExact = false;
switch (E->getStmtClass()) {
@@ -93,10 +93,9 @@
return BaseInfoTy(D, IsExact);
}
-
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
const ObjCPropertyRefExpr *PropE)
- : Base(0, true), Property(getBestPropertyDecl(PropE)) {
+ : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) {
if (PropE->isObjectReceiver()) {
const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase());
@@ -111,7 +110,7 @@
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
const ObjCPropertyDecl *Prop)
- : Base(0, true), Property(Prop) {
+ : Base(nullptr, true), Property(Prop) {
if (BaseE)
Base = getBaseInfo(BaseE);
// else, this is a message accessing a property on super.
@@ -119,7 +118,7 @@
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
const DeclRefExpr *DRE)
- : Base(0, true), Property(DRE->getDecl()) {
+ : Base(nullptr, true), Property(DRE->getDecl()) {
assert(isa<VarDecl>(Property));
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 3612bb9..e8b487e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
@@ -43,6 +44,12 @@
using namespace clang;
using namespace sema;
+SourceLocation Sema::getLocForEndOfToken(SourceLocation Loc, unsigned Offset) {
+ return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts);
+}
+
+ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
+
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Context.getPrintingPolicy();
@@ -69,39 +76,41 @@
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CodeCompleter)
- : ExternalSource(0),
+ : ExternalSource(nullptr),
isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()),
LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
CollectStats(false), CodeCompleter(CodeCompleter),
- CurContext(0), OriginalLexicalContext(0),
- PackContext(0), MSStructPragmaOn(false),
+ CurContext(nullptr), OriginalLexicalContext(nullptr),
+ PackContext(nullptr), MSStructPragmaOn(false),
MSPointerToMemberRepresentationMethod(
LangOpts.getMSPointerToMemberRepresentationMethod()),
VtorDispModeStack(1, MSVtorDispAttr::Mode(LangOpts.VtorDispMode)),
- VisContext(0),
+ DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
+ CodeSegStack(nullptr), VisContext(nullptr),
IsBuildingRecoveryCallExpr(false),
- ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
- IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
- NSNumberDecl(0),
- NSStringDecl(0), StringWithUTF8StringMethod(0),
- NSArrayDecl(0), ArrayWithObjectsMethod(0),
- NSDictionaryDecl(0), DictionaryWithObjectsMethod(0),
+ ExprNeedsCleanups(false), LateTemplateParser(nullptr),
+ OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
+ CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
+ NSNumberDecl(nullptr),
+ NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
+ NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr),
+ NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr),
GlobalNewDeleteDeclared(false),
TUKind(TUKind),
NumSFINAEErrors(0),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
- CurrentInstantiationScope(0), DisableTypoCorrection(false),
+ CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
TyposCorrected(0), AnalysisWarnings(*this),
- VarDataSharingAttributesStack(0), CurScope(0),
- Ident_super(0), Ident___float128(0)
+ VarDataSharingAttributesStack(nullptr), CurScope(nullptr),
+ Ident_super(nullptr), Ident___float128(nullptr)
{
- TUScope = 0;
+ TUScope = nullptr;
LoadedExternalKnownNamespaces = false;
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
- NSNumberLiteralMethods[I] = 0;
+ NSNumberLiteralMethods[I] = nullptr;
if (getLangOpts().ObjC1)
NSAPIObj.reset(new NSAPI(Context));
@@ -115,7 +124,7 @@
ExprEvalContexts.push_back(
ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0,
- false, 0, false));
+ false, nullptr, false));
FunctionScopes.push_back(new FunctionScopeInfo(Diags));
@@ -143,7 +152,7 @@
ExternalSema->InitializeSema(*this);
// Initialize predefined 128-bit integer types, if needed.
- if (PP.getTargetInfo().hasInt128Type()) {
+ if (Context.getTargetInfo().hasInt128Type()) {
// If either of the 128-bit integer types are unavailable to name lookup,
// define them now.
DeclarationName Int128 = &Context.Idents.get("__int128_t");
@@ -470,6 +479,13 @@
I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
NamedDecl *ND = I->first;
+ if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
+ // An exported function will always be emitted when defined, so even if
+ // the function is inline, it doesn't have to be emitted in this TU. An
+ // imported function implies that it has been exported somewhere else.
+ continue;
+ }
+
if (!ND->isExternallyVisible()) {
S.Diag(ND->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(ND) << ND;
@@ -578,7 +594,7 @@
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
- assert(DelayedDiagnostics.getCurrentPool() == NULL
+ assert(DelayedDiagnostics.getCurrentPool() == nullptr
&& "reached end of translation unit with a pool attached?");
// If code completion is enabled, don't perform any end-of-translation-unit
@@ -599,8 +615,9 @@
I != E; ++I) {
assert(!(*I)->isDependentType() &&
"Should not see dependent types here!");
- if (const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(*I)) {
- const FunctionDecl *Definition = 0;
+ if (const CXXMethodDecl *KeyFunction =
+ Context.getCurrentKeyFunction(*I)) {
+ const FunctionDecl *Definition = nullptr;
if (KeyFunction->hasBody(Definition))
MarkVTableUsed(Definition->getLocation(), *I, true);
}
@@ -639,14 +656,14 @@
// Remove file scoped decls that turned out to be used.
UnusedFileScopedDecls.erase(
- std::remove_if(UnusedFileScopedDecls.begin(0, true),
+ std::remove_if(UnusedFileScopedDecls.begin(nullptr, true),
UnusedFileScopedDecls.end(),
std::bind1st(std::ptr_fun(ShouldRemoveFromUnused), this)),
UnusedFileScopedDecls.end());
if (TUKind == TU_Prefix) {
// Translation unit prefixes don't need any of the checking below.
- TUScope = 0;
+ TUScope = nullptr;
return;
}
@@ -698,7 +715,7 @@
}
// Modules don't need any of the checking below.
- TUScope = 0;
+ TUScope = nullptr;
return;
}
@@ -724,7 +741,7 @@
// If the tentative definition was completed, getActingDefinition() returns
// null. If we've already seen this variable before, insert()'s second
// return value is false.
- if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
+ if (!VD || VD->isInvalidDecl() || !Seen.insert(VD))
continue;
if (const IncompleteArrayType *ArrayT
@@ -829,7 +846,7 @@
assert(ParsingInitForAutoVars.empty() &&
"Didn't unmark var as having its initializer parsed");
- TUScope = 0;
+ TUScope = nullptr;
}
@@ -873,7 +890,7 @@
DeclContext *DC = getFunctionLevelDeclContext();
if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
return cast<NamedDecl>(DC);
- return 0;
+ return nullptr;
}
void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
@@ -1021,7 +1038,7 @@
Scope *Sema::getScopeForContext(DeclContext *Ctx) {
if (!Ctx)
- return 0;
+ return nullptr;
Ctx = Ctx->getPrimaryContext();
for (Scope *S = getCurScope(); S; S = S->getParent()) {
@@ -1033,7 +1050,7 @@
return S;
}
- return 0;
+ return nullptr;
}
/// \brief Enter a new function scope
@@ -1077,19 +1094,12 @@
// Issue any analysis-based warnings.
if (WP && D)
AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr);
- else {
- for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = Scope->PossiblyUnreachableDiags.begin(),
- e = Scope->PossiblyUnreachableDiags.end();
- i != e; ++i) {
- const sema::PossiblyUnreachableDiag &D = *i;
- Diag(D.Loc, D.PD);
- }
- }
+ else
+ for (const auto &PUD : Scope->PossiblyUnreachableDiags)
+ Diag(PUD.Loc, PUD.PD);
- if (FunctionScopes.back() != Scope) {
+ if (FunctionScopes.back() != Scope)
delete Scope;
- }
}
void Sema::PushCompoundScope() {
@@ -1111,25 +1121,41 @@
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
- return 0;
+ return nullptr;
- return dyn_cast<BlockScopeInfo>(FunctionScopes.back());
+ auto CurBSI = dyn_cast<BlockScopeInfo>(FunctionScopes.back());
+ if (CurBSI && CurBSI->TheDecl &&
+ !CurBSI->TheDecl->Encloses(CurContext)) {
+ // We have switched contexts due to template instantiation.
+ assert(!ActiveTemplateInstantiations.empty());
+ return nullptr;
+ }
+
+ return CurBSI;
}
LambdaScopeInfo *Sema::getCurLambda() {
if (FunctionScopes.empty())
- return 0;
+ return nullptr;
- return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+ auto CurLSI = dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+ if (CurLSI && CurLSI->Lambda &&
+ !CurLSI->Lambda->Encloses(CurContext)) {
+ // We have switched contexts due to template instantiation.
+ assert(!ActiveTemplateInstantiations.empty());
+ return nullptr;
+ }
+
+ return CurLSI;
}
// We have a generic lambda if we parsed auto parameters, or we have
// an associated template parameter list.
LambdaScopeInfo *Sema::getCurGenericLambda() {
if (LambdaScopeInfo *LSI = getCurLambda()) {
return (LSI->AutoTemplateParams.size() ||
- LSI->GLTemplateParameterList) ? LSI : 0;
+ LSI->GLTemplateParameterList) ? LSI : nullptr;
}
- return 0;
+ return nullptr;
}
@@ -1207,7 +1233,7 @@
ZeroArgCallReturnTy = QualType();
OverloadSet.clear();
- const OverloadExpr *Overloads = NULL;
+ const OverloadExpr *Overloads = nullptr;
bool IsMemExpr = false;
if (E.getType() == Context.OverloadTy) {
OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E));
@@ -1256,8 +1282,8 @@
if (IsMemExpr && !E.isTypeDependent()) {
bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
getDiagnostics().setSuppressAllDiagnostics(true);
- ExprResult R = BuildCallToMemberFunction(NULL, &E, SourceLocation(), None,
- SourceLocation());
+ ExprResult R = BuildCallToMemberFunction(nullptr, &E, SourceLocation(),
+ None, SourceLocation());
getDiagnostics().setSuppressAllDiagnostics(Suppress);
if (R.isUsable()) {
ZeroArgCallReturnTy = R.get()->getType();
@@ -1277,7 +1303,7 @@
// We don't have an expression that's convenient to get a FunctionDecl from,
// but we can at least check if the type is "function of 0 arguments".
QualType ExprTy = E.getType();
- const FunctionType *FunTy = NULL;
+ const FunctionType *FunTy = nullptr;
QualType PointeeTy = ExprTy->getPointeeType();
if (!PointeeTy.isNull())
FunTy = PointeeTy->getAs<FunctionType>();
@@ -1382,7 +1408,7 @@
// FIXME: Try this before emitting the fixit, and suppress diagnostics
// while doing so.
- E = ActOnCallExpr(0, E.take(), Range.getEnd(), None,
+ E = ActOnCallExpr(nullptr, E.take(), Range.getEnd(), None,
Range.getEnd().getLocWithOffset(1));
return true;
}
@@ -1417,7 +1443,7 @@
CapturedRegionScopeInfo *Sema::getCurCapturedRegion() {
if (FunctionScopes.empty())
- return 0;
+ return nullptr;
return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back());
}
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index f7806d2..dc574f1 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -78,7 +78,7 @@
namespace {
struct EffectiveContext {
- EffectiveContext() : Inner(0), Dependent(false) {}
+ EffectiveContext() : Inner(nullptr), Dependent(false) {}
explicit EffectiveContext(DeclContext *DC)
: Inner(DC),
@@ -209,7 +209,8 @@
CalculatedInstanceContext = true;
DeclContext *IC = S.computeDeclContext(getBaseObjectType());
- InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
+ InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl()
+ : nullptr);
return InstanceContext;
}
@@ -232,7 +233,7 @@
!getBaseObjectType().isNull() &&
getTargetDecl()->isCXXInstanceMember());
CalculatedInstanceContext = false;
- InstanceContext = 0;
+ InstanceContext = nullptr;
if (isMemberAccess())
DeclaringClass = FindDeclaringClass(getTargetDecl());
@@ -709,7 +710,7 @@
static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
const CXXRecordDecl *InstanceContext,
const CXXRecordDecl *NamingClass) {
- assert(InstanceContext == 0 ||
+ assert(InstanceContext == nullptr ||
InstanceContext->getCanonicalDecl() == InstanceContext);
assert(NamingClass->getCanonicalDecl() == NamingClass);
@@ -842,7 +843,7 @@
// and instead rely on whether any potential P is a friend.
if (Access == AS_protected && Target.isInstanceMember()) {
// Compute the instance context if possible.
- const CXXRecordDecl *InstanceContext = 0;
+ const CXXRecordDecl *InstanceContext = nullptr;
if (Target.hasInstanceContext()) {
InstanceContext = Target.resolveInstanceContext(S);
if (!InstanceContext) return AR_dependent;
@@ -937,7 +938,7 @@
assert(isDerived && "derived class not actually derived from base");
(void) isDerived;
- CXXBasePath *BestPath = 0;
+ CXXBasePath *BestPath = nullptr;
assert(FinalAccess != AS_none && "forbidden access after declaring class");
@@ -986,7 +987,7 @@
// Note that we modify the path's Access field to the
// friend-modified access.
- if (BestPath == 0 || PathAccess < BestPath->Access) {
+ if (BestPath == nullptr || PathAccess < BestPath->Access) {
BestPath = &*PI;
BestPath->Access = PathAccess;
@@ -1004,7 +1005,7 @@
// We didn't find a public path, but at least one path was subject
// to dependent friendship, so delay the check.
if (AnyDependent)
- return 0;
+ return nullptr;
return BestPath;
}
@@ -1101,7 +1102,7 @@
// Find an original declaration.
while (D->isOutOfLine()) {
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
if (VarDecl *VD = dyn_cast<VarDecl>(D))
PrevDecl = VD->getPreviousDecl();
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
@@ -1212,7 +1213,7 @@
case AR_accessible:
accessSoFar = AS_public;
entity.suppressInstanceContext();
- constrainingBase = 0;
+ constrainingBase = nullptr;
break;
case AR_dependent:
llvm_unreachable("cannot diagnose dependent access");
@@ -1259,7 +1260,7 @@
AccessTarget &Entity) {
const CXXRecordDecl *NamingClass = Entity.getNamingClass();
const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
- NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
+ NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr);
S.Diag(Loc, Entity.getDiag())
<< (Entity.getAccess() == AS_protected)
@@ -1872,7 +1873,7 @@
// If we are inside a class or category implementation, determine the
// interface we're in.
- ObjCInterfaceDecl *ClassOfMethodDecl = 0;
+ ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;
if (ObjCMethodDecl *MD = getCurMethodDecl())
ClassOfMethodDecl = MD->getClassInterface();
else if (FunctionDecl *FD = getCurFunctionDecl()) {
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 2e344ff..7c182a1 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -109,7 +109,7 @@
/// FreePackedContext - Deallocate and null out PackContext.
void Sema::FreePackedContext() {
delete static_cast<PragmaPackStack*>(PackContext);
- PackContext = 0;
+ PackContext = nullptr;
}
void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
@@ -143,7 +143,7 @@
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc) {
- if (PackContext == 0)
+ if (!PackContext)
PackContext = new PragmaPackStack();
PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
@@ -155,31 +155,31 @@
case POAK_Native:
case POAK_Power:
case POAK_Natural:
- Context->push(0);
+ Context->push(nullptr);
Context->setAlignment(0);
break;
// Note that '#pragma options align=packed' is not equivalent to attribute
// packed, it has a different precedence relative to attribute aligned.
case POAK_Packed:
- Context->push(0);
+ Context->push(nullptr);
Context->setAlignment(1);
break;
case POAK_Mac68k:
// Check if the target supports this.
- if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
+ if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) {
Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
return;
}
- Context->push(0);
+ Context->push(nullptr);
Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
break;
case POAK_Reset:
// Reset just pops the top of the stack, or resets the current alignment to
// default.
- if (!Context->pop(0, /*IsReset=*/true)) {
+ if (!Context->pop(nullptr, /*IsReset=*/true)) {
Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
<< "stack empty";
}
@@ -211,7 +211,7 @@
AlignmentVal = (unsigned) Val.getZExtValue();
}
- if (PackContext == 0)
+ if (!PackContext)
PackContext = new PragmaPackStack();
PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
@@ -325,12 +325,118 @@
}
}
+template<typename ValueType>
+void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ llvm::StringRef StackSlotLabel,
+ ValueType Value) {
+ if (Action == PSK_Reset) {
+ CurrentValue = nullptr;
+ return;
+ }
+ if (Action & PSK_Push)
+ Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation));
+ else if (Action & PSK_Pop) {
+ if (!StackSlotLabel.empty()) {
+ // If we've got a label, try to find it and jump there.
+ auto I = std::find_if(Stack.rbegin(), Stack.rend(),
+ [&](const Slot &x) { return x.StackSlotLabel == StackSlotLabel; });
+ // If we found the label so pop from there.
+ if (I != Stack.rend()) {
+ CurrentValue = I->Value;
+ CurrentPragmaLocation = I->PragmaLocation;
+ Stack.erase(std::prev(I.base()), Stack.end());
+ }
+ } else if (!Stack.empty()) {
+ // We don't have a label, just pop the last entry.
+ CurrentValue = Stack.back().Value;
+ CurrentPragmaLocation = Stack.back().PragmaLocation;
+ Stack.pop_back();
+ }
+ }
+ if (Action & PSK_Set) {
+ CurrentValue = Value;
+ CurrentPragmaLocation = PragmaLocation;
+ }
+}
+
+bool Sema::UnifySection(const StringRef &SectionName,
+ int SectionFlags,
+ DeclaratorDecl *Decl) {
+ auto Section = SectionInfos.find(SectionName);
+ if (Section == SectionInfos.end()) {
+ SectionInfos[SectionName] =
+ SectionInfo(Decl, SourceLocation(), SectionFlags);
+ return false;
+ }
+ // A pre-declared section takes precedence w/o diagnostic.
+ if (Section->second.SectionFlags == SectionFlags ||
+ !(Section->second.SectionFlags & PSF_Implicit))
+ return false;
+ auto OtherDecl = Section->second.Decl;
+ Diag(Decl->getLocation(), diag::err_section_conflict)
+ << Decl << OtherDecl;
+ Diag(OtherDecl->getLocation(), diag::note_declared_at)
+ << OtherDecl->getName();
+ if (auto A = Decl->getAttr<SectionAttr>())
+ if (A->isImplicit())
+ Diag(A->getLocation(), diag::note_pragma_entered_here);
+ if (auto A = OtherDecl->getAttr<SectionAttr>())
+ if (A->isImplicit())
+ Diag(A->getLocation(), diag::note_pragma_entered_here);
+ return false;
+}
+
+bool Sema::UnifySection(const StringRef &SectionName,
+ int SectionFlags,
+ SourceLocation PragmaSectionLocation) {
+ auto Section = SectionInfos.find(SectionName);
+ if (Section != SectionInfos.end()) {
+ if (Section->second.SectionFlags == SectionFlags)
+ return false;
+ if (!(Section->second.SectionFlags & PSF_Implicit)) {
+ Diag(PragmaSectionLocation, diag::err_section_conflict)
+ << "this" << "a prior #pragma section";
+ Diag(Section->second.PragmaSectionLocation,
+ diag::note_pragma_entered_here);
+ return true;
+ }
+ }
+ SectionInfos[SectionName] =
+ SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
+ return false;
+}
+
+/// \brief Called on well formed \#pragma bss_seg().
+void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ llvm::StringRef StackSlotLabel,
+ StringLiteral *SegmentName,
+ llvm::StringRef PragmaName) {
+ PragmaStack<StringLiteral *> *Stack =
+ llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName)
+ .Case("data_seg", &DataSegStack)
+ .Case("bss_seg", &BSSSegStack)
+ .Case("const_seg", &ConstSegStack)
+ .Case("code_seg", &CodeSegStack);
+ if (Action & PSK_Pop && Stack->Stack.empty())
+ Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName
+ << "stack empty";
+ Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
+}
+
+/// \brief Called on well formed \#pragma bss_seg().
+void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
+ int SectionFlags, StringLiteral *SegmentName) {
+ UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
+}
+
void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
SourceLocation PragmaLoc) {
IdentifierInfo *Name = IdTok.getIdentifierInfo();
LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
- LookupParsedName(Lookup, curScope, NULL, true);
+ LookupParsedName(Lookup, curScope, nullptr, true);
if (Lookup.empty()) {
Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
@@ -364,6 +470,34 @@
D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
}
+void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
+ if(On)
+ OptimizeOffPragmaLocation = SourceLocation();
+ else
+ OptimizeOffPragmaLocation = PragmaLoc;
+}
+
+void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
+ // In the future, check other pragmas if they're implemented (e.g. pragma
+ // optimize 0 will probably map to this functionality too).
+ if(OptimizeOffPragmaLocation.isValid())
+ AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
+}
+
+void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
+ SourceLocation Loc) {
+ // Don't add a conflicting attribute. No diagnostic is needed.
+ if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
+ return;
+
+ // Add attributes only if required. Optnone requires noinline as well, but if
+ // either is already present then don't bother adding them.
+ if (!FD->hasAttr<OptimizeNoneAttr>())
+ FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc));
+ if (!FD->hasAttr<NoInlineAttr>())
+ FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
+}
+
typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
enum : unsigned { NoVisibility = ~0U };
@@ -389,7 +523,7 @@
/// FreeVisContext - Deallocate and null out VisContext.
void Sema::FreeVisContext() {
delete static_cast<VisStack*>(VisContext);
- VisContext = 0;
+ VisContext = nullptr;
}
static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index ce47cff..8c42335 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -29,7 +29,7 @@
static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
DeclContext *CurContext) {
if (T.isNull())
- return 0;
+ return nullptr;
const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
@@ -38,11 +38,11 @@
Record->isCurrentInstantiation(CurContext))
return Record;
- return 0;
+ return nullptr;
} else if (isa<InjectedClassNameType>(Ty))
return cast<InjectedClassNameType>(Ty)->getDecl();
else
- return 0;
+ return nullptr;
}
/// \brief Compute the DeclContext that is associated with the given type.
@@ -76,7 +76,7 @@
DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
bool EnteringContext) {
if (!SS.isSet() || SS.isInvalid())
- return 0;
+ return nullptr;
NestedNameSpecifier *NNS = SS.getScopeRep();
if (NNS->isDependent()) {
@@ -88,7 +88,7 @@
if (EnteringContext) {
const Type *NNSType = NNS->getAsType();
if (!NNSType) {
- return 0;
+ return nullptr;
}
// Look through type alias templates, per C++0x [temp.dep.type]p1.
@@ -126,7 +126,7 @@
}
}
- return 0;
+ return nullptr;
}
switch (NNS->getKind()) {
@@ -170,7 +170,7 @@
assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed");
if (!NNS->getAsType())
- return 0;
+ return nullptr;
QualType T = QualType(NNS->getAsType(), 0);
return ::getCurrentInstantiationOf(T, CurContext);
@@ -187,7 +187,7 @@
/// will attempt to instantiate that class template.
bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
DeclContext *DC) {
- assert(DC != 0 && "given null context");
+ assert(DC && "given null context");
TagDecl *tag = dyn_cast<TagDecl>(DC);
@@ -282,13 +282,13 @@
/// name lookup.
NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
if (!S || !NNS)
- return 0;
+ return nullptr;
while (NNS->getPrefix())
NNS = NNS->getPrefix();
if (NNS->getKind() != NestedNameSpecifier::Identifier)
- return 0;
+ return nullptr;
LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
LookupNestedNameSpecifierName);
@@ -296,13 +296,13 @@
assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
if (!Found.isSingleResult())
- return 0;
+ return nullptr;
NamedDecl *Result = Found.getFoundDecl();
if (isAcceptableNestedNameSpecifier(Result))
return Result;
- return 0;
+ return nullptr;
}
bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
@@ -313,7 +313,7 @@
LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
// Determine where to perform name lookup
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
bool isDependent = false;
if (!ObjectType.isNull()) {
// This nested-name-specifier occurs in a member access expression, e.g.,
@@ -377,6 +377,28 @@
/// by ActOnCXXNestedNameSpecifier.
///
/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
+/// that it contains an extra parameter \p ScopeLookupResult.
+///
+/// \param S Scope in which the nested-name-specifier occurs.
+/// \param Identifier Identifier in the sequence "identifier" "::".
+/// \param IdentifierLoc Location of the \p Identifier.
+/// \param CCLoc Location of "::" following Identifier.
+/// \param ObjectType Type of postfix expression if the nested-name-specifier
+/// occurs in construct like: <tt>ptr->nns::f</tt>.
+/// \param EnteringContext If true, enter the context specified by the
+/// nested-name-specifier.
+/// \param SS Optional nested name specifier preceding the identifier.
+/// \param ScopeLookupResult Provides the result of name lookup within the
+/// scope of the nested-name-specifier that was computed at template
+/// definition time.
+/// \param ErrorRecoveryLookup Specifies if the method is called to improve
+/// error recovery and what kind of recovery is performed.
+/// \param IsCorrectedToColon If not null, suggestion of replace '::' -> ':'
+/// are allowed. The bool value pointed by this parameter is set to
+/// 'true' if the identifier is treated as if it was followed by ':',
+/// not '::'.
+///
+/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
/// that it contains an extra parameter \p ScopeLookupResult, which provides
/// the result of name lookup within the scope of the nested-name-specifier
/// that was computed at template definition time.
@@ -395,13 +417,16 @@
bool EnteringContext,
CXXScopeSpec &SS,
NamedDecl *ScopeLookupResult,
- bool ErrorRecoveryLookup) {
+ bool ErrorRecoveryLookup,
+ bool *IsCorrectedToColon) {
LookupResult Found(*this, &Identifier, IdentifierLoc,
LookupNestedNameSpecifierName);
// Determine where to perform name lookup
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
bool isDependent = false;
+ if (IsCorrectedToColon)
+ *IsCorrectedToColon = false;
if (!ObjectType.isNull()) {
// This nested-name-specifier occurs in a member access expression, e.g.,
// x->B::f, and we are looking into the type of the object.
@@ -416,7 +441,6 @@
Found.setContextRange(SS.getRange());
}
-
bool ObjectTypeSearchedInScope = false;
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
@@ -473,17 +497,48 @@
// Don't speculate if we're just trying to improve error recovery.
if (ErrorRecoveryLookup)
return true;
-
+
// We were not able to compute the declaration context for a dependent
// base object type or prior nested-name-specifier, so this
// nested-name-specifier refers to an unknown specialization. Just build
// a dependent nested-name-specifier.
SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
return false;
- }
-
+ }
+
// FIXME: Deal with ambiguities cleanly.
+ if (Found.empty() && !ErrorRecoveryLookup) {
+ // If identifier is not found as class-name-or-namespace-name, but is found
+ // as other entity, don't look for typos.
+ LookupResult R(*this, Found.getLookupNameInfo(), LookupOrdinaryName);
+ if (LookupCtx)
+ LookupQualifiedName(R, LookupCtx);
+ else if (S && !isDependent)
+ LookupName(R, S);
+ if (!R.empty()) {
+ // The identifier is found in ordinary lookup. If correction to colon is
+ // allowed, suggest replacement to ':'.
+ if (IsCorrectedToColon) {
+ *IsCorrectedToColon = true;
+ Diag(CCLoc, diag::err_nested_name_spec_is_not_class)
+ << &Identifier << getLangOpts().CPlusPlus
+ << FixItHint::CreateReplacement(CCLoc, ":");
+ if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(), diag::note_declared_at);
+ return true;
+ }
+ // Replacement '::' -> ':' is not allowed, just issue respective error.
+ Diag(R.getNameLoc(), diag::err_expected_class_or_namespace)
+ << &Identifier << getLangOpts().CPlusPlus;
+ if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(),
+ diag::note_expected_class_or_namespace_declared_here)
+ << &Identifier;
+ return true;
+ }
+ }
+
if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MSVCCompat) {
// We haven't found anything, and we're not recovering from a
// different kind of error, so look for typos.
@@ -492,7 +547,8 @@
Found.clear();
if (TypoCorrection Corrected =
CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S,
- &SS, Validator, LookupCtx, EnteringContext)) {
+ &SS, Validator, CTK_ErrorRecovery, LookupCtx,
+ EnteringContext)) {
if (LookupCtx) {
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() &&
@@ -543,8 +599,8 @@
!Context.hasSameType(
Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
- if (ErrorRecoveryLookup)
- return true;
+ if (ErrorRecoveryLookup)
+ return true;
Diag(IdentifierLoc,
diag::err_nested_name_member_ref_lookup_ambiguous)
@@ -558,7 +614,7 @@
}
}
- // If we're just performing this lookup for error-recovery purposes,
+ // If we're just performing this lookup for error-recovery purposes,
// don't extend the nested-name-specifier. Just return now.
if (ErrorRecoveryLookup)
return false;
@@ -681,14 +737,17 @@
SourceLocation CCLoc,
ParsedType ObjectType,
bool EnteringContext,
- CXXScopeSpec &SS) {
+ CXXScopeSpec &SS,
+ bool ErrorRecoveryLookup,
+ bool *IsCorrectedToColon) {
if (SS.isInvalid())
return true;
-
+
return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc,
GetTypeFromParser(ObjectType),
EnteringContext, SS,
- /*ScopeLookupResult=*/0, false);
+ /*ScopeLookupResult=*/nullptr, false,
+ IsCorrectedToColon);
}
bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
@@ -728,11 +787,11 @@
bool EnteringContext) {
if (SS.isInvalid())
return false;
-
+
return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc,
GetTypeFromParser(ObjectType),
EnteringContext, SS,
- /*ScopeLookupResult=*/0, true);
+ /*ScopeLookupResult=*/nullptr, true);
}
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
@@ -835,8 +894,8 @@
void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
if (SS.isEmpty() || SS.isInvalid())
- return 0;
-
+ return nullptr;
+
void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) +
SS.location_size()),
llvm::alignOf<NestedNameSpecifierAnnotation>());
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index 5d49225..df4e823 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -90,7 +90,7 @@
if (IsARCUnbridgedCast) {
castExpr = ImplicitCastExpr::Create(Self.Context,
Self.Context.ARCUnbridgedCastTy,
- CK_Dependent, castExpr, 0,
+ CK_Dependent, castExpr, nullptr,
castExpr->getValueKind());
}
return Self.Owned(castExpr);
@@ -286,7 +286,7 @@
}
return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
- 0, DestTInfo, OpLoc,
+ nullptr, DestTInfo, OpLoc,
Parens.getEnd(),
AngleBrackets));
}
@@ -549,7 +549,7 @@
QualType DestPointee;
const PointerType *DestPointer = DestType->getAs<PointerType>();
- const ReferenceType *DestReference = 0;
+ const ReferenceType *DestReference = nullptr;
if (DestPointer) {
DestPointee = DestPointer->getPointeeType();
} else if ((DestReference = DestType->getAs<ReferenceType>())) {
@@ -1067,6 +1067,11 @@
Kind = CK_BitCast;
return TC_Success;
}
+ // Allow ns-pointer to cf-pointer conversion in either direction
+ // with static casts.
+ if (!CStyle &&
+ Self.CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind))
+ return TC_Success;
// We tried everything. Everything! Nothing works! :-(
return TC_NotApplicable;
@@ -1272,7 +1277,7 @@
return TC_Failed;
}
- if (Paths.getDetectedVirtual() != 0) {
+ if (Paths.getDetectedVirtual() != nullptr) {
QualType VirtualBase(Paths.getDetectedVirtual(), 0);
Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual)
<< OrigSrcType << OrigDestType << VirtualBase << OpRange;
@@ -1584,8 +1589,7 @@
// This is a const_cast from a class prvalue to an rvalue reference type.
// Materialize a temporary to store the result of the conversion.
SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
- SrcType, SrcExpr.take(), /*IsLValueReference*/ false,
- /*ExtendingDecl*/ 0);
+ SrcType, SrcExpr.take(), /*IsLValueReference*/ false);
return TC_Success;
}
@@ -1735,7 +1739,7 @@
// same effect as the conversion *reinterpret_cast<T*>(&x) with the
// built-in & and * operators.
- const char *inappropriate = 0;
+ const char *inappropriate = nullptr;
switch (SrcExpr.get()->getObjectKind()) {
case OK_Ordinary:
break;
@@ -2087,8 +2091,6 @@
if (Self.getLangOpts().ObjCAutoRefCount && tcr == TC_Success)
checkObjCARCConversion(CCK);
- else if (Self.getLangOpts().ObjC1 && tcr == TC_Success)
- Self.CheckTollFreeBridgeCast(DestType, SrcExpr.get());
if (tcr != TC_Success && msg != 0) {
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
@@ -2097,10 +2099,16 @@
DestType,
/*Complain*/ true,
Found);
-
- assert(!Fn && "cast failed but able to resolve overload expression!!");
- (void)Fn;
-
+ if (Fn) {
+ // If DestType is a function type (not to be confused with the function
+ // pointer type), it will be possible to resolve the function address,
+ // but the type cast should be considered as failure.
+ OverloadExpr *OE = OverloadExpr::find(SrcExpr.get()).Expression;
+ Self.Diag(OpRange.getBegin(), diag::err_bad_cstyle_cast_overload)
+ << OE->getName() << DestType << OpRange
+ << OE->getQualifierLoc().getSourceRange();
+ Self.NoteAllOverloadCandidates(SrcExpr.get());
+ }
} else {
diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
OpRange, SrcExpr.get(), DestType, ListInitialization);
@@ -2349,8 +2357,6 @@
return;
}
}
- else if (Self.getLangOpts().ObjC1)
- Self.CheckTollFreeBridgeCast(DestType, SrcExpr.get());
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
DiagnoseBadFunctionCast(Self, SrcExpr, DestType);
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 27cc8a3..83fb1d7 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -27,7 +27,7 @@
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
@@ -43,8 +43,8 @@
SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
unsigned ByteNo) const {
- return SL->getLocationOfByte(ByteNo, PP.getSourceManager(),
- PP.getLangOpts(), PP.getTargetInfo());
+ return SL->getLocationOfByte(ByteNo, getSourceManager(), LangOpts,
+ Context.getTargetInfo());
}
/// Checks that a call expression's argument count is the desired number.
@@ -176,7 +176,7 @@
return ExprError();
break;
case Builtin::BI__builtin_object_size:
- if (SemaBuiltinObjectSize(TheCall))
+ if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3))
return ExprError();
break;
case Builtin::BI__builtin_longjmp:
@@ -309,12 +309,10 @@
if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
- case llvm::Triple::arm64:
- if (CheckARM64BuiltinFunctionCall(BuiltinID, TheCall))
- return ExprError();
- break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
@@ -467,43 +465,19 @@
#include "clang/Basic/arm_neon.inc"
#undef GET_NEON_IMMEDIATE_CHECK
}
- ;
- // We can't check the value of a dependent argument.
- if (TheCall->getArg(i)->isTypeDependent() ||
- TheCall->getArg(i)->isValueDependent())
- return false;
-
- // Check that the immediate argument is actually a constant.
- if (SemaBuiltinConstantArg(TheCall, i, Result))
- return true;
-
- // Range check against the upper/lower values for this isntruction.
- unsigned Val = Result.getZExtValue();
- if (Val < l || Val > (u + l))
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << l << u + l << TheCall->getArg(i)->getSourceRange();
-
- return false;
-}
-
-bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall) {
- if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
- return true;
-
- return false;
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
unsigned MaxWidth) {
assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
BuiltinID == ARM::BI__builtin_arm_strex ||
- BuiltinID == ARM64::BI__builtin_arm_ldrex ||
- BuiltinID == ARM64::BI__builtin_arm_strex) &&
+ BuiltinID == AArch64::BI__builtin_arm_ldrex ||
+ BuiltinID == AArch64::BI__builtin_arm_strex) &&
"unexpected ARM builtin");
bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
- BuiltinID == ARM64::BI__builtin_arm_ldrex;
+ BuiltinID == AArch64::BI__builtin_arm_ldrex;
DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
@@ -628,33 +602,18 @@
case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
case ARM::BI__builtin_arm_dmb:
case ARM::BI__builtin_arm_dsb: l = 0; u = 15; break;
- };
-
- // We can't check the value of a dependent argument.
- if (TheCall->getArg(i)->isTypeDependent() ||
- TheCall->getArg(i)->isValueDependent())
- return false;
-
- // Check that the immediate argument is actually a constant.
- if (SemaBuiltinConstantArg(TheCall, i, Result))
- return true;
-
- // Range check against the upper/lower values for this isntruction.
- unsigned Val = Result.getZExtValue();
- if (Val < l || Val > (u + l))
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << l << u+l << TheCall->getArg(i)->getSourceRange();
+ }
// FIXME: VFP Intrinsics should error if VFP not present.
- return false;
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
-bool Sema::CheckARM64BuiltinFunctionCall(unsigned BuiltinID,
+bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
llvm::APSInt Result;
- if (BuiltinID == ARM64::BI__builtin_arm_ldrex ||
- BuiltinID == ARM64::BI__builtin_arm_strex) {
+ if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
+ BuiltinID == AArch64::BI__builtin_arm_strex) {
return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128);
}
@@ -675,31 +634,16 @@
case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break;
case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break;
case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break;
- };
+ }
- // We can't check the value of a dependent argument.
- if (TheCall->getArg(i)->isTypeDependent() ||
- TheCall->getArg(i)->isValueDependent())
- return false;
-
- // Check that the immediate argument is actually a constant.
- llvm::APSInt Result;
- if (SemaBuiltinConstantArg(TheCall, i, Result))
- return true;
-
- // Range check against the upper/lower values for this instruction.
- unsigned Val = Result.getZExtValue();
- if (Val < l || Val > u)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << l << u << TheCall->getArg(i)->getSourceRange();
-
- return false;
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
switch (BuiltinID) {
case X86::BI_mm_prefetch:
- return SemaBuiltinMMPrefetch(TheCall);
+ // This is declared to take (const char*, int)
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
}
return false;
}
@@ -762,11 +706,8 @@
SourceLocation CallSiteLoc) {
// Check the attributes attached to the method/function itself.
for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) {
- for (NonNullAttr::args_iterator i = NonNull->args_begin(),
- e = NonNull->args_end();
- i != e; ++i) {
- CheckNonNullArgument(S, ExprArgs[*i], CallSiteLoc);
- }
+ for (const auto &Val : NonNull->args())
+ CheckNonNullArgument(S, ExprArgs[Val], CallSiteLoc);
}
// Check the attributes on the parameters.
@@ -930,12 +871,13 @@
/// Checks function calls when a FunctionDecl or a NamedDecl is not available,
/// such as function pointers returned from functions.
bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
- VariadicCallType CallType = getVariadicCallType(/*FDecl=*/0, Proto,
+ VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto,
TheCall->getCallee());
unsigned NumParams = Proto ? Proto->getNumParams() : 0;
- checkCall(/*FDecl=*/0, llvm::makeArrayRef<const Expr *>(
- TheCall->getArgs(), TheCall->getNumArgs()),
+ checkCall(/*FDecl=*/nullptr,
+ llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
+ TheCall->getNumArgs()),
NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -1589,7 +1531,7 @@
LookupName(Res, TUScope, /*AllowBuiltinCreation=*/true);
assert(Res.getFoundDecl());
NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl());
- if (NewBuiltinDecl == 0)
+ if (!NewBuiltinDecl)
return ExprError();
}
@@ -1831,7 +1773,7 @@
if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) &&
"promotion from float to double is the only expected cast here");
- Cast->setSubExpr(0);
+ Cast->setSubExpr(nullptr);
TheCall->setArg(NumArgs-1, CastArg);
}
}
@@ -1916,7 +1858,7 @@
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
exprs.push_back(TheCall->getArg(i));
- TheCall->setArg(i, 0);
+ TheCall->setArg(i, nullptr);
}
return Owned(new (Context) ShuffleVectorExpr(Context, exprs, resType,
@@ -1969,51 +1911,10 @@
// Argument 0 is checked for us and the remaining arguments must be
// constant integers.
- for (unsigned i = 1; i != NumArgs; ++i) {
- Expr *Arg = TheCall->getArg(i);
-
- // We can't check the value of a dependent argument.
- if (Arg->isTypeDependent() || Arg->isValueDependent())
- continue;
-
- llvm::APSInt Result;
- if (SemaBuiltinConstantArg(TheCall, i, Result))
+ for (unsigned i = 1; i != NumArgs; ++i)
+ if (SemaBuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3))
return true;
- // FIXME: gcc issues a warning and rewrites these to 0. These
- // seems especially odd for the third argument since the default
- // is 3.
- if (i == 1) {
- if (Result.getLimitedValue() > 1)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << "0" << "1" << Arg->getSourceRange();
- } else {
- if (Result.getLimitedValue() > 3)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << "0" << "3" << Arg->getSourceRange();
- }
- }
-
- return false;
-}
-
-/// SemaBuiltinMMPrefetch - Handle _mm_prefetch.
-// This is declared to take (const char*, int)
-bool Sema::SemaBuiltinMMPrefetch(CallExpr *TheCall) {
- Expr *Arg = TheCall->getArg(1);
-
- // We can't check the value of a dependent argument.
- if (Arg->isTypeDependent() || Arg->isValueDependent())
- return false;
-
- llvm::APSInt Result;
- if (SemaBuiltinConstantArg(TheCall, 1, Result))
- return true;
-
- if (Result.getLimitedValue() > 3)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << "0" << "3" << Arg->getSourceRange();
-
return false;
}
@@ -2034,27 +1935,24 @@
return false;
}
-/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr,
-/// int type). This simply type checks that type is one of the defined
-/// constants (0-3).
-// For compatibility check 0-3, llvm only handles 0 and 2.
-bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
+/// SemaBuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr
+/// TheCall is a constant expression in the range [Low, High].
+bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
+ int Low, int High) {
llvm::APSInt Result;
// We can't check the value of a dependent argument.
- if (TheCall->getArg(1)->isTypeDependent() ||
- TheCall->getArg(1)->isValueDependent())
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
return false;
// Check constant-ness first.
- if (SemaBuiltinConstantArg(TheCall, 1, Result))
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
return true;
- Expr *Arg = TheCall->getArg(1);
- if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) {
+ if (Result.getSExtValue() < Low || Result.getSExtValue() > High)
return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
- }
+ << Low << High << Arg->getSourceRange();
return false;
}
@@ -2248,7 +2146,7 @@
}
case Stmt::ObjCStringLiteralClass:
case Stmt::StringLiteralClass: {
- const StringLiteral *StrE = NULL;
+ const StringLiteral *StrE = nullptr;
if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E))
StrE = ObjCFExpr->getString();
@@ -2952,7 +2850,7 @@
if (!RD || !RD->getDefinition())
return Results;
- LookupResult R(S, &S.PP.getIdentifierTable().get(Name), SourceLocation(),
+ LookupResult R(S, &S.Context.Idents.get(Name), SourceLocation(),
Sema::LookupMemberName);
R.suppressDiagnostics();
@@ -2998,8 +2896,7 @@
if (Method->getMinRequiredArguments() == 0 &&
AT.matchesType(S.Context, Method->getReturnType())) {
// FIXME: Suggest parens if the expression needs them.
- SourceLocation EndLoc =
- S.getPreprocessor().getLocForEndOfToken(E->getLocEnd());
+ SourceLocation EndLoc = S.getLocForEndOfToken(E->getLocEnd());
S.Diag(E->getLocStart(), diag::note_printf_c_str)
<< "c_str()"
<< FixItHint::CreateInsertion(EndLoc, ".c_str()");
@@ -3328,7 +3225,7 @@
Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(),
CastFix.str()));
- SourceLocation After = S.PP.getLocForEndOfToken(E->getLocEnd());
+ SourceLocation After = S.getLocForEndOfToken(E->getLocEnd());
Hints.push_back(FixItHint::CreateInsertion(After, ")"));
}
@@ -3862,54 +3759,106 @@
// If the replacement is valid, emit a note with replacement function.
// Additionally, suggest including the proper header if not already included.
static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range,
- unsigned AbsKind) {
- std::string AbsName = S.Context.BuiltinInfo.GetName(AbsKind);
-
- // Look up absolute value function in TU scope.
- DeclarationName DN(&S.Context.Idents.get(AbsName));
- LookupResult R(S, DN, Loc, Sema::LookupAnyName);
- R.suppressDiagnostics();
- S.LookupName(R, S.TUScope);
-
- // Skip notes if multiple results found in lookup.
- if (!R.empty() && !R.isSingleResult())
- return;
-
- FunctionDecl *FD = 0;
- bool FoundFunction = R.isSingleResult();
- // When one result is found, see if it is the correct function.
- if (R.isSingleResult()) {
- FD = dyn_cast<FunctionDecl>(R.getFoundDecl());
- if (!FD || FD->getBuiltinID() != AbsKind)
- return;
- }
-
- // Look for local name conflict, prepend "::" as necessary.
- R.clear();
- S.LookupName(R, S.getCurScope());
-
- if (!FoundFunction) {
- if (!R.empty()) {
- AbsName = "::" + AbsName;
+ unsigned AbsKind, QualType ArgType) {
+ bool EmitHeaderHint = true;
+ const char *HeaderName = nullptr;
+ const char *FunctionName = nullptr;
+ if (S.getLangOpts().CPlusPlus && !ArgType->isAnyComplexType()) {
+ FunctionName = "std::abs";
+ if (ArgType->isIntegralOrEnumerationType()) {
+ HeaderName = "cstdlib";
+ } else if (ArgType->isRealFloatingType()) {
+ HeaderName = "cmath";
+ } else {
+ llvm_unreachable("Invalid Type");
}
- } else { // FoundFunction
- if (R.isSingleResult()) {
- if (R.getFoundDecl() != FD) {
- AbsName = "::" + AbsName;
+
+ // Lookup all std::abs
+ if (NamespaceDecl *Std = S.getStdNamespace()) {
+ LookupResult R(S, &S.Context.Idents.get("abs"), Loc, Sema::LookupAnyName);
+ R.suppressDiagnostics();
+ S.LookupQualifiedName(R, Std);
+
+ for (const auto *I : R) {
+ const FunctionDecl *FDecl = nullptr;
+ if (const UsingShadowDecl *UsingD = dyn_cast<UsingShadowDecl>(I)) {
+ FDecl = dyn_cast<FunctionDecl>(UsingD->getTargetDecl());
+ } else {
+ FDecl = dyn_cast<FunctionDecl>(I);
+ }
+ if (!FDecl)
+ continue;
+
+ // Found std::abs(), check that they are the right ones.
+ if (FDecl->getNumParams() != 1)
+ continue;
+
+ // Check that the parameter type can handle the argument.
+ QualType ParamType = FDecl->getParamDecl(0)->getType();
+ if (getAbsoluteValueKind(ArgType) == getAbsoluteValueKind(ParamType) &&
+ S.Context.getTypeSize(ArgType) <=
+ S.Context.getTypeSize(ParamType)) {
+ // Found a function, don't need the header hint.
+ EmitHeaderHint = false;
+ break;
+ }
}
- } else if (!R.empty()) {
- AbsName = "::" + AbsName;
+ }
+ } else {
+ FunctionName = S.Context.BuiltinInfo.GetName(AbsKind);
+ HeaderName = S.Context.BuiltinInfo.getHeaderName(AbsKind);
+
+ if (HeaderName) {
+ DeclarationName DN(&S.Context.Idents.get(FunctionName));
+ LookupResult R(S, DN, Loc, Sema::LookupAnyName);
+ R.suppressDiagnostics();
+ S.LookupName(R, S.getCurScope());
+
+ if (R.isSingleResult()) {
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(R.getFoundDecl());
+ if (FD && FD->getBuiltinID() == AbsKind) {
+ EmitHeaderHint = false;
+ } else {
+ return;
+ }
+ } else if (!R.empty()) {
+ return;
+ }
}
}
S.Diag(Loc, diag::note_replace_abs_function)
- << AbsName << FixItHint::CreateReplacement(Range, AbsName);
+ << FunctionName << FixItHint::CreateReplacement(Range, FunctionName);
- if (!FoundFunction) {
- S.Diag(Loc, diag::note_please_include_header)
- << S.Context.BuiltinInfo.getHeaderName(AbsKind)
- << S.Context.BuiltinInfo.GetName(AbsKind);
+ if (!HeaderName)
+ return;
+
+ if (!EmitHeaderHint)
+ return;
+
+ S.Diag(Loc, diag::note_please_include_header) << HeaderName << FunctionName;
+}
+
+static bool IsFunctionStdAbs(const FunctionDecl *FDecl) {
+ if (!FDecl)
+ return false;
+
+ if (!FDecl->getIdentifier() || !FDecl->getIdentifier()->isStr("abs"))
+ return false;
+
+ const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(FDecl->getDeclContext());
+
+ while (ND && ND->isInlineNamespace()) {
+ ND = dyn_cast<NamespaceDecl>(ND->getDeclContext());
}
+
+ if (!ND || !ND->getIdentifier() || !ND->getIdentifier()->isStr("std"))
+ return false;
+
+ if (!isa<TranslationUnitDecl>(ND->getDeclContext()))
+ return false;
+
+ return true;
}
// Warn when using the wrong abs() function.
@@ -3920,7 +3869,8 @@
return;
unsigned AbsKind = getAbsoluteValueFunctionKind(FDecl);
- if (AbsKind == 0)
+ bool IsStdAbs = IsFunctionStdAbs(FDecl);
+ if (AbsKind == 0 && !IsStdAbs)
return;
QualType ArgType = Call->getArg(0)->IgnoreParenImpCasts()->getType();
@@ -3929,13 +3879,20 @@
// Unsigned types can not be negative. Suggest to drop the absolute value
// function.
if (ArgType->isUnsignedIntegerType()) {
+ const char *FunctionName =
+ IsStdAbs ? "std::abs" : Context.BuiltinInfo.GetName(AbsKind);
Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
Diag(Call->getExprLoc(), diag::note_remove_abs)
- << FDecl
+ << FunctionName
<< FixItHint::CreateRemoval(Call->getCallee()->getSourceRange());
return;
}
+ // std::abs has overloads which prevent most of the absolute value problems
+ // from occurring.
+ if (IsStdAbs)
+ return;
+
AbsoluteValueKind ArgValueKind = getAbsoluteValueKind(ArgType);
AbsoluteValueKind ParamValueKind = getAbsoluteValueKind(ParamType);
@@ -3953,7 +3910,7 @@
return;
emitReplacement(*this, Call->getExprLoc(),
- Call->getCallee()->getSourceRange(), NewAbsKind);
+ Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
return;
}
@@ -3969,7 +3926,7 @@
<< FDecl << ParamValueKind << ArgValueKind;
emitReplacement(*this, Call->getExprLoc(),
- Call->getCallee()->getSourceRange(), NewAbsKind);
+ Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
return;
}
@@ -3991,20 +3948,17 @@
if (!Size->isComparisonOp() && !Size->isEqualityOp() && !Size->isLogicalOp())
return false;
- Preprocessor &PP = S.getPreprocessor();
SourceRange SizeRange = Size->getSourceRange();
S.Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison)
<< SizeRange << FnName;
- S.Diag(FnLoc, diag::warn_memsize_comparison_paren_note)
- << FnName
- << FixItHint::CreateInsertion(
- PP.getLocForEndOfToken(Size->getLHS()->getLocEnd()),
- ")")
+ S.Diag(FnLoc, diag::note_memsize_comparison_paren)
+ << FnName << FixItHint::CreateInsertion(
+ S.getLocForEndOfToken(Size->getLHS()->getLocEnd()), ")")
<< FixItHint::CreateRemoval(RParenLoc);
- S.Diag(SizeRange.getBegin(), diag::warn_memsize_comparison_cast_note)
+ S.Diag(SizeRange.getBegin(), diag::note_memsize_comparison_cast_silence)
<< FixItHint::CreateInsertion(SizeRange.getBegin(), "(size_t)(")
- << FixItHint::CreateInsertion(
- PP.getLocForEndOfToken(SizeRange.getEnd()), ")");
+ << FixItHint::CreateInsertion(S.getLocForEndOfToken(SizeRange.getEnd()),
+ ")");
return true;
}
@@ -4028,7 +3982,7 @@
if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType())
return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
- return 0;
+ return nullptr;
}
/// \brief If E is a sizeof expression, returns its argument type.
@@ -4118,7 +4072,7 @@
SourceLocation SL = SizeOfArg->getExprLoc();
SourceRange DSR = Dest->getSourceRange();
SourceRange SSR = SizeOfArg->getSourceRange();
- SourceManager &SM = PP.getSourceManager();
+ SourceManager &SM = getSourceManager();
if (SM.isMacroArgExpansion(SL)) {
ReadableName = Lexer::getImmediateMacroName(SL, SM, LangOpts);
@@ -4250,7 +4204,7 @@
const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context);
const Expr *SizeArg = ignoreLiteralAdditions(Call->getArg(2), Context);
- const Expr *CompareWithSrc = NULL;
+ const Expr *CompareWithSrc = nullptr;
if (CheckMemorySizeofForComparison(*this, SizeArg, FnName,
Call->getLocStart(), Call->getRParenLoc()))
@@ -4299,7 +4253,7 @@
SmallString<128> sizeString;
llvm::raw_svector_ostream OS(sizeString);
OS << "sizeof(";
- DstArg->printPretty(OS, 0, getPrintingPolicy());
+ DstArg->printPretty(OS, nullptr, getPrintingPolicy());
OS << ")";
Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size)
@@ -4319,10 +4273,10 @@
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
const FunctionDecl *FD = CE->getDirectCallee();
if (!FD || FD->getMemoryFunctionKind() != Builtin::BIstrlen)
- return 0;
+ return nullptr;
return CE->getArg(0)->IgnoreParenCasts();
}
- return 0;
+ return nullptr;
}
// Warn on anti-patterns as the 'size' argument to strncat.
@@ -4371,7 +4325,7 @@
// Generate the diagnostic.
SourceLocation SL = LenArg->getLocStart();
SourceRange SR = LenArg->getSourceRange();
- SourceManager &SM = PP.getSourceManager();
+ SourceManager &SM = getSourceManager();
// If the function is defined as a builtin macro, do not show macro expansion.
if (SM.isMacroArgExpansion(SL)) {
@@ -4400,10 +4354,10 @@
SmallString<128> sizeString;
llvm::raw_svector_ostream OS(sizeString);
OS << "sizeof(";
- DstArg->printPretty(OS, 0, getPrintingPolicy());
+ DstArg->printPretty(OS, nullptr, getPrintingPolicy());
OS << ") - ";
OS << "strlen(";
- DstArg->printPretty(OS, 0, getPrintingPolicy());
+ DstArg->printPretty(OS, nullptr, getPrintingPolicy());
OS << ") - 1";
Diag(SL, diag::note_strncat_wrong_size)
@@ -4423,19 +4377,19 @@
CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc) {
- Expr *stackE = 0;
+ Expr *stackE = nullptr;
SmallVector<DeclRefExpr *, 8> refVars;
// Perform checking for returned stack addresses, local blocks,
// label addresses or references to temporaries.
if (lhsType->isPointerType() ||
(!S.getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
- stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/0);
+ stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/nullptr);
} else if (lhsType->isReferenceType()) {
- stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/0);
+ stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/nullptr);
}
- if (stackE == 0)
+ if (!stackE)
return; // Nothing suspicious was found.
SourceLocation diagLoc;
@@ -4509,7 +4463,7 @@
static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
Decl *ParentDecl) {
if (E->isTypeDependent())
- return NULL;
+ return nullptr;
// We should only be called for evaluating pointer expressions.
assert((E->getType()->isAnyPointerType() ||
@@ -4528,7 +4482,7 @@
// If we leave the immediate function, the lifetime isn't about to end.
if (DR->refersToEnclosingLocal())
- return 0;
+ return nullptr;
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
// If this is a reference variable, follow through to the expression that
@@ -4540,7 +4494,7 @@
return EvalAddr(V->getInit(), refVars, ParentDecl);
}
- return NULL;
+ return nullptr;
}
case Stmt::UnaryOperatorClass: {
@@ -4551,7 +4505,7 @@
if (U->getOpcode() == UO_AddrOf)
return EvalVal(U->getSubExpr(), refVars, ParentDecl);
else
- return NULL;
+ return nullptr;
}
case Stmt::BinaryOperatorClass: {
@@ -4561,7 +4515,7 @@
BinaryOperatorKind op = B->getOpcode();
if (op != BO_Add && op != BO_Sub)
- return NULL;
+ return nullptr;
Expr *Base = B->getLHS();
@@ -4589,7 +4543,7 @@
// In C++, we can have a throw-expression, which has 'void' type.
if (C->getRHS()->getType()->isVoidType())
- return 0;
+ return nullptr;
return EvalAddr(C->getRHS(), refVars, ParentDecl);
}
@@ -4597,7 +4551,7 @@
case Stmt::BlockExprClass:
if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures())
return E; // local block.
- return NULL;
+ return nullptr;
case Stmt::AddrLabelExprClass:
return E; // address of label.
@@ -4634,7 +4588,7 @@
return EvalVal(SubExpr, refVars, ParentDecl);
default:
- return 0;
+ return nullptr;
}
}
@@ -4648,7 +4602,7 @@
// Everything else: we simply don't reason about them.
default:
- return NULL;
+ return nullptr;
}
}
@@ -4674,7 +4628,7 @@
E = IE->getSubExpr();
continue;
}
- return NULL;
+ return nullptr;
}
case Stmt::ExprWithCleanupsClass:
@@ -4688,7 +4642,7 @@
// If we leave the immediate function, the lifetime isn't about to end.
if (DR->refersToEnclosingLocal())
- return 0;
+ return nullptr;
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
// Check if it refers to itself, e.g. "int& i = i;".
@@ -4709,7 +4663,7 @@
}
}
- return NULL;
+ return nullptr;
}
case Stmt::UnaryOperatorClass: {
@@ -4721,7 +4675,7 @@
if (U->getOpcode() == UO_Deref)
return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
- return NULL;
+ return nullptr;
}
case Stmt::ArraySubscriptExprClass: {
@@ -4746,7 +4700,7 @@
// In C++, we can have a throw-expression, which has 'void' type.
if (C->getRHS()->getType()->isVoidType())
- return 0;
+ return nullptr;
return EvalVal(C->getRHS(), refVars, ParentDecl);
}
@@ -4757,12 +4711,12 @@
// Check for indirect access. We only want direct field accesses.
if (M->isArrow())
- return NULL;
+ return nullptr;
// Check whether the member type is itself a reference, in which case
// we're not going to refer to the member, but to what the member refers to.
if (M->getMemberDecl()->getType()->isReferenceType())
- return NULL;
+ return nullptr;
return EvalVal(M->getBase(), refVars, ParentDecl);
}
@@ -4782,7 +4736,7 @@
return E;
// Everything else: we simply don't reason about them.
- return NULL;
+ return nullptr;
}
} while (true);
}
@@ -5334,95 +5288,187 @@
if (!S.ActiveTemplateInstantiations.empty())
return;
+ // TODO: Investigate using GetExprRange() to get tighter bounds
+ // on the bit ranges.
+ QualType OtherT = Other->getType();
+ IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
+ unsigned OtherWidth = OtherRange.Width;
+
+ bool OtherIsBooleanType = Other->isKnownToHaveBooleanValue();
+
// 0 values are handled later by CheckTrivialUnsignedComparison().
- if (Value == 0)
+ if ((Value == 0) && (!OtherIsBooleanType))
return;
BinaryOperatorKind op = E->getOpcode();
- QualType OtherT = Other->getType();
- QualType ConstantT = Constant->getType();
- QualType CommonT = E->getLHS()->getType();
- if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
- return;
- assert((OtherT->isIntegerType() && ConstantT->isIntegerType())
- && "comparison with non-integer type");
+ bool IsTrue = true;
- bool ConstantSigned = ConstantT->isSignedIntegerType();
- bool CommonSigned = CommonT->isSignedIntegerType();
+ // Used for diagnostic printout.
+ enum {
+ LiteralConstant = 0,
+ CXXBoolLiteralTrue,
+ CXXBoolLiteralFalse
+ } LiteralOrBoolConstant = LiteralConstant;
- bool EqualityOnly = false;
+ if (!OtherIsBooleanType) {
+ QualType ConstantT = Constant->getType();
+ QualType CommonT = E->getLHS()->getType();
- // TODO: Investigate using GetExprRange() to get tighter bounds on
- // on the bit ranges.
- IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
- unsigned OtherWidth = OtherRange.Width;
-
- if (CommonSigned) {
- // The common type is signed, therefore no signed to unsigned conversion.
- if (!OtherRange.NonNegative) {
- // Check that the constant is representable in type OtherT.
- if (ConstantSigned) {
- if (OtherWidth >= Value.getMinSignedBits())
- return;
- } else { // !ConstantSigned
- if (OtherWidth >= Value.getActiveBits() + 1)
- return;
+ if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
+ return;
+ assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) &&
+ "comparison with non-integer type");
+
+ bool ConstantSigned = ConstantT->isSignedIntegerType();
+ bool CommonSigned = CommonT->isSignedIntegerType();
+
+ bool EqualityOnly = false;
+
+ if (CommonSigned) {
+ // The common type is signed, therefore no signed to unsigned conversion.
+ if (!OtherRange.NonNegative) {
+ // Check that the constant is representable in type OtherT.
+ if (ConstantSigned) {
+ if (OtherWidth >= Value.getMinSignedBits())
+ return;
+ } else { // !ConstantSigned
+ if (OtherWidth >= Value.getActiveBits() + 1)
+ return;
+ }
+ } else { // !OtherSigned
+ // Check that the constant is representable in type OtherT.
+ // Negative values are out of range.
+ if (ConstantSigned) {
+ if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
+ return;
+ } else { // !ConstantSigned
+ if (OtherWidth >= Value.getActiveBits())
+ return;
+ }
}
- } else { // !OtherSigned
- // Check that the constant is representable in type OtherT.
- // Negative values are out of range.
- if (ConstantSigned) {
- if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
- return;
- } else { // !ConstantSigned
+ } else { // !CommonSigned
+ if (OtherRange.NonNegative) {
if (OtherWidth >= Value.getActiveBits())
return;
+ } else if (!OtherRange.NonNegative && !ConstantSigned) {
+ // Check to see if the constant is representable in OtherT.
+ if (OtherWidth > Value.getActiveBits())
+ return;
+ // Check to see if the constant is equivalent to a negative value
+ // cast to CommonT.
+ if (S.Context.getIntWidth(ConstantT) ==
+ S.Context.getIntWidth(CommonT) &&
+ Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
+ return;
+ // The constant value rests between values that OtherT can represent
+ // after conversion. Relational comparison still works, but equality
+ // comparisons will be tautological.
+ EqualityOnly = true;
+ } else { // OtherSigned && ConstantSigned
+ assert(0 && "Two signed types converted to unsigned types.");
}
}
- } else { // !CommonSigned
- if (OtherRange.NonNegative) {
- if (OtherWidth >= Value.getActiveBits())
- return;
- } else if (!OtherRange.NonNegative && !ConstantSigned) {
- // Check to see if the constant is representable in OtherT.
- if (OtherWidth > Value.getActiveBits())
- return;
- // Check to see if the constant is equivalent to a negative value
- // cast to CommonT.
- if (S.Context.getIntWidth(ConstantT) == S.Context.getIntWidth(CommonT) &&
- Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
- return;
- // The constant value rests between values that OtherT can represent after
- // conversion. Relational comparison still works, but equality
- // comparisons will be tautological.
- EqualityOnly = true;
- } else { // OtherSigned && ConstantSigned
- assert(0 && "Two signed types converted to unsigned types.");
+
+ bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
+
+ if (op == BO_EQ || op == BO_NE) {
+ IsTrue = op == BO_NE;
+ } else if (EqualityOnly) {
+ return;
+ } else if (RhsConstant) {
+ if (op == BO_GT || op == BO_GE)
+ IsTrue = !PositiveConstant;
+ else // op == BO_LT || op == BO_LE
+ IsTrue = PositiveConstant;
+ } else {
+ if (op == BO_LT || op == BO_LE)
+ IsTrue = !PositiveConstant;
+ else // op == BO_GT || op == BO_GE
+ IsTrue = PositiveConstant;
}
- }
-
- bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
-
- bool IsTrue = true;
- if (op == BO_EQ || op == BO_NE) {
- IsTrue = op == BO_NE;
- } else if (EqualityOnly) {
- return;
- } else if (RhsConstant) {
- if (op == BO_GT || op == BO_GE)
- IsTrue = !PositiveConstant;
- else // op == BO_LT || op == BO_LE
- IsTrue = PositiveConstant;
} else {
- if (op == BO_LT || op == BO_LE)
- IsTrue = !PositiveConstant;
- else // op == BO_GT || op == BO_GE
- IsTrue = PositiveConstant;
+ // Other isKnownToHaveBooleanValue
+ enum CompareBoolWithConstantResult { AFals, ATrue, Unkwn };
+ enum ConstantValue { LT_Zero, Zero, One, GT_One, SizeOfConstVal };
+ enum ConstantSide { Lhs, Rhs, SizeOfConstSides };
+
+ static const struct LinkedConditions {
+ CompareBoolWithConstantResult BO_LT_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_GT_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_LE_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_GE_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_EQ_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_NE_OP[SizeOfConstSides][SizeOfConstVal];
+
+ } TruthTable = {
+ // Constant on LHS. | Constant on RHS. |
+ // LT_Zero| Zero | One |GT_One| LT_Zero| Zero | One |GT_One|
+ { { ATrue, Unkwn, AFals, AFals }, { AFals, AFals, Unkwn, ATrue } },
+ { { AFals, AFals, Unkwn, ATrue }, { ATrue, Unkwn, AFals, AFals } },
+ { { ATrue, ATrue, Unkwn, AFals }, { AFals, Unkwn, ATrue, ATrue } },
+ { { AFals, Unkwn, ATrue, ATrue }, { ATrue, ATrue, Unkwn, AFals } },
+ { { AFals, Unkwn, Unkwn, AFals }, { AFals, Unkwn, Unkwn, AFals } },
+ { { ATrue, Unkwn, Unkwn, ATrue }, { ATrue, Unkwn, Unkwn, ATrue } }
+ };
+
+ bool ConstantIsBoolLiteral = isa<CXXBoolLiteralExpr>(Constant);
+
+ enum ConstantValue ConstVal = Zero;
+ if (Value.isUnsigned() || Value.isNonNegative()) {
+ if (Value == 0) {
+ LiteralOrBoolConstant =
+ ConstantIsBoolLiteral ? CXXBoolLiteralFalse : LiteralConstant;
+ ConstVal = Zero;
+ } else if (Value == 1) {
+ LiteralOrBoolConstant =
+ ConstantIsBoolLiteral ? CXXBoolLiteralTrue : LiteralConstant;
+ ConstVal = One;
+ } else {
+ LiteralOrBoolConstant = LiteralConstant;
+ ConstVal = GT_One;
+ }
+ } else {
+ ConstVal = LT_Zero;
+ }
+
+ CompareBoolWithConstantResult CmpRes;
+
+ switch (op) {
+ case BO_LT:
+ CmpRes = TruthTable.BO_LT_OP[RhsConstant][ConstVal];
+ break;
+ case BO_GT:
+ CmpRes = TruthTable.BO_GT_OP[RhsConstant][ConstVal];
+ break;
+ case BO_LE:
+ CmpRes = TruthTable.BO_LE_OP[RhsConstant][ConstVal];
+ break;
+ case BO_GE:
+ CmpRes = TruthTable.BO_GE_OP[RhsConstant][ConstVal];
+ break;
+ case BO_EQ:
+ CmpRes = TruthTable.BO_EQ_OP[RhsConstant][ConstVal];
+ break;
+ case BO_NE:
+ CmpRes = TruthTable.BO_NE_OP[RhsConstant][ConstVal];
+ break;
+ default:
+ CmpRes = Unkwn;
+ break;
+ }
+
+ if (CmpRes == AFals) {
+ IsTrue = false;
+ } else if (CmpRes == ATrue) {
+ IsTrue = true;
+ } else {
+ return;
+ }
}
// If this is a comparison to an enum constant, include that
// constant in the diagnostic.
- const EnumConstantDecl *ED = 0;
+ const EnumConstantDecl *ED = nullptr;
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Constant))
ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
@@ -5433,11 +5479,12 @@
else
OS << Value;
- S.DiagRuntimeBehavior(E->getOperatorLoc(), E,
- S.PDiag(diag::warn_out_of_range_compare)
- << OS.str() << OtherT << IsTrue
- << E->getLHS()->getSourceRange()
- << E->getRHS()->getSourceRange());
+ S.DiagRuntimeBehavior(
+ E->getOperatorLoc(), E,
+ S.PDiag(diag::warn_out_of_range_compare)
+ << OS.str() << LiteralOrBoolConstant
+ << OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
}
/// Analyze the operands of the given comparison. Implements the
@@ -5726,7 +5773,7 @@
}
void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
- SourceLocation CC, bool *ICContext = 0) {
+ SourceLocation CC, bool *ICContext = nullptr) {
if (E->isTypeDependent() || E->isValueDependent()) return;
const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
@@ -6025,7 +6072,7 @@
if (E->isTypeDependent() || E->isValueDependent())
return;
-
+
// For conditional operators, we analyze the arguments as if they
// were being fed directly into the output.
if (isa<ConditionalOperator>(E)) {
@@ -6132,7 +6179,7 @@
}
// Expect to find a single Decl. Skip anything more complicated.
- ValueDecl *D = 0;
+ ValueDecl *D = nullptr;
if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
D = R->getDecl();
} else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) {
@@ -6163,7 +6210,7 @@
// Pretty print the expression for the diagnostic.
std::string Str;
llvm::raw_string_ostream S(Str);
- E->printPretty(S, 0, getPrintingPolicy());
+ E->printPretty(S, nullptr, getPrintingPolicy());
unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
: diag::warn_impcast_pointer_to_bool;
@@ -6213,8 +6260,7 @@
return;
}
Diag(E->getExprLoc(), diag::note_function_to_function_call)
- << FixItHint::CreateInsertion(
- getPreprocessor().getLocForEndOfToken(E->getLocEnd()), "()");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(E->getLocEnd()), "()");
}
@@ -6339,7 +6385,7 @@
};
struct Usage {
- Usage() : Use(0), Seq() {}
+ Usage() : Use(nullptr), Seq() {}
Expr *Use;
SequenceTree::Seq Seq;
};
@@ -6439,7 +6485,7 @@
} else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
// FIXME: If this is a reference, map through to its value.
return DRE->getDecl();
- return 0;
+ return nullptr;
}
/// \brief Note that an object was modified or used by an expression.
@@ -6499,8 +6545,8 @@
public:
SequenceChecker(Sema &S, Expr *E, SmallVectorImpl<Expr *> &WorkList)
- : Base(S.Context), SemaRef(S), Region(Tree.root()), ModAsSideEffect(0),
- WorkList(WorkList), EvalTracker(0) {
+ : Base(S.Context), SemaRef(S), Region(Tree.root()),
+ ModAsSideEffect(nullptr), WorkList(WorkList), EvalTracker(nullptr) {
Visit(E);
}
@@ -6785,7 +6831,7 @@
// C99 6.9.1p5: If the declarator includes a parameter type list, the
// declaration of each parameter shall include an identifier.
if (CheckParameterNames &&
- Param->getIdentifier() == 0 &&
+ Param->getIdentifier() == nullptr &&
!Param->isImplicit() &&
!getLangOpts().CPlusPlus)
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
@@ -6952,7 +6998,7 @@
if (IndexNegated)
index = -index;
- const NamedDecl *ND = NULL;
+ const NamedDecl *ND = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
ND = dyn_cast<NamedDecl>(DRE->getDecl());
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
@@ -7095,7 +7141,7 @@
namespace {
struct RetainCycleOwner {
- RetainCycleOwner() : Variable(0), Indirect(false) {}
+ RetainCycleOwner() : Variable(nullptr), Indirect(false) {}
VarDecl *Variable;
SourceRange Range;
SourceLocation Loc;
@@ -7206,7 +7252,7 @@
struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {
FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
: EvaluatedExprVisitor<FindCaptureVisitor>(Context),
- Variable(variable), Capturer(0) {}
+ Variable(variable), Capturer(nullptr) {}
VarDecl *Variable;
Expr *Capturer;
@@ -7250,7 +7296,7 @@
if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") {
e = ME->getInstanceReceiver();
if (!e)
- return 0;
+ return nullptr;
e = e->IgnoreParenCasts();
}
} else if (CallExpr *CE = dyn_cast<CallExpr>(e)) {
@@ -7267,7 +7313,7 @@
BlockExpr *block = dyn_cast<BlockExpr>(e);
if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable))
- return 0;
+ return nullptr;
FindCaptureVisitor visitor(S.Context, owner.Variable);
visitor.Visit(block->getBlockDecl()->getBody());
@@ -7343,7 +7389,7 @@
void Sema::checkRetainCycles(VarDecl *Var, Expr *Init) {
RetainCycleOwner Owner;
- if (!considerVariable(Var, /*DeclRefExpr=*/0, Owner))
+ if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner))
return;
// Because we don't have an expression for the variable, we have to set the
@@ -7854,7 +7900,7 @@
FoundWrongKind = false;
// Variable declaration that has type_tag_for_datatype attribute.
- const ValueDecl *VD = NULL;
+ const ValueDecl *VD = nullptr;
uint64_t MagicValue;
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index d44c04b..c075c92 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -104,7 +104,7 @@
if (DeclIndexPairVector *Vec
= DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
delete Vec;
- DeclOrVector = ((NamedDecl *)0);
+ DeclOrVector = ((NamedDecl *)nullptr);
}
}
@@ -172,12 +172,12 @@
explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
const CodeCompletionContext &CompletionContext,
- LookupFilter Filter = 0)
+ LookupFilter Filter = nullptr)
: SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
Filter(Filter),
AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
CompletionContext(CompletionContext),
- ObjCImplementation(0)
+ ObjCImplementation(nullptr)
{
// If this is an Objective-C instance method definition, dig out the
// corresponding implementation.
@@ -212,8 +212,8 @@
void setFilter(LookupFilter Filter) {
this->Filter = Filter;
}
-
- Result *data() { return Results.empty()? 0 : &Results.front(); }
+
+ Result *data() { return Results.empty()? nullptr : &Results.front(); }
unsigned size() const { return Results.size(); }
bool empty() const { return Results.empty(); }
@@ -289,8 +289,8 @@
/// \param R the result to add (if it is unique).
///
/// \param CurContext the context in which this result will be named.
- void MaybeAddResult(Result R, DeclContext *CurContext = 0);
-
+ void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
+
/// \brief Add a new result to this result set, where we already know
/// the hiding declation (if any).
///
@@ -364,8 +364,8 @@
return &Value;
}
};
-
- iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
+
+ iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
iterator(const NamedDecl *SingleDecl, unsigned Index)
: DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
@@ -375,7 +375,7 @@
iterator &operator++() {
if (DeclOrIterator.is<const NamedDecl *>()) {
- DeclOrIterator = (NamedDecl *)0;
+ DeclOrIterator = (NamedDecl *)nullptr;
SingleDeclIndex = 0;
return *this;
}
@@ -461,8 +461,8 @@
TargetParents.push_back(CommonAncestor);
}
-
- NestedNameSpecifier *Result = 0;
+
+ NestedNameSpecifier *Result = nullptr;
while (!TargetParents.empty()) {
const DeclContext *Parent = TargetParents.pop_back_val();
@@ -530,7 +530,7 @@
((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
Filter != &ResultBuilder::IsNamespace &&
Filter != &ResultBuilder::IsNamespaceOrAlias &&
- Filter != 0))
+ Filter != nullptr))
AsNestedNameSpecifier = true;
// Filter out any unwanted results.
@@ -779,7 +779,7 @@
ASTContext &Context = SemaRef.Context;
const NamedDecl *D = R.Declaration;
- const CXXRecordDecl *Record = 0;
+ const CXXRecordDecl *Record = nullptr;
if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Record = ClassTemplate->getTemplatedDecl();
else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
@@ -910,10 +910,11 @@
!R.StartsNestedNameSpecifier) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
+ Namespace);
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
- SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
+ false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
}
@@ -975,9 +976,10 @@
!R.StartsNestedNameSpecifier) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
+ Namespace);
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
@@ -1259,9 +1261,9 @@
bool Accessible = true;
if (Ctx)
Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
-
- ResultBuilder::Result Result(ND, Results.getBasePriority(ND), 0, false,
- Accessible);
+
+ ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
+ false, Accessible);
Results.AddResult(Result, CurContext, Hiding, InBaseClass);
}
};
@@ -2444,7 +2446,7 @@
switch (Name.getNameKind()) {
case DeclarationName::CXXOperatorName: {
- const char *OperatorName = 0;
+ const char *OperatorName = nullptr;
switch (Name.getCXXOverloadedOperator()) {
case OO_None:
case OO_Conditional:
@@ -2483,7 +2485,7 @@
break;
case DeclarationName::CXXConstructorName: {
- CXXRecordDecl *Record = 0;
+ CXXRecordDecl *Record = nullptr;
QualType Ty = Name.getCXXNameType();
if (const RecordType *RecordTy = Ty->getAs<RecordType>())
Record = cast<CXXRecordDecl>(RecordTy->getDecl());
@@ -2987,11 +2989,16 @@
for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
- if (IncludeUndefined || M->first->hasMacroDefinition())
+ if (IncludeUndefined || M->first->hasMacroDefinition()) {
+ if (MacroInfo *MI = M->second->getMacroInfo())
+ if (MI->isUsedForHeaderGuard())
+ continue;
+
Results.AddResult(Result(M->first,
getMacroUsagePriority(M->first->getName(),
PP.getLangOpts(),
TargetTypeIsPointer)));
+ }
}
Results.ExitScope();
@@ -3235,7 +3242,7 @@
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
if (getLangOpts().CPlusPlus)
- MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
+ MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
break;
case PCC_RecoveryInFunction:
@@ -3323,7 +3330,7 @@
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
CodeCompleter->includeGlobals());
- Results.setFilter(0);
+ Results.setFilter(nullptr);
}
}
Results.ExitScope();
@@ -3460,9 +3467,9 @@
// Add properties in this container.
for (const auto *P : Container->properties())
if (AddedProperties.insert(P->getIdentifier()))
- Results.MaybeAddResult(Result(P, Results.getBasePriority(P), 0),
+ Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
CurContext);
-
+
// Add nullary methods
if (AllowNullaryMethods) {
ASTContext &Context = Container->getASTContext();
@@ -3610,7 +3617,7 @@
} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
(!IsArrow && BaseType->isObjCObjectType())) {
// Objective-C instance variable access.
- ObjCInterfaceDecl *Class = 0;
+ ObjCInterfaceDecl *Class = nullptr;
if (const ObjCObjectPointerType *ObjCPtr
= BaseType->getAs<ObjCObjectPointerType>())
Class = ObjCPtr->getInterfaceDecl();
@@ -3639,8 +3646,8 @@
void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
if (!CodeCompleter)
return;
-
- ResultBuilder::LookupFilter Filter = 0;
+
+ ResultBuilder::LookupFilter Filter = nullptr;
enum CodeCompletionContext::Kind ContextKind
= CodeCompletionContext::CCC_Other;
switch ((DeclSpec::TST)TagSpec) {
@@ -3729,7 +3736,7 @@
// token, in case we are code-completing in the middle of the switch and not
// at the end. However, we aren't able to do so at the moment.
llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
- NestedNameSpecifier *Qualifier = 0;
+ NestedNameSpecifier *Qualifier = nullptr;
for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
CaseStmt *Case = dyn_cast<CaseStmt>(SC);
@@ -3780,7 +3787,7 @@
continue;
CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
- Results.AddResult(R, CurContext, 0, false);
+ Results.AddResult(R, CurContext, nullptr, false);
}
Results.ExitScope();
@@ -3828,7 +3835,7 @@
// Build an overload candidate set based on the functions we find.
SourceLocation Loc = Fn->getExprLoc();
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
// FIXME: What if we're calling something that isn't a function declaration?
// FIXME: What if we're calling a pseudo-destructor?
@@ -4136,8 +4143,9 @@
NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
Results.AddResult(CodeCompletionResult(
- NS->second, Results.getBasePriority(NS->second), 0),
- CurContext, 0, false);
+ NS->second, Results.getBasePriority(NS->second),
+ nullptr),
+ CurContext, nullptr, false);
Results.ExitScope();
}
@@ -4322,15 +4330,13 @@
// Note what has already been captured.
llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
bool IncludedThis = false;
- for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
- CEnd = Intro.Captures.end();
- C != CEnd; ++C) {
- if (C->Kind == LCK_This) {
+ for (const auto &C : Intro.Captures) {
+ if (C.Kind == LCK_This) {
IncludedThis = true;
continue;
}
- Known.insert(C->Id);
+ Known.insert(C.Id);
}
// Look for other capturable variables.
@@ -4344,7 +4350,7 @@
if (Known.insert(Var->getIdentifier()))
Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
- CurContext, 0, false);
+ CurContext, nullptr, false);
}
}
@@ -4813,8 +4819,8 @@
if (!Selectors.insert(M->getSelector()))
continue;
-
- Result R = Result(M, Results.getBasePriority(M), 0);
+
+ Result R = Result(M, Results.getBasePriority(M), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = (WantKind != MK_Any);
if (!InOriginalClass)
@@ -5016,22 +5022,22 @@
static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
if (!Msg)
- return 0;
+ return nullptr;
Selector Sel = Msg->getSelector();
if (Sel.isNull())
- return 0;
+ return nullptr;
IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
if (!Id)
- return 0;
+ return nullptr;
ObjCMethodDecl *Method = Msg->getMethodDecl();
if (!Method)
- return 0;
+ return nullptr;
// Determine the class that we're sending the message to.
- ObjCInterfaceDecl *IFace = 0;
+ ObjCInterfaceDecl *IFace = nullptr;
switch (Msg->getReceiverKind()) {
case ObjCMessageExpr::Class:
if (const ObjCObjectType *ObjType
@@ -5052,7 +5058,7 @@
}
if (!IFace)
- return 0;
+ return nullptr;
ObjCInterfaceDecl *Super = IFace->getSuperClass();
if (Method->isInstanceMethod())
@@ -5069,7 +5075,7 @@
.Case("class", IFace)
.Case("classForCoder", IFace)
.Case("superclass", Super)
- .Default(0);
+ .Default(nullptr);
return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
.Case("new", IFace)
@@ -5077,7 +5083,7 @@
.Case("allocWithZone", IFace)
.Case("class", IFace)
.Case("superclass", Super)
- .Default(0);
+ .Default(nullptr);
}
// Add a special completion for a message send to "super", which fills in the
@@ -5102,14 +5108,14 @@
ResultBuilder &Results) {
ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
if (!CurMethod)
- return 0;
-
+ return nullptr;
+
ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
if (!Class)
- return 0;
-
+ return nullptr;
+
// Try to find a superclass method with the same selector.
- ObjCMethodDecl *SuperMethod = 0;
+ ObjCMethodDecl *SuperMethod = nullptr;
while ((Class = Class->getSuperClass()) && !SuperMethod) {
// Check in the class
SuperMethod = Class->getMethod(CurMethod->getSelector(),
@@ -5126,13 +5132,13 @@
}
if (!SuperMethod)
- return 0;
-
+ return nullptr;
+
// Check whether the superclass method has the same signature.
if (CurMethod->param_size() != SuperMethod->param_size() ||
CurMethod->isVariadic() != SuperMethod->isVariadic())
- return 0;
-
+ return nullptr;
+
for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
CurPEnd = CurMethod->param_end(),
SuperP = SuperMethod->param_begin();
@@ -5140,11 +5146,11 @@
// Make sure the parameter types are compatible.
if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
(*SuperP)->getType()))
- return 0;
-
+ return nullptr;
+
// Make sure we have a parameter name to forward!
if (!(*CurP)->getIdentifier())
- return 0;
+ return nullptr;
}
// We have a superclass method. Now, form the send-to-super completion.
@@ -5239,7 +5245,7 @@
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression) {
- ObjCInterfaceDecl *CDecl = 0;
+ ObjCInterfaceDecl *CDecl = nullptr;
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
// Figure out which interface we're in.
CDecl = CurMethod->getClassInterface();
@@ -5255,7 +5261,7 @@
// We are inside an instance method, which means that the message
// send [super ...] is actually calling an instance method on the
// current object.
- return CodeCompleteObjCInstanceMessage(S, 0, SelIdents,
+ return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
AtArgumentExpression,
CDecl);
}
@@ -5340,12 +5346,12 @@
bool IsSuper,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
- ObjCInterfaceDecl *CDecl = 0;
-
+ ObjCInterfaceDecl *CDecl = nullptr;
+
// If the given name refers to an interface type, retrieve the
// corresponding declaration.
if (Receiver) {
- QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
+ QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
if (!T.isNull())
if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
CDecl = Interface->getInterface();
@@ -5398,8 +5404,9 @@
MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
continue;
-
- Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
+
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method),
+ nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, SemaRef.CurContext);
@@ -5573,8 +5580,9 @@
if (!Selectors.insert(MethList->Method->getSelector()))
continue;
-
- Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
+
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method),
+ nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, CurContext);
@@ -5690,8 +5698,8 @@
// Record any protocols we find.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
if (!OnlyForwardDeclarations || !Proto->hasDefinition())
- Results.AddResult(Result(Proto, Results.getBasePriority(Proto), 0),
- CurContext, 0, false);
+ Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
+ CurContext, nullptr, false);
}
}
@@ -5757,8 +5765,8 @@
if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
(!OnlyUnimplemented || !Class->getImplementation()))
- Results.AddResult(Result(Class, Results.getBasePriority(Class), 0),
- CurContext, 0, false);
+ Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
+ CurContext, nullptr, false);
}
}
@@ -5851,8 +5859,9 @@
for (const auto *D : TU->decls())
if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
if (CategoryNames.insert(Category->getIdentifier()))
- Results.AddResult(Result(Category, Results.getBasePriority(Category),0),
- CurContext, 0, false);
+ Results.AddResult(Result(Category, Results.getBasePriority(Category),
+ nullptr),
+ CurContext, nullptr, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
@@ -5888,8 +5897,8 @@
for (const auto *Cat : Class->visible_categories()) {
if ((!IgnoreImplemented || !Cat->getImplementation()) &&
CategoryNames.insert(Cat->getIdentifier()))
- Results.AddResult(Result(Cat, Results.getBasePriority(Cat), 0),
- CurContext, 0, false);
+ Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
+ CurContext, nullptr, false);
}
Class = Class->getSuperClass();
@@ -5956,7 +5965,7 @@
return;
// Figure out which interface we're looking into.
- ObjCInterfaceDecl *Class = 0;
+ ObjCInterfaceDecl *Class = nullptr;
if (ObjCImplementationDecl *ClassImpl
= dyn_cast<ObjCImplementationDecl>(Container))
Class = ClassImpl->getClassInterface();
@@ -5988,9 +5997,9 @@
for(; Class; Class = Class->getSuperClass()) {
for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Ivar = Ivar->getNextIvar()) {
- Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), 0),
- CurContext, 0, false);
-
+ Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
+ CurContext, nullptr, false);
+
// Determine whether we've seen an ivar with a name similar to the
// property.
if ((PropertyName == Ivar->getIdentifier() ||
@@ -6183,10 +6192,10 @@
CodeCompletionAllocator &Allocator;
StringRef Key;
const char *CopiedKey;
-
+
KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
- : Allocator(Allocator), Key(Key), CopiedKey(0) { }
-
+ : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
+
operator const char *() {
if (CopiedKey)
return CopiedKey;
@@ -6788,13 +6797,13 @@
// Determine the return type of the method we're declaring, if
// provided.
QualType ReturnType = GetTypeFromParser(ReturnTy);
- Decl *IDecl = 0;
+ Decl *IDecl = nullptr;
if (CurContext->isObjCContainer()) {
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
IDecl = cast<Decl>(OCD);
}
// Determine where we should start searching for methods.
- ObjCContainerDecl *SearchDecl = 0;
+ ObjCContainerDecl *SearchDecl = nullptr;
bool IsInImplementation = false;
if (Decl *D = IDecl) {
if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
@@ -6816,7 +6825,7 @@
if (!SearchDecl) {
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_Other,
- 0, 0);
+ nullptr, 0);
return;
}
@@ -6997,8 +7006,9 @@
continue;
}
-
- Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0);
+
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method),
+ nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
R.DeclaringEntity = true;
@@ -7244,7 +7254,7 @@
void Sema::CodeCompleteNaturalLanguage() {
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_NaturalLanguage,
- 0, 0);
+ nullptr, 0);
}
void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 43d855c..a0ce766 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -25,12 +25,14 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/HeaderSearch.h" // FIXME: Sema shouldn't depend on Lex
-#include "clang/Lex/ModuleLoader.h" // FIXME: Sema shouldn't depend on Lex
-#include "clang/Lex/Preprocessor.h" // FIXME: Sema shouldn't depend on Lex
+#include "clang/Lex/HeaderSearch.h" // TODO: Sema shouldn't depend on Lex
+#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
+#include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex
+#include "clang/Lex/Preprocessor.h" // Included for isCodeCompletionEnabled()
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
@@ -142,7 +144,7 @@
bool WantNontrivialTypeSourceInfo,
IdentifierInfo **CorrectedII) {
// Determine where we will perform name lookup.
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
if (ObjectTypePtr) {
QualType ObjectType = ObjectTypePtr.get();
if (ObjectType->isRecordType())
@@ -170,11 +172,9 @@
return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get();
NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context);
- QualType T =
- CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc,
- II, NameLoc);
-
- return ParsedType::make(T);
+ QualType T = CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc,
+ II, NameLoc);
+ return ParsedType::make(T);
}
return ParsedType();
@@ -210,15 +210,16 @@
// Perform unqualified name lookup.
LookupName(Result, S);
}
-
- NamedDecl *IIDecl = 0;
+
+ NamedDecl *IIDecl = nullptr;
switch (Result.getResultKind()) {
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (CorrectedII) {
TypeNameValidatorCCC Validator(true, isClassName);
TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(),
- Kind, S, SS, Validator);
+ Kind, S, SS, Validator,
+ CTK_ErrorRecovery);
IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
TemplateTy Template;
bool MemberOfUnknownSpecialization;
@@ -308,8 +309,7 @@
if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
DiagnoseUseOfDecl(IIDecl, NameLoc);
- if (T.isNull())
- T = Context.getTypeDeclType(TD);
+ T = Context.getTypeDeclType(TD);
// NOTE: avoid constructing an ElaboratedType(Loc) if this is a
// constructor or destructor name (in such a case, the scope specifier
@@ -408,7 +408,7 @@
TypeNameValidatorCCC Validator(false, false, AllowClassTemplates);
if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc),
LookupOrdinaryName, S, SS,
- Validator)) {
+ Validator, CTK_ErrorRecovery)) {
if (Corrected.isKeyword()) {
// We corrected to a keyword.
diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II);
@@ -513,35 +513,30 @@
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName);
SemaRef.LookupParsedName(R, S, &SS);
if (TagDecl *Tag = R.getAsSingle<TagDecl>()) {
- const char *TagName = 0;
- const char *FixItTagName = 0;
+ StringRef FixItTagName;
switch (Tag->getTagKind()) {
case TTK_Class:
- TagName = "class";
FixItTagName = "class ";
break;
case TTK_Enum:
- TagName = "enum";
FixItTagName = "enum ";
break;
case TTK_Struct:
- TagName = "struct";
FixItTagName = "struct ";
break;
case TTK_Interface:
- TagName = "__interface";
FixItTagName = "__interface ";
break;
case TTK_Union:
- TagName = "union";
FixItTagName = "union ";
break;
}
+ StringRef TagName = FixItTagName.drop_back();
SemaRef.Diag(NameLoc, diag::err_use_of_tag_name_without_tag)
<< Name << TagName << SemaRef.getLangOpts().CPlusPlus
<< FixItHint::CreateInsertion(NameLoc, FixItTagName);
@@ -584,16 +579,15 @@
CorrectionCandidateCallback *CCC) {
DeclarationNameInfo NameInfo(Name, NameLoc);
ObjCMethodDecl *CurMethod = getCurMethodDecl();
-
+
if (NextToken.is(tok::coloncolon)) {
BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(),
- QualType(), false, SS, 0, false);
-
+ QualType(), false, SS, nullptr, false);
}
-
+
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
LookupParsedName(Result, S, &SS, !CurMethod);
-
+
// Perform lookup for Objective-C instance variables (including automatically
// synthesized instance variables), if we're in an Objective-C method.
// FIXME: This lookup really, really needs to be folded in to the normal
@@ -651,13 +645,14 @@
SecondTry = true;
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
Result.getLookupKind(), S,
- &SS, *CCC)) {
+ &SS, *CCC,
+ CTK_ErrorRecovery)) {
unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
unsigned QualifiedDiag = diag::err_no_member_suggest;
NamedDecl *FirstDecl = Corrected.getCorrectionDecl();
NamedDecl *UnderlyingFirstDecl
- = FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
+ = FirstDecl? FirstDecl->getUnderlyingDecl() : nullptr;
if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
UnqualifiedDiag = diag::err_no_template_suggest;
@@ -730,7 +725,7 @@
// keyword here.
return ActOnDependentIdExpression(SS, /*TemplateKWLoc=*/SourceLocation(),
NameInfo, IsAddressOfOperand,
- /*TemplateArgs=*/0);
+ /*TemplateArgs=*/nullptr);
}
case LookupResult::Found:
@@ -822,8 +817,8 @@
ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl);
if (!Class) {
// FIXME: It's unfortunate that we don't have a Type node for handling this.
- if (ObjCCompatibleAliasDecl *Alias
- = dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl))
+ if (ObjCCompatibleAliasDecl *Alias =
+ dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl))
Class = Alias->getClassInterface();
}
@@ -862,7 +857,8 @@
}
if (FirstDecl->isCXXClassMember())
- return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0);
+ return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result,
+ nullptr);
bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
return BuildDeclarationNameExpr(SS, Result, ADL);
@@ -1101,7 +1097,7 @@
return S;
} while ((S = S->getParent()));
- return 0;
+ return nullptr;
}
static bool isOutOfScopePreviousDeclaration(NamedDecl *,
@@ -1219,8 +1215,7 @@
return false;
} else {
// 'static inline' functions are defined in headers; don't warn.
- if (FD->isInlineSpecified() &&
- !isMainFileLoc(*this, FD->getLocation()))
+ if (FD->isInlined() && !isMainFileLoc(*this, FD->getLocation()))
return false;
}
@@ -1245,6 +1240,8 @@
}
// Only warn for unused decls internal to the translation unit.
+ // FIXME: This seems like a bogus check; it suppresses -Wunused-function
+ // for inline functions defined in the main source file, for instance.
return mightHaveNonExternalLinkage(D);
}
@@ -1311,7 +1308,8 @@
return false;
if (const Expr *Init = VD->getInit()) {
- if (const ExprWithCleanups *Cleanups = dyn_cast<ExprWithCleanups>(Init))
+ if (const ExprWithCleanups *Cleanups =
+ dyn_cast<ExprWithCleanups>(Init))
Init = Cleanups->getSubExpr();
const CXXConstructExpr *Construct =
dyn_cast<CXXConstructExpr>(Init);
@@ -1346,10 +1344,10 @@
/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used
/// unless they are marked attr(unused).
void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
- FixItHint Hint;
if (!ShouldDiagnoseUnusedDecl(D))
return;
+ FixItHint Hint;
GenerateFixForUnusedDecl(D, Context, Hint);
unsigned DiagID;
@@ -1367,11 +1365,13 @@
// Verify that we have no forward references left. If so, there was a goto
// or address of a label taken, but no definition of it. Label fwd
// definitions are indicated with a null substmt.
- if (L->getStmt() == 0)
+ if (L->getStmt() == nullptr)
S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
+ S->mergeNRVOIntoParent();
+
if (S->decl_empty()) return;
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
"Scope shouldn't contain decls!");
@@ -1422,8 +1422,8 @@
// find an Objective-C class name.
DeclFilterCCC<ObjCInterfaceDecl> Validator;
if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc),
- LookupOrdinaryName, TUScope, NULL,
- Validator)) {
+ LookupOrdinaryName, TUScope, nullptr,
+ Validator, CTK_ErrorRecovery)) {
diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);
IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
Id = IDecl->getIdentifier();
@@ -1507,19 +1507,19 @@
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_stdio)
<< Context.BuiltinInfo.GetName(BID);
- return 0;
+ return nullptr;
case ASTContext::GE_Missing_setjmp:
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_setjmp)
<< Context.BuiltinInfo.GetName(BID);
- return 0;
+ return nullptr;
case ASTContext::GE_Missing_ucontext:
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_ucontext)
<< Context.BuiltinInfo.GetName(BID);
- return 0;
+ return nullptr;
}
if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
@@ -1546,7 +1546,7 @@
FunctionDecl *New = FunctionDecl::Create(Context,
Parent,
- Loc, Loc, II, R, /*TInfo=*/0,
+ Loc, Loc, II, R, /*TInfo=*/nullptr,
SC_Extern,
false,
/*hasPrototype=*/true);
@@ -1559,7 +1559,8 @@
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
ParmVarDecl *parm =
ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(),
- 0, FT->getParamType(i), /*TInfo=*/0, SC_None, 0);
+ nullptr, FT->getParamType(i), /*TInfo=*/nullptr,
+ SC_None, nullptr);
parm->setScopeInfo(0, i);
Params.push_back(parm);
}
@@ -1820,8 +1821,8 @@
static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
// Look for alignas attributes on Old, and pick out whichever attribute
// specifies the strictest alignment requirement.
- AlignedAttr *OldAlignasAttr = 0;
- AlignedAttr *OldStrictestAlignAttr = 0;
+ AlignedAttr *OldAlignasAttr = nullptr;
+ AlignedAttr *OldStrictestAlignAttr = nullptr;
unsigned OldAlign = 0;
for (auto *I : Old->specific_attrs<AlignedAttr>()) {
// FIXME: We have no way of representing inherited dependent alignments
@@ -1844,7 +1845,7 @@
}
// Look for alignas attributes on New.
- AlignedAttr *NewAlignasAttr = 0;
+ AlignedAttr *NewAlignasAttr = nullptr;
unsigned NewAlign = 0;
for (auto *I : New->specific_attrs<AlignedAttr>()) {
if (I->isAlignmentDependent())
@@ -1924,43 +1925,43 @@
return AnyAdded;
}
-static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr,
- bool Override) {
- InheritableAttr *NewAttr = NULL;
+static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
+ const InheritableAttr *Attr, bool Override) {
+ InheritableAttr *NewAttr = nullptr;
unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
- if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr))
+ if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr))
NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
AA->getIntroduced(), AA->getDeprecated(),
AA->getObsoleted(), AA->getUnavailable(),
AA->getMessage(), Override,
AttrSpellingListIndex);
- else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr))
+ else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr))
NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
AttrSpellingListIndex);
- else if (TypeVisibilityAttr *VA = dyn_cast<TypeVisibilityAttr>(Attr))
+ else if (const auto *VA = dyn_cast<TypeVisibilityAttr>(Attr))
NewAttr = S.mergeTypeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
AttrSpellingListIndex);
- else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr))
+ else if (const auto *ImportA = dyn_cast<DLLImportAttr>(Attr))
NewAttr = S.mergeDLLImportAttr(D, ImportA->getRange(),
AttrSpellingListIndex);
- else if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr))
+ else if (const auto *ExportA = dyn_cast<DLLExportAttr>(Attr))
NewAttr = S.mergeDLLExportAttr(D, ExportA->getRange(),
AttrSpellingListIndex);
- else if (FormatAttr *FA = dyn_cast<FormatAttr>(Attr))
+ else if (const auto *FA = dyn_cast<FormatAttr>(Attr))
NewAttr = S.mergeFormatAttr(D, FA->getRange(), FA->getType(),
FA->getFormatIdx(), FA->getFirstArg(),
AttrSpellingListIndex);
- else if (SectionAttr *SA = dyn_cast<SectionAttr>(Attr))
+ else if (const auto *SA = dyn_cast<SectionAttr>(Attr))
NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
AttrSpellingListIndex);
- else if (MSInheritanceAttr *IA = dyn_cast<MSInheritanceAttr>(Attr))
+ else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr))
NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
AttrSpellingListIndex,
IA->getSemanticSpelling());
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
- NewAttr = 0;
+ NewAttr = nullptr;
else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
@@ -1987,7 +1988,7 @@
if (FD->isDefined(Def))
return Def;
}
- return NULL;
+ return nullptr;
}
static bool hasAttribute(const Decl *D, attr::Kind Kind) {
@@ -2279,7 +2280,7 @@
!Old->getDeclContext()->getRedeclContext()->Equals(
New->getDeclContext()->getRedeclContext()) &&
!(Old->isExternC() && New->isExternC()))
- Old = 0;
+ Old = nullptr;
if (!Old) {
Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
@@ -2642,7 +2643,7 @@
Context.typesAreCompatible(OldQType, NewQType)) {
const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
- const FunctionProtoType *OldProto = 0;
+ const FunctionProtoType *OldProto = nullptr;
if (MergeTypeWithOld && isa<FunctionNoProtoType>(NewFuncType) &&
(OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
// The old declaration provided a function prototype, but the
@@ -2655,12 +2656,13 @@
New->setType(NewQType);
New->setHasInheritedPrototype();
- // Synthesize a parameter for each argument type.
+ // Synthesize parameters with the same types.
SmallVector<ParmVarDecl*, 16> Params;
for (const auto &ParamType : OldProto->param_types()) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, New, SourceLocation(),
- SourceLocation(), 0, ParamType,
- /*TInfo=*/0, SC_None, 0);
+ SourceLocation(), nullptr,
+ ParamType, /*TInfo=*/nullptr,
+ SC_None, nullptr);
Param->setScopeInfo(0, Params.size());
Param->setImplicit();
Params.push_back(Param);
@@ -2968,12 +2970,12 @@
VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate();
// Verify the old decl was also a variable or variable template.
- VarDecl *Old = 0;
- VarTemplateDecl *OldTemplate = 0;
+ VarDecl *Old = nullptr;
+ VarTemplateDecl *OldTemplate = nullptr;
if (Previous.isSingleResult()) {
if (NewTemplate) {
OldTemplate = dyn_cast<VarTemplateDecl>(Previous.getFoundDecl());
- Old = OldTemplate ? OldTemplate->getTemplatedDecl() : 0;
+ Old = OldTemplate ? OldTemplate->getTemplatedDecl() : nullptr;
} else
Old = dyn_cast<VarDecl>(Previous.getFoundDecl());
}
@@ -3170,8 +3172,8 @@
DeclSpec &DS,
MultiTemplateParamsArg TemplateParams,
bool IsExplicitInstantiation) {
- Decl *TagD = 0;
- TagDecl *Tag = 0;
+ Decl *TagD = nullptr;
+ TagDecl *Tag = nullptr;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
DS.getTypeSpecType() == DeclSpec::TST_struct ||
DS.getTypeSpecType() == DeclSpec::TST_interface ||
@@ -3180,7 +3182,7 @@
TagD = DS.getRepAsDecl();
if (!TagD) // We probably had an error
- return 0;
+ return nullptr;
// Note that the above type specs guarantee that the
// type rep is a Decl, whereas in many of the others
@@ -3228,7 +3230,7 @@
// If we're dealing with a decl but not a TagDecl, assume that
// whatever routines created it handled the friendship aspect.
if (TagD && !Tag)
- return 0;
+ return nullptr;
return ActOnFriendTypeDecl(S, DS, TemplateParams);
}
@@ -3247,7 +3249,7 @@
DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4)
<< SS.getRange();
- return 0;
+ return nullptr;
}
// Track whether this decl-specifier declares anything.
@@ -3342,10 +3344,15 @@
// Note that a linkage-specification sets a storage class, but
// 'extern "C" struct foo;' is actually valid and not theoretically
// useless.
- if (DeclSpec::SCS SCS = DS.getStorageClassSpec())
- if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef)
+ if (DeclSpec::SCS SCS = DS.getStorageClassSpec()) {
+ if (SCS == DeclSpec::SCS_mutable)
+ // Since mutable is not a viable storage class specifier in C, there is
+ // no reason to treat it as an extension. Instead, diagnose as an error.
+ Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_nonmember);
+ else if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef)
Diag(DS.getStorageClassSpecLoc(), DiagID)
<< DeclSpec::getSpecifierName(SCS);
+ }
if (DeclSpec::TSCS TSCS = DS.getThreadStorageClassSpec())
Diag(DS.getThreadStorageClassSpecLoc(), DiagID)
@@ -3573,7 +3580,7 @@
// structs/unions.
bool Invalid = false;
if (getLangOpts().CPlusPlus) {
- const char* PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
if (Record->isUnion()) {
// C++ [class.union]p6:
@@ -3729,15 +3736,15 @@
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
// Create a declaration for this anonymous struct/union.
- NamedDecl *Anon = 0;
+ NamedDecl *Anon = nullptr;
if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
Anon = FieldDecl::Create(Context, OwningClass,
DS.getLocStart(),
Record->getLocation(),
- /*IdentifierInfo=*/0,
+ /*IdentifierInfo=*/nullptr,
Context.getTypeDeclType(Record),
TInfo,
- /*BitWidth=*/0, /*Mutable=*/false,
+ /*BitWidth=*/nullptr, /*Mutable=*/false,
/*InitStyle=*/ICIS_NoInit);
Anon->setAccess(AS);
if (getLangOpts().CPlusPlus)
@@ -3755,7 +3762,7 @@
Anon = VarDecl::Create(Context, Owner,
DS.getLocStart(),
- Record->getLocation(), /*IdentifierInfo=*/0,
+ Record->getLocation(), /*IdentifierInfo=*/nullptr,
Context.getTypeDeclType(Record),
TInfo, SC);
@@ -3829,14 +3836,14 @@
assert(TInfo && "couldn't build declarator info for anonymous struct");
// Create a declaration for this anonymous struct.
- NamedDecl* Anon = FieldDecl::Create(Context,
+ NamedDecl *Anon = FieldDecl::Create(Context,
cast<RecordDecl>(CurContext),
DS.getLocStart(),
DS.getLocStart(),
- /*IdentifierInfo=*/0,
+ /*IdentifierInfo=*/nullptr,
Context.getTypeDeclType(Record),
TInfo,
- /*BitWidth=*/0, /*Mutable=*/false,
+ /*BitWidth=*/nullptr, /*Mutable=*/false,
/*InitStyle=*/ICIS_NoInit);
Anon->setImplicit();
@@ -3938,7 +3945,7 @@
Context.getCanonicalType(CurClassType)));
NameInfo.setLoc(Name.StartLocation);
// FIXME: should we retrieve TypeSourceInfo?
- NameInfo.setNamedTypeInfo(0);
+ NameInfo.setNamedTypeInfo(nullptr);
return NameInfo;
}
@@ -4034,7 +4041,7 @@
case DeclSpec::TST_underlyingType:
case DeclSpec::TST_atomic: {
// Grab the type from the parser.
- TypeSourceInfo *TSI = 0;
+ TypeSourceInfo *TSI = nullptr;
QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
if (T.isNull() || !T->isDependentType()) break;
@@ -4226,9 +4233,9 @@
Diag(D.getDeclSpec().getLocStart(),
diag::err_declarator_need_ident)
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
- return 0;
+ return nullptr;
} else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
- return 0;
+ return nullptr;
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
@@ -4242,7 +4249,7 @@
else if (D.getCXXScopeSpec().isSet()) {
if (DiagnoseUnexpandedParameterPack(D.getCXXScopeSpec(),
UPPC_DeclarationQualifier))
- return 0;
+ return nullptr;
bool EnteringContext = !D.getDeclSpec().isFriendSpecified();
DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext);
@@ -4255,13 +4262,13 @@
diag::err_template_qualified_declarator_no_match)
<< D.getCXXScopeSpec().getScopeRep()
<< D.getCXXScopeSpec().getRange();
- return 0;
+ return nullptr;
}
bool IsDependentContext = DC->isDependentContext();
if (!IsDependentContext &&
RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
- return 0;
+ return nullptr;
if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
Diag(D.getIdentifierLoc(),
@@ -4272,8 +4279,8 @@
if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
Name, D.getIdentifierLoc())) {
if (DC->isRecord())
- return 0;
-
+ return nullptr;
+
D.setInvalidType();
}
}
@@ -4292,8 +4299,8 @@
// If this is a typedef, we'll end up spewing multiple diagnostics.
// Just return early; it's safer.
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- return 0;
-
+ return nullptr;
+
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
@@ -4394,7 +4401,7 @@
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
if (TemplateParamLists.size()) {
Diag(D.getIdentifierLoc(), diag::err_template_typedef);
- return 0;
+ return nullptr;
}
New = ActOnTypedefDeclarator(S, D, DC, TInfo, Previous);
@@ -4407,8 +4414,8 @@
AddToScope);
}
- if (New == 0)
- return 0;
+ if (!New)
+ return nullptr;
// If this has an identifier and is not an invalid redeclaration or
// function template specialization, add it to the scope stack.
@@ -4535,7 +4542,7 @@
= TryToFixInvalidVariablyModifiedType(TInfo->getType(), Context,
SizeIsNegative, Oversized);
if (FixedTy.isNull())
- return 0;
+ return nullptr;
TypeSourceInfo *FixedTInfo = Context.getTrivialTypeSourceInfo(FixedTy);
FixInvalidVariablyModifiedTypeLoc(TInfo->getTypeLoc(),
FixedTInfo->getTypeLoc());
@@ -4574,7 +4581,7 @@
}
NamedDecl *D = LocallyScopedExternCDecls.lookup(Name);
- return D ? D->getMostRecentDecl() : 0;
+ return D ? D->getMostRecentDecl() : nullptr;
}
/// \brief Diagnose function specifiers on a declaration of an identifier that
@@ -4621,11 +4628,11 @@
if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
Diag(D.getName().StartLocation, diag::err_typedef_not_identifier)
<< D.getName().getSourceRange();
- return 0;
+ return nullptr;
}
TypedefDecl *NewTD = ParseTypedefDecl(S, D, TInfo->getType(), TInfo);
- if (!NewTD) return 0;
+ if (!NewTD) return nullptr;
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewTD, D);
@@ -4649,7 +4656,7 @@
if (T->isVariablyModifiedType()) {
getCurFunction()->setHasBranchProtectedScope();
- if (S->getFnParent() == 0) {
+ if (S->getFnParent() == nullptr) {
bool SizeIsNegative;
llvm::APSInt Oversized;
TypeSourceInfo *FixedTInfo =
@@ -4899,9 +4906,11 @@
// A redeclaration is not allowed to drop a dllimport attribute, the only
// exception being inline function definitions.
- // FIXME: Handle inline functions.
// NB: MSVC converts such a declaration to dllexport.
- if (OldImportAttr && !HasNewAttr) {
+ bool IsInline =
+ isa<FunctionDecl>(NewDecl) && cast<FunctionDecl>(NewDecl)->isInlined();
+
+ if (OldImportAttr && !HasNewAttr && !IsInline) {
S.Diag(NewDecl->getLocation(),
diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
<< NewDecl << OldImportAttr;
@@ -4935,7 +4944,8 @@
FD->setLazyBody(1);
#endif
- bool isC99Inline = (S.Context.GetGVALinkageForFunction(FD) == GVA_C99Inline);
+ bool isC99Inline =
+ S.Context.GetGVALinkageForFunction(FD) == GVA_AvailableExternally;
#ifndef NDEBUG
FD->setLazyBody(0);
@@ -5054,7 +5064,8 @@
// dllimport globals without explicit storage class are treated as extern. We
// have to change the storage class this early to get the right DeclContext.
if (SC == SC_None && !DC->isRecord() &&
- hasParsedAttr(S, D, AttributeList::AT_DLLImport))
+ hasParsedAttr(S, D, AttributeList::AT_DLLImport) &&
+ !hasParsedAttr(S, D, AttributeList::AT_DLLExport))
SC = SC_Extern;
DeclContext *OriginalDC = DC;
@@ -5106,21 +5117,17 @@
if (!II) {
Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
<< Name;
- return 0;
+ return nullptr;
}
DiagnoseFunctionSpecifiers(D.getDeclSpec());
- if (!DC->isRecord() && S->getFnParent() == 0) {
+ if (!DC->isRecord() && S->getFnParent() == nullptr) {
// C99 6.9p2: The storage-class specifiers auto and register shall not
// appear in the declaration specifiers in an external declaration.
- if (SC == SC_Auto || SC == SC_Register) {
- // If this is a register variable with an asm label specified, then this
- // is a GNU extension.
- if (SC == SC_Register && D.getAsmLabel())
- Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register);
- else
- Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
+ // Global Register+Asm is a GNU extension we support.
+ if (SC == SC_Auto || (SC == SC_Register && !D.getAsmLabel())) {
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
D.setInvalidType();
}
}
@@ -5145,7 +5152,7 @@
// The event type cannot be used with the __local, __constant and __global
// address space qualifiers.
if (R->isEventT()) {
- if (S->getParent() == 0) {
+ if (S->getParent() == nullptr) {
Diag(D.getLocStart(), diag::err_event_t_global_var);
D.setInvalidType();
}
@@ -5161,9 +5168,9 @@
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
bool IsVariableTemplate = false;
- VarDecl *NewVD = 0;
- VarTemplateDecl *NewTemplate = 0;
- TemplateParameterList *TemplateParams = 0;
+ VarDecl *NewVD = nullptr;
+ VarTemplateDecl *NewTemplate = nullptr;
+ TemplateParameterList *TemplateParams = nullptr;
if (!getLangOpts().CPlusPlus) {
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
@@ -5229,29 +5236,13 @@
// determine whether we have a template or a template specialization.
TemplateParams = MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
- D.getCXXScopeSpec(), TemplateParamLists,
+ D.getCXXScopeSpec(),
+ D.getName().getKind() == UnqualifiedId::IK_TemplateId
+ ? D.getName().TemplateId
+ : nullptr,
+ TemplateParamLists,
/*never a friend*/ false, IsExplicitSpecialization, Invalid);
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
- !TemplateParams) {
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
-
- // We have encountered something that the user meant to be a
- // specialization (because it has explicitly-specified template
- // arguments) but that was not introduced with a "template<>" (or had
- // too few of them).
- // FIXME: Differentiate between attempts for explicit instantiations
- // (starting with "template") and the rest.
- Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
- << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
- << FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),
- "template<> ");
- IsExplicitSpecialization = true;
- TemplateParams = TemplateParameterList::Create(Context, SourceLocation(),
- SourceLocation(), 0, 0,
- SourceLocation());
- }
-
if (TemplateParams) {
if (!TemplateParams->size() &&
D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
@@ -5262,14 +5253,8 @@
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
- TemplateParams = 0;
+ TemplateParams = nullptr;
} else {
- // Only C++1y supports variable templates (N3651).
- Diag(D.getIdentifierLoc(),
- getLangOpts().CPlusPlus1y
- ? diag::warn_cxx11_compat_variable_template
- : diag::ext_variable_template);
-
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
// This is an explicit specialization or a partial specialization.
// FIXME: Check that we can declare a specialization here.
@@ -5281,9 +5266,18 @@
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
- return 0;
+ return nullptr;
+
+ // Only C++1y supports variable templates (N3651).
+ Diag(D.getIdentifierLoc(),
+ getLangOpts().CPlusPlus1y
+ ? diag::warn_cxx11_compat_variable_template
+ : diag::ext_variable_template);
}
}
+ } else {
+ assert(D.getName().getKind() != UnqualifiedId::IK_TemplateId &&
+ "should have a 'template<>' for this decl");
}
if (IsVariableTemplateSpecialization) {
@@ -5295,7 +5289,7 @@
S, D, TInfo, TemplateKWLoc, TemplateParams, SC,
IsPartialSpecialization);
if (Res.isInvalid())
- return 0;
+ return nullptr;
NewVD = cast<VarDecl>(Res.get());
AddToScope = false;
} else
@@ -5376,7 +5370,7 @@
// that a local variable with thread storage duration still has to
// be marked 'static'. Also note that it's possible to get these
// semantics in C++ using __attribute__((gnu_inline)).
- if (SC == SC_Static && S->getFnParent() != 0 &&
+ if (SC == SC_Static && S->getFnParent() != nullptr &&
!NewVD->getType().isConstQualified()) {
FunctionDecl *CurFD = getCurFunctionDecl();
if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) {
@@ -5414,7 +5408,7 @@
if (getLangOpts().CUDA) {
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
// storage [duration]."
- if (SC == SC_None && S->getFnParent() != 0 &&
+ if (SC == SC_None && S->getFnParent() != nullptr &&
(NewVD->hasAttr<CUDASharedAttr>() ||
NewVD->hasAttr<CUDAConstantAttr>())) {
NewVD->setStorageClass(SC_Static);
@@ -5438,13 +5432,14 @@
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
StringRef Label = SE->getString();
- if (S->getFnParent() != 0) {
+ if (S->getFnParent() != nullptr) {
switch (SC) {
case SC_None:
case SC_Auto:
Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label;
break;
case SC_Register:
+ // Local Named register
if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
break;
@@ -5454,6 +5449,10 @@
case SC_OpenCLWorkGroupLocal:
break;
}
+ } else if (SC == SC_Register) {
+ // Global Named register
+ if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
+ Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
}
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
@@ -5522,7 +5521,7 @@
VarTemplateDecl *PrevVarTemplate =
NewVD->getPreviousDecl()
? NewVD->getPreviousDecl()->getDescribedVarTemplate()
- : 0;
+ : nullptr;
// Check the template parameter list of this declaration, possibly
// merging in the template parameter list from the previous variable
@@ -5530,7 +5529,7 @@
if (CheckTemplateParameterList(
TemplateParams,
PrevVarTemplate ? PrevVarTemplate->getTemplateParameters()
- : 0,
+ : nullptr,
(D.getCXXScopeSpec().isSet() && DC && DC->isRecord() &&
DC->isDependentContext())
? TPC_ClassTemplateMember
@@ -5865,7 +5864,7 @@
TypeSourceInfo *FixedTInfo =
TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
SizeIsNegative, Oversized);
- if (FixedTInfo == 0 && T->isVariableArrayType()) {
+ if (!FixedTInfo && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
// FIXME: This won't give the correct result for
// int a[10][n];
@@ -5884,7 +5883,7 @@
return;
}
- if (FixedTInfo == 0) {
+ if (!FixedTInfo) {
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
else
@@ -6087,7 +6086,7 @@
DifferentNameValidatorCCC(ASTContext &Context, FunctionDecl *TypoFD,
CXXRecordDecl *Parent)
: Context(Context), OriginalFD(TypoFD),
- ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {}
+ ExpectedParent(Parent ? Parent->getCanonicalDecl() : nullptr) {}
bool ValidateCandidate(const TypoCorrection &candidate) override {
if (candidate.getEditDistance() == 0)
@@ -6156,7 +6155,7 @@
"Cannot have an ambiguity in previous-declaration lookup");
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
DifferentNameValidatorCCC Validator(SemaRef.Context, NewFD,
- MD ? MD->getParent() : 0);
+ MD ? MD->getParent() : nullptr);
if (!Prev.empty()) {
for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
Func != FuncEnd; ++Func) {
@@ -6174,7 +6173,7 @@
} else if ((Correction = SemaRef.CorrectTypo(
Prev.getLookupNameInfo(), Prev.getLookupKind(), S,
&ExtraArgs.D.getCXXScopeSpec(), Validator,
- IsLocalFriend ? 0 : NewDC))) {
+ Sema::CTK_ErrorRecovery, IsLocalFriend ? nullptr : NewDC))) {
// Set up everything for the call to ActOnFunctionDeclarator
ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(),
ExtraArgs.D.getIdentifierLoc());
@@ -6208,7 +6207,7 @@
ExtraArgs.AddToScope);
if (Trap.hasErrorOccurred())
- Result = 0;
+ Result = nullptr;
}
if (Result) {
@@ -6268,7 +6267,7 @@
IsMember ? diag::note_member_def_close_match
: diag::note_local_decl_close_match);
}
- return 0;
+ return nullptr;
}
static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef,
@@ -6315,7 +6314,7 @@
DeclarationNameInfo NameInfo = SemaRef.GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
- FunctionDecl *NewFD = 0;
+ FunctionDecl *NewFD = nullptr;
bool isInline = D.getDeclSpec().isInlineSpecified();
if (!SemaRef.getLangOpts().CPlusPlus) {
@@ -6405,7 +6404,7 @@
if (!DC->isRecord()) {
SemaRef.Diag(D.getIdentifierLoc(),
diag::err_conv_function_not_member);
- return 0;
+ return nullptr;
}
SemaRef.CheckConversionDeclarator(D, R, SC);
@@ -6425,7 +6424,7 @@
SemaRef.Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
- return 0;
+ return nullptr;
}
// This is a C++ method declaration.
@@ -6544,7 +6543,7 @@
// Track where we are in the nested structs. Items will migrate from
// VisitStack to HistoryStack as we do the DFS for bad field.
SmallVector<const FieldDecl *, 4> HistoryStack;
- HistoryStack.push_back((const FieldDecl *) 0);
+ HistoryStack.push_back(nullptr);
const RecordDecl *PD = PT->castAs<RecordType>()->getDecl();
VisitStack.push_back(PD);
@@ -6573,7 +6572,7 @@
}
// Add a null marker so we know when we've gone back up a level
- VisitStack.push_back((const Decl *) 0);
+ VisitStack.push_back(nullptr);
for (const auto *FD : RD->fields()) {
QualType QT = FD->getType();
@@ -6648,7 +6647,7 @@
adjustMemberFunctionCC(R, D.isStaticMember());
bool isFriend = false;
- FunctionTemplateDecl *FunctionTemplate = 0;
+ FunctionTemplateDecl *FunctionTemplate = nullptr;
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
@@ -6663,7 +6662,7 @@
FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC,
isVirtualOkay);
- if (!NewFD) return 0;
+ if (!NewFD) return nullptr;
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer())
NewFD->setTopLevelDeclInObjCContainer();
@@ -6710,19 +6709,23 @@
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
- D.getCXXScopeSpec(), TemplateParamLists, isFriend,
- isExplicitSpecialization, Invalid)) {
+ D.getCXXScopeSpec(),
+ D.getName().getKind() == UnqualifiedId::IK_TemplateId
+ ? D.getName().TemplateId
+ : nullptr,
+ TemplateParamLists, isFriend, isExplicitSpecialization,
+ Invalid)) {
if (TemplateParams->size() > 0) {
// This is a function template
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
- return 0;
+ return nullptr;
// A destructor cannot be a template.
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(NewFD->getLocation(), diag::err_destructor_template);
- return 0;
+ return nullptr;
}
// If we're adding a template to a dependent context, we may need to
@@ -6752,9 +6755,10 @@
// This is a function template specialization.
isFunctionTemplateSpecialization = true;
// For source fidelity, store all the template param lists.
- NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size(),
- TemplateParamLists.data());
+ if (TemplateParamLists.size() > 0)
+ NewFD->setTemplateParameterListsInfo(Context,
+ TemplateParamLists.size(),
+ TemplateParamLists.data());
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
if (isFriend) {
@@ -6769,7 +6773,7 @@
SourceLocation InsertLoc;
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
InsertLoc = D.getName().getSourceRange().getEnd();
- InsertLoc = PP.getLocForEndOfToken(InsertLoc);
+ InsertLoc = getLocForEndOfToken(InsertLoc);
}
Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
@@ -6996,11 +7000,7 @@
// single void argument.
// We let through "const void" here because Sema::GetTypeForDeclarator
// already checks for that case.
- if (FTI.NumParams == 1 && !FTI.isVariadic && FTI.Params[0].Ident == 0 &&
- FTI.Params[0].Param &&
- cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType()) {
- // Empty arg list, don't push any params.
- } else if (FTI.NumParams > 0 && FTI.Params[0].Param != 0) {
+ if (FTIHasNonVoidParameters(FTI) && FTI.Params[0].Param) {
for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
assert(Param->getDeclContext() != NewFD && "Was set before ?");
@@ -7059,6 +7059,17 @@
NewFD->setInvalidDecl();
}
+ if (D.isFunctionDefinition() && CodeSegStack.CurrentValue &&
+ !NewFD->hasAttr<SectionAttr>()) {
+ NewFD->addAttr(
+ SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate,
+ CodeSegStack.CurrentValue->getString(),
+ CodeSegStack.CurrentPragmaLocation));
+ if (UnifySection(CodeSegStack.CurrentValue->getString(),
+ PSF_Implicit | PSF_Execute | PSF_Read, NewFD))
+ NewFD->dropAttr<SectionAttr>();
+ }
+
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
@@ -7142,21 +7153,10 @@
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
HasExplicitTemplateArgs = false;
- } else if (!isFunctionTemplateSpecialization &&
- !D.getDeclSpec().isFriendSpecified()) {
- // We have encountered something that the user meant to be a
- // specialization (because it has explicitly-specified template
- // arguments) but that was not introduced with a "template<>" (or had
- // too few of them).
- // FIXME: Differentiate between attempts for explicit instantiations
- // (starting with "template") and the rest.
- Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
- << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
- << FixItHint::CreateInsertion(
- D.getDeclSpec().getLocStart(),
- "template<> ");
- isFunctionTemplateSpecialization = true;
} else {
+ assert((isFunctionTemplateSpecialization ||
+ D.getDeclSpec().isFriendSpecified()) &&
+ "should have a 'template<>' for this decl");
// "friend void foo<>(int);" is an implicit specialization decl.
isFunctionTemplateSpecialization = true;
}
@@ -7168,7 +7168,7 @@
// friend void foo<>(int);
// Go ahead and fake up a template id.
HasExplicitTemplateArgs = true;
- TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
+ TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
}
@@ -7196,7 +7196,8 @@
diag::err_function_specialization_in_class)
<< NewFD->getDeclName();
} else if (CheckFunctionTemplateSpecialization(NewFD,
- (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+ (HasExplicitTemplateArgs ? &TemplateArgs
+ : nullptr),
Previous))
NewFD->setInvalidDecl();
@@ -7265,7 +7266,8 @@
FunctionTemplateDecl *PrevTemplate =
FunctionTemplate->getPreviousDecl();
CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(),
- PrevTemplate ? PrevTemplate->getTemplateParameters() : 0,
+ PrevTemplate ? PrevTemplate->getTemplateParameters()
+ : nullptr,
D.getDeclSpec().isFriendSpecified()
? (D.isFunctionDefinition()
? TPC_FriendFunctionTemplateDefinition
@@ -7319,7 +7321,7 @@
// whether the parameter types are references).
if (NamedDecl *Result = DiagnoseInvalidRedeclaration(
- *this, Previous, NewFD, ExtraArgs, false, 0)) {
+ *this, Previous, NewFD, ExtraArgs, false, nullptr)) {
AddToScope = ExtraArgs.AddToScope;
return Result;
}
@@ -7382,6 +7384,11 @@
// marking the function.
AddCFAuditedAttribute(NewFD);
+ // If this is a function definition, check if we have to apply optnone due to
+ // a pragma.
+ if(D.isFunctionDefinition())
+ AddRangeBasedOptnone(NewFD);
+
// If this is the first declaration of an extern C variable, update
// the map of such variables.
if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() &&
@@ -7487,7 +7494,7 @@
filterNonConflictingPreviousDecls(Context, NewFD, Previous);
bool Redeclaration = false;
- NamedDecl *OldDecl = 0;
+ NamedDecl *OldDecl = nullptr;
// Merge or overload the declaration with an existing declaration of
// the same name, if appropriate.
@@ -7523,7 +7530,7 @@
// with that name must be marked "overloadable".
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
<< Redeclaration << NewFD;
- NamedDecl *OverloadedDecl = 0;
+ NamedDecl *OverloadedDecl = nullptr;
if (Redeclaration)
OverloadedDecl = OldDecl;
else if (!Previous.empty())
@@ -7558,7 +7565,7 @@
}
if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {
Redeclaration = false;
- OldDecl = 0;
+ OldDecl = nullptr;
}
}
}
@@ -7577,7 +7584,7 @@
if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() &&
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
(MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
- CXXMethodDecl *OldMD = 0;
+ CXXMethodDecl *OldMD = nullptr;
if (OldDecl)
OldMD = dyn_cast<CXXMethodDecl>(OldDecl->getAsFunction());
if (!OldMD || !OldMD->isStatic()) {
@@ -7594,7 +7601,7 @@
SourceLocation AddConstLoc;
if (FunctionTypeLoc FTL = MD->getTypeSourceInfo()->getTypeLoc()
.IgnoreParens().getAs<FunctionTypeLoc>())
- AddConstLoc = PP.getLocForEndOfToken(FTL.getRParenLoc());
+ AddConstLoc = getLocForEndOfToken(FTL.getRParenLoc());
Diag(MD->getLocation(), diag::warn_cxx1y_compat_constexpr_not_const)
<< FixItHint::CreateInsertion(AddConstLoc, " const");
@@ -7790,8 +7797,7 @@
<< FixItHint::CreateRemoval(DS.getInlineSpecLoc());
if (DS.isNoreturnSpecified()) {
SourceLocation NoreturnLoc = DS.getNoreturnSpecLoc();
- SourceRange NoreturnRange(NoreturnLoc,
- PP.getLocForEndOfToken(NoreturnLoc));
+ SourceRange NoreturnRange(NoreturnLoc, getLocForEndOfToken(NoreturnLoc));
Diag(NoreturnLoc, diag::ext_noreturn_main);
Diag(NoreturnLoc, diag::note_main_remove_noreturn)
<< FixItHint::CreateRemoval(NoreturnRange);
@@ -7941,10 +7947,11 @@
// "may accept other forms of constant expressions" exception.
// (We never end up here for C++, so the constant expression
// rules there don't matter.)
- if (Init->isConstantInitializer(Context, false))
+ const Expr *Culprit;
+ if (Init->isConstantInitializer(Context, false, &Culprit))
return false;
- Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
- << Init->getSourceRange();
+ Diag(Culprit->getExprLoc(), diag::err_init_element_not_constant)
+ << Culprit->getSourceRange();
return true;
}
@@ -8118,7 +8125,7 @@
bool DirectInit, bool TypeMayContainAuto) {
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
- if (RealDecl == 0 || RealDecl->isInvalidDecl())
+ if (!RealDecl || RealDecl->isInvalidDecl())
return;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
@@ -8277,8 +8284,8 @@
VDecl->setInvalidDecl();
return;
}
-
- const VarDecl* PrevInit = 0;
+
+ const VarDecl *PrevInit = nullptr;
if (getLangOpts().CPlusPlus) {
// C++ [class.static.data]p4
// If a static data member is of const integral or const
@@ -8425,6 +8432,7 @@
// static storage duration shall be constant expressions or string literals.
// C++ does not have this restriction.
if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) {
+ const Expr *Culprit;
if (VDecl->getStorageClass() == SC_Static)
CheckForConstantInitializer(Init, DclT);
// C89 is stricter than C99 for non-static aggregate types.
@@ -8433,10 +8441,10 @@
// constant expressions.
else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() &&
isa<InitListExpr>(Init) &&
- !Init->isConstantInitializer(Context, false))
- Diag(Init->getExprLoc(),
+ !Init->isConstantInitializer(Context, false, &Culprit))
+ Diag(Culprit->getExprLoc(),
diag::ext_aggregate_init_not_constant)
- << Init->getSourceRange();
+ << Culprit->getSourceRange();
}
} else if (VDecl->isStaticDataMember() &&
VDecl->getLexicalDeclContext()->isRecord()) {
@@ -8545,19 +8553,6 @@
// C99 6.7.8p4. All file scoped initializers need to be constant.
if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl())
CheckForConstantInitializer(Init, DclT);
- else if (VDecl->getTLSKind() == VarDecl::TLS_Static &&
- !VDecl->isInvalidDecl() && !DclT->isDependentType() &&
- !Init->isValueDependent() && !VDecl->isConstexpr() &&
- !Init->isConstantInitializer(
- Context, VDecl->getType()->isReferenceType())) {
- // GNU C++98 edits for __thread, [basic.start.init]p4:
- // An object of thread storage duration shall not require dynamic
- // initialization.
- // FIXME: Need strict checking here.
- Diag(VDecl->getLocation(), diag::err_thread_dynamic_init);
- if (getLangOpts().CPlusPlus11)
- Diag(VDecl->getLocation(), diag::note_use_thread_local);
- }
}
// We will represent direct-initialization similarly to copy-initialization:
@@ -8613,7 +8608,7 @@
return;
}
- // Require an abstract type.
+ // Require a non-abstract type.
if (RequireNonAbstractType(VD->getLocation(), Ty,
diag::err_abstract_type_in_decl,
AbstractVariableType)) {
@@ -8628,7 +8623,7 @@
void Sema::ActOnUninitializedDecl(Decl *RealDecl,
bool TypeMayContainAuto) {
// If there is no declaration, there was an error parsing it. Just ignore it.
- if (RealDecl == 0)
+ if (!RealDecl)
return;
if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
@@ -8919,14 +8914,51 @@
Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var;
}
- if (var->getTLSKind() == VarDecl::TLS_Static &&
- var->getType().isDestructedType()) {
- // GNU C++98 edits for __thread, [basic.start.term]p3:
- // The type of an object with thread storage duration shall not
- // have a non-trivial destructor.
- Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
- if (getLangOpts().CPlusPlus11)
- Diag(var->getLocation(), diag::note_use_thread_local);
+ if (var->getTLSKind() == VarDecl::TLS_Static) {
+ const Expr *Culprit;
+ if (var->getType().isDestructedType()) {
+ // GNU C++98 edits for __thread, [basic.start.term]p3:
+ // The type of an object with thread storage duration shall not
+ // have a non-trivial destructor.
+ Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
+ if (getLangOpts().CPlusPlus11)
+ Diag(var->getLocation(), diag::note_use_thread_local);
+ } else if (getLangOpts().CPlusPlus && var->hasInit() &&
+ !var->getInit()->isConstantInitializer(
+ Context, var->getType()->isReferenceType(), &Culprit)) {
+ // GNU C++98 edits for __thread, [basic.start.init]p4:
+ // An object of thread storage duration shall not require dynamic
+ // initialization.
+ // FIXME: Need strict checking here.
+ Diag(Culprit->getExprLoc(), diag::err_thread_dynamic_init)
+ << Culprit->getSourceRange();
+ if (getLangOpts().CPlusPlus11)
+ Diag(var->getLocation(), diag::note_use_thread_local);
+ }
+
+ }
+
+ if (var->isThisDeclarationADefinition() &&
+ ActiveTemplateInstantiations.empty()) {
+ PragmaStack<StringLiteral *> *Stack = nullptr;
+ int SectionFlags = PSF_Implicit | PSF_Read;
+ if (var->getType().isConstQualified())
+ Stack = &ConstSegStack;
+ else if (!var->getInit()) {
+ Stack = &BSSSegStack;
+ SectionFlags |= PSF_Write;
+ } else {
+ Stack = &DataSegStack;
+ SectionFlags |= PSF_Write;
+ }
+ if (!var->hasAttr<SectionAttr>() && Stack->CurrentValue)
+ var->addAttr(
+ SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate,
+ Stack->CurrentValue->getString(),
+ Stack->CurrentPragmaLocation));
+ if (const SectionAttr *SA = var->getAttr<SectionAttr>())
+ if (UnifySection(SA->getName(), SectionFlags, var))
+ var->dropAttr<SectionAttr>();
}
// All the following checks are C++ only.
@@ -9046,7 +9078,8 @@
AddPushedVisibilityAttribute(VD);
// FIXME: Warn on unused templates.
- if (VD->isFileVarDecl() && !VD->getDescribedVarTemplate())
+ if (VD->isFileVarDecl() && !VD->getDescribedVarTemplate() &&
+ !isa<VarTemplatePartialSpecializationDecl>(VD))
MarkUnusedFileScopedDecl(VD);
// Now we have parsed the initializer and can update the table of magic
@@ -9089,7 +9122,7 @@
if (DS.isTypeSpecOwned())
Decls.push_back(DS.getRepAsDecl());
- DeclaratorDecl *FirstDeclaratorInGroup = 0;
+ DeclaratorDecl *FirstDeclaratorInGroup = nullptr;
for (unsigned i = 0, e = Group.size(); i != e; ++i)
if (Decl *D = Group[i]) {
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
@@ -9124,7 +9157,7 @@
if (TypeMayContainAuto && Group.size() > 1) {
QualType Deduced;
CanQualType DeducedCanon;
- VarDecl *DeducedDecl = 0;
+ VarDecl *DeducedDecl = nullptr;
for (unsigned i = 0, e = Group.size(); i != e; ++i) {
if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
AutoType *AT = D->getType()->getContainedAutoType();
@@ -9250,7 +9283,7 @@
}
// Ensure we have a valid name
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
if (D.hasName()) {
II = D.getIdentifier();
if (!II) {
@@ -9271,14 +9304,14 @@
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
} else if (S->isDeclScope(PrevDecl)) {
Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;
Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
// Recover by removing the name
- II = 0;
- D.SetIdentifier(0, D.getIdentifierLoc());
+ II = nullptr;
+ D.SetIdentifier(nullptr, D.getIdentifierLoc());
D.setInvalidType(true);
}
}
@@ -9328,9 +9361,9 @@
/* FIXME: setting StartLoc == Loc.
Would it be worth to modify callers so as to provide proper source
location for the unnamed parameters, embedding the parameter's type? */
- ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0,
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, nullptr,
T, Context.getTrivialTypeSourceInfo(T, Loc),
- SC_None, 0);
+ SC_None, nullptr);
Param->setImplicit();
return Param;
}
@@ -9410,7 +9443,7 @@
ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
Context.getAdjustedParameterType(T),
TSInfo,
- StorageClass, 0);
+ StorageClass, nullptr);
// Parameters can not be abstract class types.
// For record types, this is done by the AbstractClassUsageDiagnoser once
@@ -9436,8 +9469,12 @@
// Since all parameters have automatic store duration, they can not have
// an address space.
if (T.getAddressSpace() != 0) {
- Diag(NameLoc, diag::err_arg_with_address_space);
- New->setInvalidDecl();
+ // OpenCL allows function arguments declared to be an array of a type
+ // to be qualified with an address space.
+ if (!(getLangOpts().OpenCL && T->isArrayType())) {
+ Diag(NameLoc, diag::err_arg_with_address_space);
+ New->setInvalidDecl();
+ }
}
return New;
@@ -9452,7 +9489,7 @@
if (!FTI.hasPrototype) {
for (int i = FTI.NumParams; i != 0; /* decrement in loop */) {
--i;
- if (FTI.Params[i].Param == 0) {
+ if (FTI.Params[i].Param == nullptr) {
SmallString<256> Code;
llvm::raw_svector_ostream(Code)
<< " int " << FTI.Params[i].Ident->getName() << ";\n";
@@ -9480,7 +9517,7 @@
}
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
- assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+ assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
assert(D.isFunctionDeclarator() && "Not a function declarator!");
Scope *ParentScope = FnBodyScope->getParent();
@@ -9489,6 +9526,10 @@
return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
+void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) {
+ Consumer.HandleInlineMethodDefinition(D);
+}
+
static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
const FunctionDecl*& PossibleZeroParamPrototype) {
// Don't warn about invalid declarations.
@@ -9599,11 +9640,11 @@
/*RefersToEnclosingLocal*/true, C.getLocation(),
/*EllipsisLoc*/C.isPackExpansion()
? C.getEllipsisLoc() : SourceLocation(),
- CaptureType, /*Expr*/ 0);
-
+ CaptureType, /*Expr*/ nullptr);
+
} else if (C.capturesThis()) {
LSI->addThisCapture(/*Nested*/ false, C.getLocation(),
- S.getCurrentThisType(), /*Expr*/ 0);
+ S.getCurrentThisType(), /*Expr*/ nullptr);
}
}
}
@@ -9614,7 +9655,7 @@
if (!D)
return D;
- FunctionDecl *FD = 0;
+ FunctionDecl *FD = nullptr;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
FD = FunTmpl->getTemplatedDecl();
@@ -9666,7 +9707,7 @@
// prototype declaration. This warning is issued even if the
// definition itself provides a prototype. The aim is to detect
// global functions that fail to be declared in header files.
- const FunctionDecl *PossibleZeroParamPrototype = 0;
+ const FunctionDecl *PossibleZeroParamPrototype = nullptr;
if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
@@ -9745,20 +9786,13 @@
if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>())
ResolveExceptionSpec(D->getLocation(), FPT);
- // Checking attributes of current function definition
- // dllimport attribute.
- DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
- if (DA && (!FD->hasAttr<DLLExportAttr>())) {
- // dllimport attribute cannot be directly applied to definition.
- // Microsoft accepts dllimport for functions defined within class scope.
- if (!DA->isInherited() &&
- !(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) {
- Diag(FD->getLocation(),
- diag::err_attribute_can_be_applied_only_to_symbol_declaration)
- << DA;
- FD->setInvalidDecl();
- return D;
- }
+ // dllimport cannot be applied to non-inline function definitions.
+ if (FD->hasAttr<DLLImportAttr>() && !FD->isInlined() &&
+ !FD->isTemplateInstantiation()) {
+ assert(!FD->hasAttr<DLLExportAttr>());
+ Diag(FD->getLocation(), diag::err_attribute_dllimport_function_definition);
+ FD->setInvalidDecl();
+ return D;
}
// We want to attach documentation to original Decl (which might be
// a function template).
@@ -9776,28 +9810,17 @@
/// use the named return value optimization.
///
/// This function applies a very simplistic algorithm for NRVO: if every return
-/// statement in the function has the same NRVO candidate, that candidate is
-/// the NRVO variable.
-///
-/// FIXME: Employ a smarter algorithm that accounts for multiple return
-/// statements and the lifetimes of the NRVO candidates. We should be able to
-/// find a maximal set of NRVO variables.
+/// statement in the scope of a variable has the same NRVO candidate, that
+/// candidate is an NRVO variable.
void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
ReturnStmt **Returns = Scope->Returns.data();
- const VarDecl *NRVOCandidate = 0;
for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) {
- if (!Returns[I]->getNRVOCandidate())
- return;
-
- if (!NRVOCandidate)
- NRVOCandidate = Returns[I]->getNRVOCandidate();
- else if (NRVOCandidate != Returns[I]->getNRVOCandidate())
- return;
+ if (const VarDecl *NRVOCandidate = Returns[I]->getNRVOCandidate()) {
+ if (!NRVOCandidate->isNRVOVariable())
+ Returns[I]->setNRVOCandidate(nullptr);
+ }
}
-
- if (NRVOCandidate)
- const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
}
bool Sema::canDelayFunctionBody(const Declarator &D) {
@@ -9841,7 +9864,7 @@
FD->setHasSkippedBody();
else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Decl))
MD->setHasSkippedBody();
- return ActOnFinishFunctionBody(Decl, 0);
+ return ActOnFinishFunctionBody(Decl, nullptr);
}
Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
@@ -9850,10 +9873,10 @@
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
bool IsInstantiation) {
- FunctionDecl *FD = dcl ? dcl->getAsFunction() : 0;
+ FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr;
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
- sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
+ sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
if (FD) {
FD->setBody(Body);
@@ -9899,7 +9922,9 @@
Diag(FD->getLocation(), diag::warn_pure_function_definition);
if (!FD->isInvalidDecl()) {
- DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
+ // Don't diagnose unused parameters of defaulted or deleted functions.
+ if (Body)
+ DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
FD->getReturnType(), FD);
@@ -9934,13 +9959,25 @@
getCurFunction()->ObjCShouldCallSuper = false;
}
if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) {
- const ObjCMethodDecl *InitMethod = 0;
+ const ObjCMethodDecl *InitMethod = nullptr;
bool isDesignated =
MD->isDesignatedInitializerForTheInterface(&InitMethod);
assert(isDesignated && InitMethod);
(void)isDesignated;
- // Don't issue this warning for unavaialable inits.
- if (!MD->isUnavailable()) {
+
+ auto superIsNSObject = [&](const ObjCMethodDecl *MD) {
+ auto IFace = MD->getClassInterface();
+ if (!IFace)
+ return false;
+ auto SuperD = IFace->getSuperClass();
+ if (!SuperD)
+ return false;
+ return SuperD->getIdentifier() ==
+ NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);
+ };
+ // Don't issue this warning for unavailable inits or direct subclasses
+ // of NSObject.
+ if (!MD->isUnavailable() && !superIsNSObject(MD)) {
Diag(MD->getLocation(),
diag::warn_objc_designated_init_missing_super_call);
Diag(InitMethod->getLocation(),
@@ -9955,7 +9992,7 @@
getCurFunction()->ObjCWarnForNoInitDelegation = false;
}
} else {
- return 0;
+ return nullptr;
}
assert(!getCurFunction()->ObjCShouldCallSuper &&
@@ -9972,8 +10009,6 @@
// Verify that gotos and switch cases don't jump into scopes illegally.
if (getCurFunction()->NeedsScopeChecking() &&
- !dcl->isInvalidDecl() &&
- !hasAnyUnrecoverableErrorsInThisFunction() &&
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(Body);
@@ -9988,11 +10023,11 @@
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
// deletion in some later function.
- if (PP.getDiagnostics().hasErrorOccurred() ||
- PP.getDiagnostics().getSuppressAllDiagnostics()) {
+ if (getDiagnostics().hasErrorOccurred() ||
+ getDiagnostics().getSuppressAllDiagnostics()) {
DiscardCleanupsInEvaluationContext();
}
- if (!PP.getDiagnostics().hasUncompilableErrorOccurred() &&
+ if (!getDiagnostics().hasUncompilableErrorOccurred() &&
!isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
// enabled.
@@ -10070,7 +10105,8 @@
TypoCorrection Corrected;
DeclFilterCCC<FunctionDecl> Validator;
if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
- LookupOrdinaryName, S, 0, Validator)))
+ LookupOrdinaryName, S, nullptr, Validator,
+ CTK_NonError)))
diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion),
/*ErrorRecovery*/false);
}
@@ -10088,9 +10124,9 @@
Declarator D(DS, Declarator::BlockContext);
D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false,
/*IsAmbiguous=*/false,
- /*RParenLoc=*/NoLoc,
- /*ArgInfo=*/0,
- /*NumArgs=*/0,
+ /*LParenLoc=*/NoLoc,
+ /*Params=*/nullptr,
+ /*NumParams=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
/*TypeQuals=*/0,
@@ -10101,10 +10137,10 @@
/*MutableLoc=*/NoLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
- /*Exceptions=*/0,
- /*ExceptionRanges=*/0,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
- /*NoexceptExpr=*/0,
+ /*NoexceptExpr=*/nullptr,
Loc, Loc, D),
DS.getAttributes(),
SourceLocation());
@@ -10288,8 +10324,7 @@
Diag(D.getIdentifierLoc(), diag::err_typedef_changes_linkage);
SourceLocation tagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
- tagLoc = Lexer::getLocForEndOfToken(tagLoc, 0, getSourceManager(),
- getLangOpts());
+ tagLoc = getLocForEndOfToken(tagLoc);
llvm::SmallString<40> textToInsert;
textToInsert += ' ';
@@ -10501,7 +10536,7 @@
bool IsTypeSpecifier) {
// If this is not a definition, it must have a name.
IdentifierInfo *OrigName = Name;
- assert((Name != 0 || TUK == TUK_Definition) &&
+ assert((Name != nullptr || TUK == TUK_Definition) &&
"Nameless record must be a definition!");
assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference);
@@ -10520,11 +10555,11 @@
(SS.isNotEmpty() && TUK != TUK_Reference)) {
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
- KWLoc, NameLoc, SS, TemplateParameterLists, TUK == TUK_Friend,
- isExplicitSpecialization, Invalid)) {
+ KWLoc, NameLoc, SS, nullptr, TemplateParameterLists,
+ TUK == TUK_Friend, isExplicitSpecialization, Invalid)) {
if (Kind == TTK_Enum) {
Diag(KWLoc, diag::err_enum_template);
- return 0;
+ return nullptr;
}
if (TemplateParams->size() > 0) {
@@ -10532,7 +10567,7 @@
// be a member of another template).
if (Invalid)
- return 0;
+ return nullptr;
OwnedDecl = false;
DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
@@ -10564,7 +10599,7 @@
else if (UnderlyingType.get()) {
// C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an
// integral type; any cv-qualification is ignored.
- TypeSourceInfo *TI = 0;
+ TypeSourceInfo *TI = nullptr;
GetTypeFromParser(UnderlyingType.get(), &TI);
EnumUnderlying = TI;
@@ -10596,7 +10631,7 @@
// Check for invalid 'foo::'.
if (SS.isInvalid()) {
- Name = 0;
+ Name = nullptr;
goto CreateNewDecl;
}
@@ -10606,26 +10641,26 @@
DC = computeDeclContext(SS, false);
if (!DC) {
IsDependent = true;
- return 0;
+ return nullptr;
}
} else {
DC = computeDeclContext(SS, true);
if (!DC) {
Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec)
<< SS.getRange();
- return 0;
+ return nullptr;
}
}
if (RequireCompleteDeclContext(SS, DC))
- return 0;
+ return nullptr;
SearchDC = DC;
// Look-up name inside 'foo::'.
LookupQualifiedName(Previous, DC);
if (Previous.isAmbiguous())
- return 0;
+ return nullptr;
if (Previous.empty()) {
// Name lookup did not find anything. However, if the
@@ -10637,13 +10672,13 @@
if (Previous.wasNotFoundInCurrentInstantiation() &&
(TUK == TUK_Reference || TUK == TUK_Friend)) {
IsDependent = true;
- return 0;
+ return nullptr;
}
// A tag 'foo::bar' must already exist.
Diag(NameLoc, diag::err_not_tag_in_scope)
<< Kind << Name << DC << SS.getRange();
- Name = 0;
+ Name = nullptr;
Invalid = true;
goto CreateNewDecl;
}
@@ -10694,7 +10729,7 @@
// Note: there used to be some attempt at recovery here.
if (Previous.isAmbiguous())
- return 0;
+ return nullptr;
if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated
@@ -10855,7 +10890,7 @@
Kind = PrevTagDecl->getTagKind();
else {
// Recover by making this an anonymous redefinition.
- Name = 0;
+ Name = nullptr;
Previous.clear();
Invalid = true;
}
@@ -10885,7 +10920,7 @@
// in which case we want the caller to bail out.
if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
ScopedEnum, EnumUnderlyingTy, PrevEnum))
- return TUK == TUK_Declaration ? PrevTagDecl : 0;
+ return TUK == TUK_Declaration ? PrevTagDecl : nullptr;
}
// C++11 [class.mem]p1:
@@ -10899,14 +10934,17 @@
}
if (!Invalid) {
- // If this is a use, just return the declaration we found.
+ // If this is a use, just return the declaration we found, unless
+ // we have attributes.
// FIXME: In the future, return a variant or some other clue
// for the consumer of this Decl to know it doesn't own it.
// For our current ASTs this shouldn't be a problem, but will
// need to be changed with DeclGroups.
- if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() ||
- getLangOpts().MicrosoftExt)) || TUK == TUK_Friend)
+ if (!Attr &&
+ ((TUK == TUK_Reference &&
+ (!PrevTagDecl->getFriendObjectKind() || getLangOpts().MicrosoftExt))
+ || TUK == TUK_Friend))
return PrevTagDecl;
// Diagnose attempts to redefine a tag.
@@ -10938,7 +10976,7 @@
// If this is a redefinition, recover by making this
// struct be anonymous, which will make any later
// references get the previous definition.
- Name = 0;
+ Name = nullptr;
Previous.clear();
Invalid = true;
}
@@ -10951,14 +10989,22 @@
Diag(NameLoc, diag::err_nested_redefinition) << Name;
Diag(PrevTagDecl->getLocation(),
diag::note_previous_definition);
- Name = 0;
+ Name = nullptr;
Previous.clear();
Invalid = true;
}
}
// Okay, this is definition of a previously declared or referenced
- // tag PrevDecl. We're going to create a new Decl for it.
+ // tag. We're going to create a new Decl for it.
+ }
+
+ // Okay, we're going to make a redeclaration. If this is some kind
+ // of reference, make sure we build the redeclaration in the same DC
+ // as the original, and ignore the current access specifier.
+ if (TUK == TUK_Friend || TUK == TUK_Reference) {
+ SearchDC = PrevTagDecl->getDeclContext();
+ AS = AS_none;
}
}
// If we get here we have (another) forward declaration or we
@@ -11024,7 +11070,7 @@
// issue an error and recover by making this tag be anonymous.
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- Name = 0;
+ Name = nullptr;
Invalid = true;
}
@@ -11036,7 +11082,7 @@
CreateNewDecl:
- TagDecl *PrevDecl = 0;
+ TagDecl *PrevDecl = nullptr;
if (Previous.isSingleResult())
PrevDecl = cast<TagDecl>(Previous.getFoundDecl());
@@ -11249,7 +11295,7 @@
OwnedDecl = true;
// In C++, don't return an invalid declaration. We can't recover well from
// the cases where we make the type anonymous.
- return (Invalid && getLangOpts().CPlusPlus) ? 0 : New;
+ return (Invalid && getLangOpts().CPlusPlus) ? nullptr : New;
}
void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
@@ -11301,7 +11347,7 @@
= CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext,
Record->getLocStart(), Record->getLocation(),
Record->getIdentifier(),
- /*PrevDecl=*/0,
+ /*PrevDecl=*/nullptr,
/*DelayTypeCreation=*/true);
Context.getTypeDeclType(InjectedClassName, Record);
InjectedClassName->setImplicit();
@@ -11354,7 +11400,7 @@
void Sema::ActOnObjCReenterContainerContext(DeclContext *DC) {
ActOnObjCContainerStartDefinition(cast<Decl>(DC));
- OriginalLexicalContext = 0;
+ OriginalLexicalContext = nullptr;
}
void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
@@ -11507,7 +11553,7 @@
<< DeclSpec::getSpecifierName(TSCS);
// Check to see if this name was declared as a member previously
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
LookupName(Previous, S);
switch (Previous.getResultKind()) {
@@ -11531,11 +11577,11 @@
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
- PrevDecl = 0;
+ PrevDecl = nullptr;
bool Mutable
= (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
@@ -11651,7 +11697,7 @@
&ZeroWidth).take();
if (!BitWidth) {
InvalidDecl = true;
- BitWidth = 0;
+ BitWidth = nullptr;
ZeroWidth = false;
}
}
@@ -11863,7 +11909,7 @@
// Must set ivar's DeclContext to its enclosing interface.
ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(CurContext);
if (!EnclosingDecl || EnclosingDecl->isInvalidDecl())
- return 0;
+ return nullptr;
ObjCContainerDecl *EnclosingContext;
if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
@@ -11879,7 +11925,7 @@
dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
if (LangOpts.ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) {
Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();
- return 0;
+ return nullptr;
}
}
EnclosingContext = EnclosingDecl;
@@ -11957,7 +12003,7 @@
Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc);
Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(CurContext),
- DeclLoc, DeclLoc, 0,
+ DeclLoc, DeclLoc, nullptr,
Context.CharTy,
Context.getTrivialTypeSourceInfo(Context.CharTy,
DeclLoc),
@@ -12434,7 +12480,7 @@
QualType EltTy;
if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue))
- Val = 0;
+ Val = nullptr;
if (Val)
Val = DefaultLvalueConversion(Val).take();
@@ -12454,7 +12500,7 @@
CheckConvertedConstantExpression(Val, EltTy, EnumVal,
CCEK_Enumerator);
if (Converted.isInvalid())
- Val = 0;
+ Val = nullptr;
else
Val = Converted.take();
} else if (!Val->isValueDependent() &&
@@ -12616,7 +12662,7 @@
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
if (PrevDecl) {
@@ -12630,7 +12676,7 @@
else
Diag(IdLoc, diag::err_redefinition) << Id;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- return 0;
+ return nullptr;
}
}
@@ -13043,7 +13089,7 @@
ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
CK_IntegralCast,
ECD->getInitExpr(),
- /*base paths*/ 0,
+ /*base paths*/ nullptr,
VK_RValue));
if (getLangOpts().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
@@ -13109,14 +13155,21 @@
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
- Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
- Module::AllVisible,
- /*IsIncludeDirective=*/false);
+ Module *Mod =
+ getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
+ /*IsIncludeDirective=*/false);
if (!Mod)
return true;
checkModuleImportContext(*this, Mod, ImportLoc, CurContext);
+ // FIXME: we should support importing a submodule within a different submodule
+ // of the same top-level module. Until we do, make it an error rather than
+ // silently ignoring the import.
+ if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule)
+ Diag(ImportLoc, diag::err_module_self_import)
+ << Mod->getFullModuleName() << getLangOpts().CurrentModule;
+
SmallVector<SourceLocation, 2> IdentifierLocs;
Module *ModCheck = Mod;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
@@ -13141,11 +13194,16 @@
checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
// FIXME: Should we synthesize an ImportDecl here?
- PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
- /*Complain=*/true);
+ getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
+ /*Complain=*/true);
}
-void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) {
+void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
+ Module *Mod) {
+ // Bail if we're not allowed to implicitly import a module here.
+ if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery)
+ return;
+
// Create the implicit import declaration.
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
@@ -13154,8 +13212,8 @@
Consumer.HandleImplicitImportDecl(ImportD);
// Make the module visible.
- PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
- /*Complain=*/false);
+ getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
+ /*Complain=*/false);
}
void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
@@ -13185,7 +13243,7 @@
} else {
(void)WeakUndeclaredIdentifiers.insert(
std::pair<IdentifierInfo*,WeakInfo>
- (Name, WeakInfo((IdentifierInfo*)0, NameLoc)));
+ (Name, WeakInfo((IdentifierInfo*)nullptr, NameLoc)));
}
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 38b3c45..6a85c38 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
@@ -47,7 +48,7 @@
/// type (function or function-typed variable) or an Objective-C
/// method.
static bool isFunctionOrMethod(const Decl *D) {
- return (D->getFunctionType() != NULL) || isa<ObjCMethodDecl>(D);
+ return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
}
/// Return true if the given decl has a declarator that should have
@@ -360,11 +361,10 @@
if (const PointerType *PT = QT->getAs<PointerType>())
return PT->getPointeeType()->getAs<RecordType>();
- return 0;
+ return nullptr;
}
-static bool checkRecordTypeForCapability(Sema &S, const AttributeList &Attr,
- QualType Ty) {
+static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
const RecordType *RT = getRecordType(Ty);
if (!RT)
@@ -391,14 +391,13 @@
void *) {
return BS->getType()->getAs<RecordType>()
->getDecl()->hasAttr<CapabilityAttr>();
- }, 0, BPaths))
+ }, nullptr, BPaths))
return true;
}
return false;
}
-static bool checkTypedefTypeForCapability(Sema &S, const AttributeList &Attr,
- QualType Ty) {
+static bool checkTypedefTypeForCapability(QualType Ty) {
const auto *TD = Ty->getAs<TypedefType>();
if (!TD)
return false;
@@ -410,18 +409,40 @@
return TN->hasAttr<CapabilityAttr>();
}
-/// \brief Checks that the passed in type is qualified as a capability. This
-/// type can either be a struct, or a typedef to a built-in type (such as int).
-static void checkForCapability(Sema &S, const AttributeList &Attr,
- QualType Ty) {
- if (checkTypedefTypeForCapability(S, Attr, Ty))
- return;
+static bool typeHasCapability(Sema &S, QualType Ty) {
+ if (checkTypedefTypeForCapability(Ty))
+ return true;
- if (checkRecordTypeForCapability(S, Attr, Ty))
- return;
+ if (checkRecordTypeForCapability(S, Ty))
+ return true;
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
- << Attr.getName() << Ty;
+ return false;
+}
+
+static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
+ // Capability expressions are simple expressions involving the boolean logic
+ // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once
+ // a DeclRefExpr is found, its type should be checked to determine whether it
+ // is a capability or not.
+
+ if (const auto *E = dyn_cast<DeclRefExpr>(Ex))
+ return typeHasCapability(S, E->getType());
+ else if (const auto *E = dyn_cast<CastExpr>(Ex))
+ return isCapabilityExpr(S, E->getSubExpr());
+ else if (const auto *E = dyn_cast<ParenExpr>(Ex))
+ return isCapabilityExpr(S, E->getSubExpr());
+ else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) {
+ if (E->getOpcode() == UO_LNot)
+ return isCapabilityExpr(S, E->getSubExpr());
+ return false;
+ } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) {
+ if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr)
+ return isCapabilityExpr(S, E->getLHS()) &&
+ isCapabilityExpr(S, E->getRHS());
+ return false;
+ }
+
+ return false;
}
/// \brief Checks that all attribute arguments, starting from Sidx, resolve to
@@ -491,7 +512,13 @@
}
}
- checkForCapability(S, Attr, ArgTy);
+ // If the type does not have a capability, see if the components of the
+ // expression have capabilities. This allows for writing C code where the
+ // capability may be on the type, and the expression is a capability
+ // boolean logic expression. Eg) requires_capability(A || B && !C)
+ if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp))
+ S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
+ << Attr.getName() << ArgTy;
Args.push_back(ArgExp);
}
@@ -531,7 +558,7 @@
}
static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- Expr *Arg = 0;
+ Expr *Arg = nullptr;
if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
return;
@@ -541,7 +568,7 @@
static void handlePtGuardedByAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- Expr *Arg = 0;
+ Expr *Arg = nullptr;
if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
return;
@@ -621,7 +648,7 @@
return;
unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
+ Expr **StartArg = Size == 0 ? nullptr : &Args[0];
D->addAttr(::new (S.Context)
AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size,
Attr.getAttributeSpellingListIndex()));
@@ -634,7 +661,7 @@
return;
unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
+ Expr **StartArg = Size == 0 ? nullptr : &Args[0];
D->addAttr(::new (S.Context)
AssertExclusiveLockAttr(Attr.getRange(), S.Context,
StartArg, Size,
@@ -1053,7 +1080,7 @@
}
}
- TypeSourceInfo *QTLoc = 0;
+ TypeSourceInfo *QTLoc = nullptr;
QualType QT = S.GetTypeFromParser(PT, &QTLoc);
if (!QTLoc)
QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc());
@@ -1165,7 +1192,7 @@
return;
D->addAttr(::new (S.Context)
- NonNullAttr(Attr.getRange(), S.Context, 0, 0,
+ NonNullAttr(Attr.getRange(), S.Context, nullptr, 0,
Attr.getAttributeSpellingListIndex()));
}
@@ -1198,7 +1225,7 @@
// Figure out our Kind.
OwnershipAttr::OwnershipKind K =
- OwnershipAttr(AL.getLoc(), S.Context, 0, 0, 0,
+ OwnershipAttr(AL.getLoc(), S.Context, nullptr, nullptr, 0,
AL.getAttributeSpellingListIndex()).getOwnKind();
// Check arguments.
@@ -1463,8 +1490,8 @@
// because 'analyzer_noreturn' does not impact the type.
if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (VD == 0 || (!VD->getType()->isBlockPointerType()
- && !VD->getType()->isFunctionPointerType())) {
+ if (!VD || (!VD->getType()->isBlockPointerType() &&
+ !VD->getType()->isFunctionPointerType())) {
S.Diag(Attr.getLoc(),
Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
: diag::warn_attribute_wrong_decl_type)
@@ -1803,7 +1830,7 @@
MergedIntroduced == Introduced &&
MergedDeprecated == Deprecated &&
MergedObsoleted == Obsoleted)
- return NULL;
+ return nullptr;
// Only create a new attribute if !Override, but we want to do
// the checking.
@@ -1815,7 +1842,7 @@
Obsoleted, IsUnavailable, Message,
AttrSpellingListIndex);
}
- return NULL;
+ return nullptr;
}
static void handleAvailabilityAttr(Sema &S, Decl *D,
@@ -1864,7 +1891,7 @@
if (existingAttr) {
typename T::VisibilityType existingValue = existingAttr->getVisibility();
if (existingValue == value)
- return NULL;
+ return nullptr;
S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility);
S.Diag(range.getBegin(), diag::note_previous_attribute);
D->dropAttr<T>();
@@ -2163,9 +2190,16 @@
static void handleWorkGroupSize(Sema &S, Decl *D,
const AttributeList &Attr) {
uint32_t WGSize[3];
- for (unsigned i = 0; i < 3; ++i)
- if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(i), WGSize[i], i))
+ for (unsigned i = 0; i < 3; ++i) {
+ const Expr *E = Attr.getArgAsExpr(i);
+ if (!checkUInt32Argument(S, Attr, E, WGSize[i], i))
return;
+ if (WGSize[i] == 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
+ << Attr.getName() << E->getSourceRange();
+ return;
+ }
+ }
WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>();
if (Existing && !(Existing->getXDim() == WGSize[0] &&
@@ -2185,7 +2219,7 @@
return;
}
- TypeSourceInfo *ParmTSI = 0;
+ TypeSourceInfo *ParmTSI = nullptr;
QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI);
assert(ParmTSI && "no type source info for attribute argument");
@@ -2214,10 +2248,10 @@
unsigned AttrSpellingListIndex) {
if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
if (ExistingAttr->getName() == Name)
- return NULL;
+ return nullptr;
Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section);
Diag(Range.getBegin(), diag::note_previous_attribute);
- return NULL;
+ return nullptr;
}
return ::new (Context) SectionAttr(Range, Context, Name,
AttrSpellingListIndex);
@@ -2255,7 +2289,7 @@
Expr *E = Attr.getArgAsExpr(0);
SourceLocation Loc = E->getExprLoc();
- FunctionDecl *FD = 0;
+ FunctionDecl *FD = nullptr;
DeclarationNameInfo NI;
// gcc only allows for simple identifiers. Since we support more than gcc, we
@@ -2435,7 +2469,7 @@
// location.
if (F->getLocation().isInvalid())
F->setRange(Range);
- return NULL;
+ return nullptr;
}
}
@@ -2571,7 +2605,7 @@
static void handleTransparentUnionAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
// Try to find the underlying union declaration.
- RecordDecl *RD = 0;
+ RecordDecl *RD = nullptr;
TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && TD->getUnderlyingType()->isUnionType())
RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
@@ -2665,7 +2699,7 @@
if (Attr.getNumArgs() == 0) {
D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context,
- true, 0, Attr.getAttributeSpellingListIndex()));
+ true, nullptr, Attr.getAttributeSpellingListIndex()));
return;
}
@@ -2793,7 +2827,7 @@
// The combined effect of all alignment attributes in a declaration shall
// not specify an alignment that is less strict than the alignment that
// would otherwise be required for the entity being declared.
- AlignedAttr *AlignasAttr = 0;
+ AlignedAttr *AlignasAttr = nullptr;
unsigned Align = 0;
for (auto *I : D->specific_attrs<AlignedAttr>()) {
if (I->isAlignmentDependent())
@@ -3308,7 +3342,7 @@
}
IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident;
- TypeSourceInfo *MatchingCTypeLoc = 0;
+ TypeSourceInfo *MatchingCTypeLoc = nullptr;
S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc);
assert(MatchingCTypeLoc && "no type source info for attribute argument");
@@ -3512,7 +3546,7 @@
static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
const AttributeList &Attr) {
- IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
+ IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
if (!Parm) {
S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
@@ -3526,8 +3560,8 @@
static void handleObjCBridgeMutableAttr(Sema &S, Scope *Sc, Decl *D,
const AttributeList &Attr) {
- IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
-
+ IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+
if (!Parm) {
S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
return;
@@ -3541,15 +3575,15 @@
static void handleObjCBridgeRelatedAttr(Sema &S, Scope *Sc, Decl *D,
const AttributeList &Attr) {
IdentifierInfo *RelatedClass =
- Attr.isArgIdent(0) ? Attr.getArgAsIdent(0)->Ident : 0;
+ Attr.isArgIdent(0) ? Attr.getArgAsIdent(0)->Ident : nullptr;
if (!RelatedClass) {
S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
return;
}
IdentifierInfo *ClassMethod =
- Attr.getArgAsIdent(1) ? Attr.getArgAsIdent(1)->Ident : 0;
+ Attr.getArgAsIdent(1) ? Attr.getArgAsIdent(1)->Ident : nullptr;
IdentifierInfo *InstanceMethod =
- Attr.getArgAsIdent(2) ? Attr.getArgAsIdent(2)->Ident : 0;
+ Attr.getArgAsIdent(2) ? Attr.getArgAsIdent(2)->Ident : nullptr;
D->addAttr(::new (S.Context)
ObjCBridgeRelatedAttr(Attr.getRange(), S.Context, RelatedClass,
ClassMethod, InstanceMethod,
@@ -3681,6 +3715,25 @@
D->addAttr(IA);
}
+static void handleDeclspecThreadAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ VarDecl *VD = cast<VarDecl>(D);
+ if (!S.Context.getTargetInfo().isTLSSupported()) {
+ S.Diag(Attr.getLoc(), diag::err_thread_unsupported);
+ return;
+ }
+ if (VD->getTSCSpec() != TSCS_unspecified) {
+ S.Diag(Attr.getLoc(), diag::err_declspec_thread_on_thread_variable);
+ return;
+ }
+ if (VD->hasLocalStorage()) {
+ S.Diag(Attr.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
+ return;
+ }
+ VD->addAttr(::new (S.Context) ThreadAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
static void handleARMInterruptAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
// Check the attribute arguments.
@@ -3783,35 +3836,16 @@
unsigned AttrSpellingListIndex) {
if (D->hasAttr<DLLExportAttr>()) {
Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'dllimport'";
- return NULL;
+ return nullptr;
}
if (D->hasAttr<DLLImportAttr>())
- return NULL;
+ return nullptr;
return ::new (Context) DLLImportAttr(Range, Context, AttrSpellingListIndex);
}
static void handleDLLImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Attribute can be applied only to functions or variables.
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD && !isa<VarDecl>(D)) {
- // Apparently Visual C++ thinks it is okay to not emit a warning
- // in this case, so only emit a warning when -fms-extensions is not
- // specified.
- if (!S.getLangOpts().MicrosoftExt)
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
- // Currently, the dllimport attribute is ignored for inlined functions.
- // Warning is emitted.
- if (FD && FD->isInlineSpecified()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
-
unsigned Index = Attr.getAttributeSpellingListIndex();
DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
if (NewAttr)
@@ -3826,20 +3860,12 @@
}
if (D->hasAttr<DLLExportAttr>())
- return NULL;
+ return nullptr;
return ::new (Context) DLLExportAttr(Range, Context, AttrSpellingListIndex);
}
static void handleDLLExportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Currently, the dllexport attribute is ignored for inlined functions, unless
- // the -fkeep-inline-functions flag has been used. Warning is emitted.
- if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isInlineSpecified()) {
- // FIXME: ... unless the -fkeep-inline-functions flag has been used.
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
-
unsigned Index = Attr.getAttributeSpellingListIndex();
DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
if (NewAttr)
@@ -3852,7 +3878,7 @@
MSInheritanceAttr::Spelling SemanticSpelling) {
if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) {
if (IA->getSemanticSpelling() == SemanticSpelling)
- return 0;
+ return nullptr;
Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance)
<< 1 /*previous declaration*/;
Diag(Range.getBegin(), diag::note_previous_ms_inheritance);
@@ -3863,18 +3889,18 @@
if (RD->hasDefinition()) {
if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase,
SemanticSpelling)) {
- return 0;
+ return nullptr;
}
} else {
if (isa<ClassTemplatePartialSpecializationDecl>(RD)) {
Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
<< 1 /*partial specialization*/;
- return 0;
+ return nullptr;
}
if (RD->getDescribedClassTemplate()) {
Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
<< 0 /*primary template*/;
- return 0;
+ return nullptr;
}
}
@@ -4119,6 +4145,9 @@
case AttributeList::AT_OptimizeNone:
handleOptimizeNoneAttr(S, D, Attr);
break;
+ case AttributeList::AT_Flatten:
+ handleSimpleAttribute<FlattenAttr>(S, D, Attr);
+ break;
case AttributeList::AT_Format:
handleFormatAttr(S, D, Attr);
break;
@@ -4155,6 +4184,9 @@
case AttributeList::AT_NoCommon:
handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
break;
+ case AttributeList::AT_NoSplitStack:
+ handleSimpleAttribute<NoSplitStackAttr>(S, D, Attr);
+ break;
case AttributeList::AT_NonNull:
if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
handleNonNullAttrParameter(S, PVD, Attr);
@@ -4381,6 +4413,9 @@
case AttributeList::AT_SelectAny:
handleSimpleAttribute<SelectAnyAttr>(S, D, Attr);
break;
+ case AttributeList::AT_Thread:
+ handleDeclspecThreadAttr(S, D, Attr);
+ break;
// Thread safety attributes:
case AttributeList::AT_AssertExclusiveLock:
@@ -4578,7 +4613,7 @@
NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
SourceLocation Loc) {
assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
- NamedDecl *NewD = 0;
+ NamedDecl *NewD = nullptr;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
FunctionDecl *NewFD;
// FIXME: Missing call to CheckFunctionDeclaration().
@@ -4651,7 +4686,7 @@
// have to do this.
LoadExternalWeakUndeclaredIdentifiers();
if (!WeakUndeclaredIdentifiers.empty()) {
- NamedDecl *ND = NULL;
+ NamedDecl *ND = nullptr;
if (VarDecl *VD = dyn_cast<VarDecl>(D))
if (VD->isExternC())
ND = VD;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 850db26..2f9f982 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -18,7 +18,6 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
-#include "clang/AST/DeclVisitor.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
@@ -387,11 +386,11 @@
<< SourceRange((*Toks)[1].getLocation(),
Toks->back().getLocation());
delete Toks;
- chunk.Fun.Params[argIdx].DefaultArgTokens = 0;
+ chunk.Fun.Params[argIdx].DefaultArgTokens = nullptr;
} else if (Param->getDefaultArg()) {
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< Param->getDefaultArg()->getSourceRange();
- Param->setDefaultArg(0);
+ Param->setDefaultArg(nullptr);
}
}
} else if (chunk.Kind != DeclaratorChunk::Paren) {
@@ -707,7 +706,7 @@
for (p = 0; p <= LastMissingDefaultArg; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->hasDefaultArg()) {
- Param->setDefaultArg(0);
+ Param->setDefaultArg(nullptr);
}
}
}
@@ -1175,10 +1174,12 @@
} else {
if (ReturnStmts.empty()) {
// C++1y doesn't require constexpr functions to contain a 'return'
- // statement. We still do, unless the return type is void, because
+ // statement. We still do, unless the return type might be void, because
// otherwise if there's no return statement, the function cannot
// be used in a core constant expression.
- bool OK = getLangOpts().CPlusPlus1y && Dcl->getReturnType()->isVoidType();
+ bool OK = getLangOpts().CPlusPlus1y &&
+ (Dcl->getReturnType()->isVoidType() ||
+ Dcl->getReturnType()->isDependentType());
Diag(Dcl->getLocation(),
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
: diag::err_constexpr_body_no_return);
@@ -1312,7 +1313,7 @@
if (Class->isUnion()) {
Diag(Class->getLocation(), diag::err_base_clause_on_union)
<< SpecifierRange;
- return 0;
+ return nullptr;
}
if (EllipsisLoc.isValid() &&
@@ -1338,8 +1339,8 @@
if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl())
Diag(BaseDecl->getLocation(), diag::note_previous_decl)
<< BaseType;
-
- return 0;
+
+ return nullptr;
}
}
@@ -1351,14 +1352,14 @@
// Base specifiers must be record types.
if (!BaseType->isRecordType()) {
Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
- return 0;
+ return nullptr;
}
// C++ [class.union]p1:
// A union shall not be used as a base class.
if (BaseType->isUnionType()) {
Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
- return 0;
+ return nullptr;
}
// C++ [class.derived]p2:
@@ -1367,7 +1368,7 @@
if (RequireCompleteType(BaseLoc, BaseType,
diag::err_incomplete_base_class, SpecifierRange)) {
Class->setInvalidDecl();
- return 0;
+ return nullptr;
}
// If the base class is polymorphic or isn't empty, the new one is/isn't, too.
@@ -1387,7 +1388,7 @@
if (CXXBaseDecl->hasFlexibleArrayMember()) {
Diag(BaseLoc, diag::err_base_class_has_flexible_array_member)
<< CXXBaseDecl->getDeclName();
- return 0;
+ return nullptr;
}
// C++ [class]p3:
@@ -1399,7 +1400,7 @@
<< FA->isSpelledAsSealed();
Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl)
<< CXXBaseDecl->getDeclName();
- return 0;
+ return nullptr;
}
if (BaseDecl->isInvalidDecl())
@@ -1446,7 +1447,7 @@
}
}
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
GetTypeFromParser(basetype, &TInfo);
if (EllipsisLoc.isInvalid() &&
@@ -1849,10 +1850,10 @@
}
static AttributeList *getMSPropertyAttr(AttributeList *list) {
- for (AttributeList* it = list; it != 0; it = it->getNext())
+ for (AttributeList *it = list; it != nullptr; it = it->getNext())
if (it->isDeclspecPropertyAttribute())
return it;
- return 0;
+ return nullptr;
}
/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
@@ -1921,7 +1922,7 @@
else
Diag(Loc, diag::err_invalid_member_in_interface)
<< (InvalidDecl-1) << "";
- return 0;
+ return nullptr;
}
}
@@ -1960,14 +1961,19 @@
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member);
SourceLocation ConstexprLoc = DS.getConstexprSpecLoc();
if (InitStyle == ICIS_NoInit) {
- B << 0 << 0 << FixItHint::CreateReplacement(ConstexprLoc, "const");
- D.getMutableDeclSpec().ClearConstexprSpec();
- const char *PrevSpec;
- unsigned DiagID;
- bool Failed = D.getMutableDeclSpec().SetTypeQual(DeclSpec::TQ_const, ConstexprLoc,
- PrevSpec, DiagID, getLangOpts());
- (void)Failed;
- assert(!Failed && "Making a constexpr member const shouldn't fail");
+ B << 0 << 0;
+ if (D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const)
+ B << FixItHint::CreateRemoval(ConstexprLoc);
+ else {
+ B << FixItHint::CreateReplacement(ConstexprLoc, "const");
+ D.getMutableDeclSpec().ClearConstexprSpec();
+ const char *PrevSpec;
+ unsigned DiagID;
+ bool Failed = D.getMutableDeclSpec().SetTypeQual(
+ DeclSpec::TQ_const, ConstexprLoc, PrevSpec, DiagID, getLangOpts());
+ (void)Failed;
+ assert(!Failed && "Making a constexpr member const shouldn't fail");
+ }
} else {
B << 1;
const char *PrevSpec;
@@ -1993,7 +1999,7 @@
if (!Name.isIdentifier()) {
Diag(Loc, diag::err_bad_variable_name)
<< Name;
- return 0;
+ return nullptr;
}
IdentifierInfo *II = Name.getAsIdentifierInfo();
@@ -2016,7 +2022,7 @@
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
}
- return 0;
+ return nullptr;
}
if (SS.isSet() && !SS.isInvalid()) {
@@ -2041,7 +2047,7 @@
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS, MSPropertyAttr);
if (!Member)
- return 0;
+ return nullptr;
isInstField = false;
} else {
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
@@ -2053,7 +2059,7 @@
Member = HandleDeclarator(S, D, TemplateParameterLists);
if (!Member)
- return 0;
+ return nullptr;
// Non-instance-fields can't have a bitfield.
if (BitWidth) {
@@ -2076,7 +2082,7 @@
<< BitWidth->getSourceRange();
}
- BitWidth = 0;
+ BitWidth = nullptr;
Member->setInvalidDecl();
}
@@ -2287,7 +2293,7 @@
// In class initializers will point to the constructor.
UninitializedFieldVisitor(S, Decls, Constructor).Visit(E);
} else {
- UninitializedFieldVisitor(S, Decls, 0).Visit(E);
+ UninitializedFieldVisitor(S, Decls, nullptr).Visit(E);
}
}
@@ -2351,7 +2357,7 @@
SourceLocation InitLoc,
Expr *InitExpr) {
// Pop the notional constructor scope we created earlier.
- PopFunctionScopeInfo(0, D);
+ PopFunctionScopeInfo(nullptr, D);
FieldDecl *FD = cast<FieldDecl>(D);
assert(FD->getInClassInitStyle() != ICIS_NoInit &&
@@ -2406,7 +2412,7 @@
const CXXBaseSpecifier *&DirectBaseSpec,
const CXXBaseSpecifier *&VirtualBaseSpec) {
// First, check for a direct base class.
- DirectBaseSpec = 0;
+ DirectBaseSpec = nullptr;
for (const auto &Base : ClassDecl->bases()) {
if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base.getType())) {
// We found a direct base of this type. That's what we're
@@ -2419,7 +2425,7 @@
// Check for a virtual base class.
// FIXME: We might be able to short-circuit this if we know in advance that
// there are no virtual bases.
- VirtualBaseSpec = 0;
+ VirtualBaseSpec = nullptr;
if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
// We haven't found a base yet; search the class hierarchy for a
// virtual base class.
@@ -2556,7 +2562,7 @@
}
// It didn't name a member, so see if it names a class.
QualType BaseType;
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
if (TemplateTypeTy) {
BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
@@ -2598,7 +2604,7 @@
MemInitializerValidatorCCC Validator(ClassDecl);
if (R.empty() && BaseType.isNull() &&
(Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
- Validator, ClassDecl))) {
+ Validator, CTK_ErrorRecovery, ClassDecl))) {
if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
@@ -2741,15 +2747,17 @@
// Initialize the member.
InitializedEntity MemberEntity =
- DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
- : InitializedEntity::InitializeMember(IndirectMember, 0);
+ DirectMember ? InitializedEntity::InitializeMember(DirectMember, nullptr)
+ : InitializedEntity::InitializeMember(IndirectMember,
+ nullptr);
InitializationKind Kind =
InitList ? InitializationKind::CreateDirectList(IdLoc)
: InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
InitRange.getEnd());
InitializationSequence InitSeq(*this, MemberEntity, Kind, Args);
- ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args, 0);
+ ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args,
+ nullptr);
if (MemberInit.isInvalid())
return true;
@@ -2802,7 +2810,7 @@
InitRange.getEnd());
InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args);
ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
- Args, 0);
+ Args, nullptr);
if (DelegationInit.isInvalid())
return true;
@@ -2870,8 +2878,8 @@
}
// Check for direct and virtual base classes.
- const CXXBaseSpecifier *DirectBaseSpec = 0;
- const CXXBaseSpecifier *VirtualBaseSpec = 0;
+ const CXXBaseSpecifier *DirectBaseSpec = nullptr;
+ const CXXBaseSpecifier *VirtualBaseSpec = nullptr;
if (!Dependent) {
if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
BaseType))
@@ -2935,7 +2943,7 @@
: InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
InitRange.getEnd());
InitializationSequence InitSeq(*this, BaseEntity, Kind, Args);
- ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, 0);
+ ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr);
if (BaseInit.isInvalid())
return true;
@@ -3045,7 +3053,7 @@
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param, false,
Constructor->getLocation(), ParamType,
- VK_LValue, 0);
+ VK_LValue, nullptr);
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));
@@ -3118,7 +3126,7 @@
Expr *MemberExprBase =
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param, false,
- Loc, ParamType, VK_LValue, 0);
+ Loc, ParamType, VK_LValue, nullptr);
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase));
@@ -3139,9 +3147,9 @@
/*IsArrow=*/false,
SS,
/*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/0,
+ /*FirstQualifierInScope=*/nullptr,
MemberLookup,
- /*TemplateArgs=*/0);
+ /*TemplateArgs=*/nullptr);
if (CtorArg.isInvalid())
return true;
@@ -3164,7 +3172,7 @@
= SemaRef.Context.getAsConstantArrayType(BaseType)) {
InitializingArray = true;
// Create the iteration variable for this array index.
- IdentifierInfo *IterationVarName = 0;
+ IdentifierInfo *IterationVarName = nullptr;
{
SmallString<8> Str;
llvm::raw_svector_ostream OS(Str);
@@ -3318,7 +3326,7 @@
}
// Nothing to initialize.
- CXXMemberInit = 0;
+ CXXMemberInit = nullptr;
return false;
}
@@ -3430,12 +3438,13 @@
static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
FieldDecl *Field,
- IndirectFieldDecl *Indirect = 0) {
+ IndirectFieldDecl *Indirect = nullptr) {
if (Field->isInvalidDecl())
return false;
// Overwhelmingly common case: we have a direct initializer for this field.
- if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field))
+ if (CXXCtorInitializer *Init =
+ Info.AllBaseFields.lookup(Field->getCanonicalDecl()))
return Info.addFieldInitializer(Init);
// C++11 [class.base.init]p8:
@@ -3480,7 +3489,7 @@
if (Info.AnyErrorsInInits)
return false;
- CXXCtorInitializer *Init = 0;
+ CXXCtorInitializer *Init = nullptr;
if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field,
Indirect, Init))
return true;
@@ -3548,7 +3557,7 @@
if (Member->isBaseInitializer())
Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
else {
- Info.AllBaseFields[Member->getAnyMember()] = Member;
+ Info.AllBaseFields[Member->getAnyMember()->getCanonicalDecl()] = Member;
if (IndirectFieldDecl *F = Member->getIndirectMember()) {
for (auto *C : F->chain()) {
@@ -3696,7 +3705,7 @@
return;
}
}
- IdealInits.push_back(Field);
+ IdealInits.push_back(Field->getCanonicalDecl());
}
static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
@@ -3708,7 +3717,7 @@
if (!Member->isAnyMemberInitializer())
return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
- return Member->getAnyMember();
+ return Member->getAnyMember()->getCanonicalDecl();
}
static void DiagnoseBaseOrMemInitializerOrder(
@@ -3761,7 +3770,7 @@
unsigned NumIdealInits = IdealInitKeys.size();
unsigned IdealIndex = 0;
- CXXCtorInitializer *PrevInit = 0;
+ CXXCtorInitializer *PrevInit = nullptr;
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
const void *InitKey = GetKeyForMember(SemaRef.Context, Init);
@@ -3903,13 +3912,12 @@
Init->setSourceOrder(i);
if (Init->isAnyMemberInitializer()) {
- FieldDecl *Field = Init->getAnyMember();
- if (CheckRedundantInit(*this, Init, Members[Field]) ||
+ const void *Key = GetKeyForMember(Context, Init);
+ if (CheckRedundantInit(*this, Init, Members[Key]) ||
CheckRedundantUnionInit(*this, Init, MemberUnions))
HadError = true;
} else if (Init->isBaseInitializer()) {
- const void *Key =
- GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
+ const void *Key = GetKeyForMember(Context, Init);
if (CheckRedundantInit(*this, Init, Members[Key]))
HadError = true;
} else {
@@ -4044,7 +4052,7 @@
CheckDerivedToBaseConversion(
Context.getTypeDeclType(ClassDecl), VBase.getType(),
diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(),
- SourceRange(), DeclarationName(), 0);
+ SourceRange(), DeclarationName(), nullptr);
}
MarkFunctionReferenced(Location, Dtor);
@@ -4406,7 +4414,8 @@
// Warn if the class has virtual methods but non-virtual public destructor.
if (Record->isPolymorphic() && !Record->isDependentType()) {
CXXDestructorDecl *dtor = Record->getDestructor();
- if (!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public))
+ if ((!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) &&
+ !Record->hasAttr<FinalAttr>())
Diag(dtor ? dtor->getLocation() : Record->getLocation(),
diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
}
@@ -5265,7 +5274,7 @@
// operator is defined as deleted.
if (MD->isImplicit() &&
(CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) {
- CXXMethodDecl *UserDeclaredMove = 0;
+ CXXMethodDecl *UserDeclaredMove = nullptr;
// In Microsoft mode, a user-declared move only causes the deletion of the
// corresponding copy operation, not both copy operations.
@@ -5311,7 +5320,7 @@
// -- for a virtual destructor, lookup of the non-array deallocation function
// results in an ambiguity or in a function that is deleted or inaccessible
if (CSM == CXXDestructor && MD->isVirtual()) {
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
DeclarationName Name =
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name,
@@ -5360,7 +5369,7 @@
Sema::CXXSpecialMember CSM, unsigned Quals,
bool ConstRHS, CXXMethodDecl **Selected) {
if (Selected)
- *Selected = 0;
+ *Selected = nullptr;
switch (CSM) {
case Sema::CXXInvalid:
@@ -5379,7 +5388,7 @@
// If there's a default constructor which could have been trivial, dig it
// out. Otherwise, if there's any user-provided default constructor, point
// to that as an example of why there's not a trivial one.
- CXXConstructorDecl *DefCtor = 0;
+ CXXConstructorDecl *DefCtor = nullptr;
if (RD->needsImplicitDefaultConstructor())
S.DeclareImplicitDefaultConstructor(RD);
for (auto *CI : RD->ctors()) {
@@ -5486,7 +5495,7 @@
return CD;
}
- return 0;
+ return nullptr;
}
/// The kind of subobject we are checking for triviality. The values of this
@@ -5512,7 +5521,7 @@
CXXMethodDecl *Selected;
if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
- ConstRHS, Diagnose ? &Selected : 0))
+ ConstRHS, Diagnose ? &Selected : nullptr))
return true;
if (Diagnose) {
@@ -5973,47 +5982,55 @@
}
}
-void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) {
+unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
if (!D)
- return;
+ return 0;
- int NumParamList = D->getNumTemplateParameterLists();
- for (int i = 0; i < NumParamList; i++) {
- TemplateParameterList* Params = D->getTemplateParameterList(i);
- for (TemplateParameterList::iterator Param = Params->begin(),
- ParamEnd = Params->end();
- Param != ParamEnd; ++Param) {
- NamedDecl *Named = cast<NamedDecl>(*Param);
- if (Named->getDeclName()) {
- S->AddDecl(Named);
- IdResolver.AddDecl(Named);
+ // The order of template parameters is not important here. All names
+ // get added to the same scope.
+ SmallVector<TemplateParameterList *, 4> ParameterLists;
+
+ if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+ D = TD->getTemplatedDecl();
+
+ if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+ ParameterLists.push_back(PSD->getTemplateParameters());
+
+ if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
+ for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i)
+ ParameterLists.push_back(DD->getTemplateParameterList(i));
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
+ ParameterLists.push_back(FTD->getTemplateParameters());
+ }
+ }
+
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i)
+ ParameterLists.push_back(TD->getTemplateParameterList(i));
+
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
+ if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
+ ParameterLists.push_back(CTD->getTemplateParameters());
+ }
+ }
+
+ unsigned Count = 0;
+ for (TemplateParameterList *Params : ParameterLists) {
+ if (Params->size() > 0)
+ // Ignore explicit specializations; they don't contribute to the template
+ // depth.
+ ++Count;
+ for (NamedDecl *Param : *Params) {
+ if (Param->getDeclName()) {
+ S->AddDecl(Param);
+ IdResolver.AddDecl(Param);
}
}
}
-}
-void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
- if (!D)
- return;
-
- TemplateParameterList *Params = 0;
- if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
- Params = Template->getTemplateParameters();
- else if (ClassTemplatePartialSpecializationDecl *PartialSpec
- = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
- Params = PartialSpec->getTemplateParameters();
- else
- return;
-
- for (TemplateParameterList::iterator Param = Params->begin(),
- ParamEnd = Params->end();
- Param != ParamEnd; ++Param) {
- NamedDecl *Named = cast<NamedDecl>(*Param);
- if (Named->getDeclName()) {
- S->AddDecl(Named);
- IdResolver.AddDecl(Named);
- }
- }
+ return Count;
}
void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
@@ -6065,7 +6082,7 @@
// If this parameter has an unparsed default argument, clear it out
// to make way for the parsed default argument.
if (Param->hasUnparsedDefaultArg())
- Param->setDefaultArg(0);
+ Param->setDefaultArg(nullptr);
S->AddDecl(Param);
if (Param->getDeclName())
@@ -6218,7 +6235,7 @@
Loc = RD->getLocation();
// If we have a virtual destructor, look up the deallocation function
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
DeclarationName Name =
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
@@ -6236,13 +6253,6 @@
return false;
}
-static inline bool
-FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
- return (FTI.NumParams == 1 && !FTI.isVariadic && FTI.Params[0].Ident == 0 &&
- FTI.Params[0].Param &&
- cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType());
-}
-
/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
/// the well-formednes of the destructor declarator @p D with type @p
/// R. If there are any errors in the declarator, this routine will
@@ -6321,7 +6331,7 @@
}
// Make sure we don't have any parameters.
- if (FTI.NumParams > 0 && !FTIHasSingleVoidArgument(FTI)) {
+ if (FTIHasNonVoidParameters(FTI)) {
Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
// Delete the parameters.
@@ -6548,7 +6558,7 @@
bool AddToKnown = false;
Scope *DeclRegionScope = NamespcScope->getParent();
- NamespaceDecl *PrevNS = 0;
+ NamespaceDecl *PrevNS = nullptr;
if (II) {
// C++ [namespace.def]p2:
// The identifier in an original-namespace-definition shall not
@@ -6564,7 +6574,7 @@
const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member |
Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag |
Decl::IDNS_Namespace;
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II);
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I) {
@@ -6725,7 +6735,7 @@
/*Inline=*/false,
SourceLocation(), SourceLocation(),
&PP.getIdentifierTable().get("std"),
- /*PrevDecl=*/0);
+ /*PrevDecl=*/nullptr);
getStdNamespace()->setImplicit(true);
}
@@ -6742,8 +6752,8 @@
if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it.
return false;
- ClassTemplateDecl *Template = 0;
- const TemplateArgument *Arguments = 0;
+ ClassTemplateDecl *Template = nullptr;
+ const TemplateArgument *Arguments = nullptr;
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -6796,14 +6806,14 @@
NamespaceDecl *Std = S.getStdNamespace();
if (!Std) {
S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
- return 0;
+ return nullptr;
}
LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"),
Loc, Sema::LookupOrdinaryName);
if (!S.LookupQualifiedName(Result, Std)) {
S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
- return 0;
+ return nullptr;
}
ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>();
if (!Template) {
@@ -6811,7 +6821,7 @@
// We found something weird. Complain about the first thing we found.
NamedDecl *Found = *Result.begin();
S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list);
- return 0;
+ return nullptr;
}
// We found some template called std::initializer_list. Now verify that it's
@@ -6820,7 +6830,7 @@
if (Params->getMinRequiredArguments() != 1 ||
!isa<TemplateTypeParmDecl>(Params->getParam(0))) {
S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list);
- return 0;
+ return nullptr;
}
return Template;
@@ -6855,7 +6865,7 @@
if (const ReferenceType *RT = ArgType->getAs<ReferenceType>())
ArgType = RT->getPointeeType().getUnqualifiedType();
- return isStdInitializerList(ArgType, 0);
+ return isStdInitializerList(ArgType, nullptr);
}
/// \brief Determine whether a using statement is in a context where it will be
@@ -6893,7 +6903,8 @@
R.clear();
if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), Sc, &SS,
- Validator)) {
+ Validator,
+ Sema::CTK_ErrorRecovery)) {
if (DeclContext *DC = S.computeDeclContext(SS, false)) {
std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
@@ -6929,8 +6940,8 @@
S = S->getParent();
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
- UsingDirectiveDecl *UDir = 0;
- NestedNameSpecifier *Qualifier = 0;
+ UsingDirectiveDecl *UDir = nullptr;
+ NestedNameSpecifier *Qualifier = nullptr;
if (SS.isSet())
Qualifier = SS.getScopeRep();
@@ -6938,7 +6949,7 @@
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
if (R.isAmbiguous())
- return 0;
+ return nullptr;
if (R.empty()) {
R.clear();
@@ -7003,7 +7014,7 @@
if (Ctx && !Ctx->isFunctionOrMethod())
Ctx->addDecl(UDir);
else
- // Otherwise, it is at block sope. The using-directives will affect lookup
+ // Otherwise, it is at block scope. The using-directives will affect lookup
// only to the end of the scope.
S->PushUsingDirective(UDir);
}
@@ -7039,23 +7050,23 @@
if (getLangOpts().CPlusPlus11) break;
- return 0;
-
+ return nullptr;
+
case UnqualifiedId::IK_DestructorName:
Diag(Name.getLocStart(), diag::err_using_decl_destructor)
<< SS.getRange();
- return 0;
-
+ return nullptr;
+
case UnqualifiedId::IK_TemplateId:
Diag(Name.getLocStart(), diag::err_using_decl_template_id)
<< SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
- return 0;
+ return nullptr;
}
DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
DeclarationName TargetName = TargetNameInfo.getName();
if (!TargetName)
- return 0;
+ return nullptr;
// Warn about access declarations.
if (!HasUsingKeyword) {
@@ -7067,7 +7078,7 @@
if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
- return 0;
+ return nullptr;
NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
TargetNameInfo, AttrList,
@@ -7159,7 +7170,7 @@
//
// FIXME: but we might be increasing its access, in which case we
// should redeclare it.
- NamedDecl *NonTag = 0, *Tag = 0;
+ NamedDecl *NonTag = nullptr, *Tag = nullptr;
bool FoundEquivalentDecl = false;
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
@@ -7177,8 +7188,9 @@
return false;
if (FunctionDecl *FD = Target->getAsFunction()) {
- NamedDecl *OldDecl = 0;
- switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) {
+ NamedDecl *OldDecl = nullptr;
+ switch (CheckOverload(nullptr, FD, Previous, OldDecl,
+ /*IsForUsingDecl*/ true)) {
case Ovl_Overload:
return false;
@@ -7306,13 +7318,30 @@
// be possible for this to happen, because...?
}
+/// Find the base specifier for a base class with the given type.
+static CXXBaseSpecifier *findDirectBaseWithType(CXXRecordDecl *Derived,
+ QualType DesiredBase,
+ bool &AnyDependentBases) {
+ // Check whether the named type is a direct base class.
+ CanQualType CanonicalDesiredBase = DesiredBase->getCanonicalTypeUnqualified();
+ for (auto &Base : Derived->bases()) {
+ CanQualType BaseType = Base.getType()->getCanonicalTypeUnqualified();
+ if (CanonicalDesiredBase == BaseType)
+ return &Base;
+ if (BaseType->isDependentType())
+ AnyDependentBases = true;
+ }
+ return nullptr;
+}
+
namespace {
class UsingValidatorCCC : public CorrectionCandidateCallback {
public:
UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
- bool RequireMember)
+ NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf)
: HasTypenameKeyword(HasTypenameKeyword),
- IsInstantiation(IsInstantiation), RequireMember(RequireMember) {}
+ IsInstantiation(IsInstantiation), OldNNS(NNS),
+ RequireMemberOf(RequireMemberOf) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
@@ -7321,14 +7350,48 @@
if (!ND || isa<NamespaceDecl>(ND))
return false;
- if (RequireMember && !isa<FieldDecl>(ND) && !isa<CXXMethodDecl>(ND) &&
- !isa<TypeDecl>(ND))
- return false;
-
// Completely unqualified names are invalid for a 'using' declaration.
if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier())
return false;
+ if (RequireMemberOf) {
+ auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND);
+ if (FoundRecord && FoundRecord->isInjectedClassName()) {
+ // No-one ever wants a using-declaration to name an injected-class-name
+ // of a base class, unless they're declaring an inheriting constructor.
+ ASTContext &Ctx = ND->getASTContext();
+ if (!Ctx.getLangOpts().CPlusPlus11)
+ return false;
+ QualType FoundType = Ctx.getRecordType(FoundRecord);
+
+ // Check that the injected-class-name is named as a member of its own
+ // type; we don't want to suggest 'using Derived::Base;', since that
+ // means something else.
+ NestedNameSpecifier *Specifier =
+ Candidate.WillReplaceSpecifier()
+ ? Candidate.getCorrectionSpecifier()
+ : OldNNS;
+ if (!Specifier->getAsType() ||
+ !Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType))
+ return false;
+
+ // Check that this inheriting constructor declaration actually names a
+ // direct base class of the current class.
+ bool AnyDependentBases = false;
+ if (!findDirectBaseWithType(RequireMemberOf,
+ Ctx.getRecordType(FoundRecord),
+ AnyDependentBases) &&
+ !AnyDependentBases)
+ return false;
+ } else {
+ auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext());
+ if (!RD || RequireMemberOf->isProvablyNotDerivedFrom(RD))
+ return false;
+
+ // FIXME: Check that the base class member is accessible?
+ }
+ }
+
if (isa<TypeDecl>(ND))
return HasTypenameKeyword || !IsInstantiation;
@@ -7338,7 +7401,8 @@
private:
bool HasTypenameKeyword;
bool IsInstantiation;
- bool RequireMember;
+ NestedNameSpecifier *OldNNS;
+ CXXRecordDecl *RequireMemberOf;
};
} // end anonymous namespace
@@ -7350,7 +7414,7 @@
NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
+ DeclarationNameInfo NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
bool HasTypenameKeyword,
@@ -7363,7 +7427,7 @@
if (SS.isEmpty()) {
Diag(IdentLoc, diag::err_using_requires_qualname);
- return 0;
+ return nullptr;
}
// Do the redeclaration lookup in the current scope.
@@ -7379,6 +7443,13 @@
NamedDecl *D = F.next();
if (!isDeclInScope(D, CurContext, S))
F.erase();
+ // If we found a local extern declaration that's not ordinarily visible,
+ // and this declaration is being added to a non-block scope, ignore it.
+ // We're only checking for scope conflicts here, not also for violations
+ // of the linkage rules.
+ else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() &&
+ !(D->getIdentifierNamespace() & Decl::IDNS_Ordinary))
+ F.erase();
}
F.done();
} else {
@@ -7390,11 +7461,11 @@
// Check for invalid redeclarations.
if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword,
SS, IdentLoc, Previous))
- return 0;
+ return nullptr;
// Check for bad qualifiers.
if (CheckUsingDeclQualifier(UsingLoc, SS, NameInfo, IdentLoc))
- return 0;
+ return nullptr;
DeclContext *LookupContext = computeDeclContext(SS);
NamedDecl *D;
@@ -7410,25 +7481,30 @@
D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
QualifierLoc, NameInfo);
}
- } else {
- D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
- NameInfo, HasTypenameKeyword);
+ D->setAccess(AS);
+ CurContext->addDecl(D);
+ return D;
}
- D->setAccess(AS);
- CurContext->addDecl(D);
- if (!LookupContext) return D;
- UsingDecl *UD = cast<UsingDecl>(D);
-
- if (RequireCompleteDeclContext(SS, LookupContext)) {
- UD->setInvalidDecl();
+ auto Build = [&](bool Invalid) {
+ UsingDecl *UD =
+ UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, NameInfo,
+ HasTypenameKeyword);
+ UD->setAccess(AS);
+ CurContext->addDecl(UD);
+ UD->setInvalidDecl(Invalid);
return UD;
- }
+ };
+ auto BuildInvalid = [&]{ return Build(true); };
+ auto BuildValid = [&]{ return Build(false); };
+
+ if (RequireCompleteDeclContext(SS, LookupContext))
+ return BuildInvalid();
// The normal rules do not apply to inheriting constructor declarations.
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
- if (CheckInheritingConstructorUsingDecl(UD))
- UD->setInvalidDecl();
+ UsingDecl *UD = BuildValid();
+ CheckInheritingConstructorUsingDecl(UD);
return UD;
}
@@ -7454,31 +7530,53 @@
// Try to correct typos if possible.
if (R.empty()) {
- UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation,
- CurContext->isRecord());
+ UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
+ dyn_cast<CXXRecordDecl>(CurContext));
if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), S, &SS, CCC)){
+ R.getLookupKind(), S, &SS, CCC,
+ CTK_ErrorRecovery)){
// We reject any correction for which ND would be NULL.
NamedDecl *ND = Corrected.getCorrectionDecl();
- R.setLookupName(Corrected.getCorrection());
- R.addDecl(ND);
+
// We reject candidates where DroppedSpecifier == true, hence the
// literal '0' below.
diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
<< NameInfo.getName() << LookupContext << 0
<< SS.getRange());
+
+ // If we corrected to an inheriting constructor, handle it as one.
+ auto *RD = dyn_cast<CXXRecordDecl>(ND);
+ if (RD && RD->isInjectedClassName()) {
+ // Fix up the information we'll use to build the using declaration.
+ if (Corrected.WillReplaceSpecifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
+ QualifierLoc.getSourceRange());
+ QualifierLoc = Builder.getWithLocInContext(Context);
+ }
+
+ 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;
+ }
+
+ // 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();
- UD->setInvalidDecl();
- return UD;
+ return BuildInvalid();
}
}
- if (R.isAmbiguous()) {
- UD->setInvalidDecl();
- return UD;
- }
+ if (R.isAmbiguous())
+ return BuildInvalid();
if (HasTypenameKeyword) {
// If we asked for a typename and got a non-type decl, error out.
@@ -7487,8 +7585,7 @@
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
Diag((*I)->getUnderlyingDecl()->getLocation(),
diag::note_using_decl_target);
- UD->setInvalidDecl();
- return UD;
+ return BuildInvalid();
}
} else {
// If we asked for a non-typename and we got a type, error out,
@@ -7497,8 +7594,7 @@
if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_dependent_value_is_type);
Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
- UD->setInvalidDecl();
- return UD;
+ return BuildInvalid();
}
}
@@ -7507,12 +7603,12 @@
if (R.getAsSingle<NamespaceDecl>()) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
<< SS.getRange();
- UD->setInvalidDecl();
- return UD;
+ return BuildInvalid();
}
+ UsingDecl *UD = BuildValid();
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- UsingShadowDecl *PrevDecl = 0;
+ UsingShadowDecl *PrevDecl = nullptr;
if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
BuildUsingShadowDecl(S, UD, *I, PrevDecl);
}
@@ -7530,28 +7626,20 @@
CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);
// Check whether the named type is a direct base class.
- CanQualType CanonicalSourceType = SourceType->getCanonicalTypeUnqualified();
- CXXRecordDecl::base_class_iterator BaseIt, BaseE;
- for (BaseIt = TargetClass->bases_begin(), BaseE = TargetClass->bases_end();
- BaseIt != BaseE; ++BaseIt) {
- CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified();
- if (CanonicalSourceType == BaseType)
- break;
- if (BaseIt->getType()->isDependentType())
- break;
- }
-
- if (BaseIt == BaseE) {
- // Did not find SourceType in the bases.
+ bool AnyDependentBases = false;
+ auto *Base = findDirectBaseWithType(TargetClass, QualType(SourceType, 0),
+ AnyDependentBases);
+ if (!Base && !AnyDependentBases) {
Diag(UD->getUsingLoc(),
diag::err_using_decl_constructor_not_in_direct_base)
<< UD->getNameInfo().getSourceRange()
<< QualType(SourceType, 0) << TargetClass;
+ UD->setInvalidDecl();
return true;
}
- if (!CurContext->isDependentContext())
- BaseIt->setInheritConstructors();
+ if (Base)
+ Base->setInheritConstructors();
return false;
}
@@ -7633,7 +7721,7 @@
if (!NamedContext || NamedContext->isRecord()) {
auto *RD = dyn_cast<CXXRecordDecl>(NamedContext);
if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD))
- RD = 0;
+ RD = nullptr;
Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
<< SS.getRange();
@@ -7812,15 +7900,15 @@
"got alias-declaration outside of declaration scope");
if (Type.isInvalid())
- return 0;
+ return nullptr;
bool Invalid = false;
DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name);
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
GetTypeFromParser(Type.get(), &TInfo);
if (DiagnoseClassNameShadow(CurContext, NameInfo))
- return 0;
+ return nullptr;
if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo,
UPPC_DeclarationType)) {
@@ -7859,8 +7947,8 @@
NamedDecl *NewND;
if (TemplateParamLists.size()) {
- TypeAliasTemplateDecl *OldDecl = 0;
- TemplateParameterList *OldTemplateParams = 0;
+ TypeAliasTemplateDecl *OldDecl = nullptr;
+ TemplateParameterList *OldTemplateParams = nullptr;
if (TemplateParamLists.size() != 1) {
Diag(UsingLoc, diag::err_alias_template_extra_headers)
@@ -7915,7 +8003,7 @@
// and check the parameter list.
if (CheckTemplateParameterList(TemplateParams, OldTemplateParams,
TPC_TypeAliasTemplate))
- return 0;
+ return nullptr;
TypeAliasTemplateDecl *NewDecl =
TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc,
@@ -7959,7 +8047,7 @@
= LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName,
ForRedeclaration);
if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
- PrevDecl = 0;
+ PrevDecl = nullptr;
if (PrevDecl) {
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
@@ -7969,23 +8057,23 @@
// declaration to maintain better source information.
if (!R.isAmbiguous() && !R.empty() &&
AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl())))
- return 0;
+ return nullptr;
}
unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition :
diag::err_redefinition_different_kind;
Diag(AliasLoc, DiagID) << Alias;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- return 0;
+ return nullptr;
}
if (R.isAmbiguous())
- return 0;
+ return nullptr;
if (R.empty()) {
if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
- return 0;
+ return nullptr;
}
}
@@ -8183,7 +8271,7 @@
DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXDefaultConstructor,
@@ -8197,9 +8285,9 @@
= Context.DeclarationNames.getCXXConstructorName(ClassType);
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
- Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(), /*TInfo=*/0,
- /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
- Constexpr);
+ Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(),
+ /*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true, Constexpr);
DefaultCon->setAccess(AS_public);
DefaultCon->setDefaulted();
DefaultCon->setImplicit();
@@ -8285,7 +8373,7 @@
/// Information about an inheriting constructor.
struct InheritingConstructor {
InheritingConstructor()
- : DeclaredInDerived(false), BaseCtor(0), DerivedCtor(0) {}
+ : DeclaredInDerived(false), BaseCtor(nullptr), DerivedCtor(nullptr) {}
/// If \c true, a constructor with this signature is already declared
/// in the derived class.
@@ -8466,7 +8554,7 @@
Context.getCanonicalType(Context.getRecordType(Derived)));
DeclarationNameInfo NameInfo(Name, UsingLoc);
- TemplateParameterList *TemplateParams = 0;
+ TemplateParameterList *TemplateParams = nullptr;
if (const FunctionTemplateDecl *FTD =
BaseCtor->getDescribedFunctionTemplate()) {
TemplateParams = FTD->getTemplateParameters();
@@ -8503,8 +8591,8 @@
TypeSourceInfo *TInfo =
Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc);
ParmVarDecl *PD = ParmVarDecl::Create(
- Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/0,
- FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/0);
+ Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr,
+ FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr);
PD->setScopeInfo(0, I);
PD->setImplicit();
ParamDecls.push_back(PD);
@@ -8640,7 +8728,7 @@
DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
// Create the actual destructor declaration.
CanQualType ClassType
@@ -8651,7 +8739,7 @@
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXDestructorDecl *Destructor
= CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
- QualType(), 0, /*isInline=*/true,
+ QualType(), nullptr, /*isInline=*/true,
/*isImplicitlyDeclared=*/true);
Destructor->setAccess(AS_public);
Destructor->setDefaulted();
@@ -8840,8 +8928,8 @@
public:
virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
- Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), 0,
- MemberLookup, 0).take());
+ Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(),
+ nullptr, MemberLookup, nullptr).take());
}
MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
@@ -8932,13 +9020,13 @@
return StmtError();
ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
- VK_RValue, Loc, 0);
+ VK_RValue, Loc, nullptr);
assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");
Expr *CallArgs[] = {
To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc)
};
- ExprResult Call = S.ActOnCallExpr(/*Scope=*/0, MemCpyRef.take(),
+ ExprResult Call = S.ActOnCallExpr(/*Scope=*/nullptr, MemCpyRef.take(),
Loc, CallArgs, Loc);
assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
@@ -9041,7 +9129,7 @@
CXXScopeSpec SS;
const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
SS.MakeTrivial(S.Context,
- NestedNameSpecifier::Create(S.Context, 0, false,
+ NestedNameSpecifier::Create(S.Context, nullptr, false,
CanonicalT),
Loc);
@@ -9049,9 +9137,9 @@
ExprResult OpEqualRef
= S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false,
SS, /*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/0,
+ /*FirstQualifierInScope=*/nullptr,
OpLookup,
- /*TemplateArgs=*/0,
+ /*TemplateArgs=*/nullptr,
/*SuppressQualifierCheck=*/true);
if (OpEqualRef.isInvalid())
return StmtError();
@@ -9059,7 +9147,7 @@
// Build the call to the assignment operator.
Expr *FromInst = From.build(S, Loc);
- ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
+ ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/nullptr,
OpEqualRef.takeAs<Expr>(),
Loc, FromInst, Loc);
if (Call.isInvalid())
@@ -9069,7 +9157,7 @@
// bail out. We'll replace the whole shebang with a memcpy.
CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Call.get());
if (CE && CE->getMethodDecl()->isTrivial() && Depth)
- return StmtResult((Stmt*)0);
+ return StmtResult((Stmt*)nullptr);
// Convert to an expression-statement, and clean up any produced
// temporaries.
@@ -9098,7 +9186,7 @@
QualType SizeType = S.Context.getSizeType();
// Create the iteration variable.
- IdentifierInfo *IterationVarName = 0;
+ IdentifierInfo *IterationVarName = nullptr;
{
SmallString<8> Str;
llvm::raw_svector_ostream OS(Str);
@@ -9158,7 +9246,7 @@
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(Loc, Loc, InitStmt,
S.MakeFullExpr(Comparison),
- 0, S.MakeFullDiscardedValueExpr(Increment),
+ nullptr, S.MakeFullDiscardedValueExpr(Increment),
Loc, Copy.take());
}
@@ -9248,7 +9336,7 @@
DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
QualType ArgType = Context.getTypeDeclType(ClassDecl);
QualType RetType = Context.getLValueReferenceType(ArgType);
@@ -9268,8 +9356,8 @@
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *CopyAssignment =
CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/ 0, /*StorageClass=*/ SC_None,
- /*isInline=*/ true, Constexpr, SourceLocation());
+ /*TInfo=*/nullptr, /*StorageClass=*/SC_None,
+ /*isInline=*/true, Constexpr, SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setDefaulted();
CopyAssignment->setImplicit();
@@ -9281,9 +9369,10 @@
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
- ClassLoc, ClassLoc, /*Id=*/0,
- ArgType, /*TInfo=*/0,
- SC_None, 0);
+ ClassLoc, ClassLoc,
+ /*Id=*/nullptr, ArgType,
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
CopyAssignment->setParams(FromParam);
AddOverriddenMethods(ClassDecl, CopyAssignment);
@@ -9314,7 +9403,7 @@
assert(CopyOp->isImplicit());
CXXRecordDecl *RD = CopyOp->getParent();
- CXXMethodDecl *UserDeclaredOperation = 0;
+ CXXMethodDecl *UserDeclaredOperation = nullptr;
// In Microsoft mode, assignment operations don't affect constructors and
// vice versa.
@@ -9531,7 +9620,7 @@
// Add a "return *this;"
ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
- StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
+ StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else {
@@ -9622,7 +9711,7 @@
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
// Note: The following rules are largely analoguous to the move
// constructor rules.
@@ -9642,7 +9731,7 @@
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *MoveAssignment =
CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0, /*StorageClass=*/SC_None,
+ /*TInfo=*/nullptr, /*StorageClass=*/SC_None,
/*isInline=*/true, Constexpr, SourceLocation());
MoveAssignment->setAccess(AS_public);
MoveAssignment->setDefaulted();
@@ -9655,9 +9744,10 @@
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
- ClassLoc, ClassLoc, /*Id=*/0,
- ArgType, /*TInfo=*/0,
- SC_None, 0);
+ ClassLoc, ClassLoc,
+ /*Id=*/nullptr, ArgType,
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
MoveAssignment->setParams(FromParam);
AddOverriddenMethods(ClassDecl, MoveAssignment);
@@ -9749,7 +9839,7 @@
<< Base << BI.getType() << BaseSpec->getSourceRange();
// Only diagnose each vbase once.
- Existing = 0;
+ Existing = nullptr;
}
} else {
// Only walk over bases that have defaulted move assignment operators.
@@ -9949,7 +10039,7 @@
// Add a "return *this;"
ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
- StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
+ StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else {
@@ -10037,7 +10127,7 @@
DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = ClassType;
@@ -10059,7 +10149,7 @@
// An implicitly-declared copy constructor is an inline public
// member of its class.
CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(
- Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/0,
+ Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
/*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
Constexpr);
CopyConstructor->setAccess(AS_public);
@@ -10074,9 +10164,9 @@
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
ClassLoc, ClassLoc,
- /*IdentifierInfo=*/0,
- ArgType, /*TInfo=*/0,
- SC_None, 0);
+ /*IdentifierInfo=*/nullptr,
+ ArgType, /*TInfo=*/nullptr,
+ SC_None, nullptr);
CopyConstructor->setParams(FromParam);
CopyConstructor->setTrivial(
@@ -10201,7 +10291,7 @@
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = Context.getRValueReferenceType(ClassType);
@@ -10220,7 +10310,7 @@
// An implicitly-declared copy/move constructor is an inline public
// member of its class.
CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
- Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/0,
+ Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
/*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
Constexpr);
MoveConstructor->setAccess(AS_public);
@@ -10235,9 +10325,9 @@
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
ClassLoc, ClassLoc,
- /*IdentifierInfo=*/0,
- ArgType, /*TInfo=*/0,
- SC_None, 0);
+ /*IdentifierInfo=*/nullptr,
+ ArgType, /*TInfo=*/nullptr,
+ SC_None, nullptr);
MoveConstructor->setParams(FromParam);
MoveConstructor->setTrivial(
@@ -10306,16 +10396,15 @@
// cache the deduced template arguments for this specialization
// so that we can use them to retrieve the corresponding call-operator
// and static-invoker.
- const TemplateArgumentList *DeducedTemplateArgs = 0;
-
-
+ const TemplateArgumentList *DeducedTemplateArgs = nullptr;
+
// Retrieve the corresponding call-operator specialization.
if (Lambda->isGenericLambda()) {
assert(Conv->isFunctionTemplateSpecialization());
FunctionTemplateDecl *CallOpTemplate =
CallOp->getDescribedFunctionTemplate();
DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
DeducedTemplateArgs->data(),
DeducedTemplateArgs->size(),
@@ -10342,7 +10431,7 @@
"Must have deduced template arguments from Conversion Operator");
FunctionTemplateDecl *InvokeTemplate =
Invoker->getDescribedFunctionTemplate();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
DeducedTemplateArgs->data(),
DeducedTemplateArgs->size(),
@@ -10355,7 +10444,7 @@
Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
VK_LValue, Conv->getLocation()).take();
assert(FunctionRef && "Can't refer to __invoke function?");
- Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
+ Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).take();
Conv->setBody(new (Context) CompoundStmt(Context, Return,
Conv->getLocation(),
Conv->getLocation()));
@@ -10403,7 +10492,7 @@
if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount)
BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(),
CK_CopyAndAutoreleaseBlockObject,
- BuildBlock.get(), 0, VK_RValue);
+ BuildBlock.get(), nullptr, VK_RValue);
if (BuildBlock.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
@@ -10413,7 +10502,7 @@
// Create the return statement that returns the block from the conversion
// function.
- StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock.get());
+ StmtResult Return = BuildReturnStmt(Conv->getLocation(), BuildBlock.get());
if (Return.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
Conv->setInvalidDecl();
@@ -10996,7 +11085,7 @@
if (!Lit->isAscii()) {
Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_not_ascii)
<< LangStr->getSourceRange();
- return 0;
+ return nullptr;
}
StringRef Lang = Lit->getString();
@@ -11008,7 +11097,7 @@
else {
Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_unknown)
<< LangStr->getSourceRange();
- return 0;
+ return nullptr;
}
// FIXME: Add all the various semantics of linkage specifications
@@ -11195,7 +11284,7 @@
if (PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
}
@@ -11229,7 +11318,7 @@
StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr);
if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
- return 0;
+ return nullptr;
return BuildStaticAssertDeclaration(StaticAssertLoc, AssertExpr,
AssertMessage, RParenLoc, false);
@@ -11257,7 +11346,7 @@
if (!Failed && !Cond) {
SmallString<256> MsgBuffer;
llvm::raw_svector_ostream Msg(MsgBuffer);
- AssertMessage->printPretty(Msg, 0, getPrintingPolicy());
+ AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
Diag(StaticAssertLoc, diag::err_static_assert_failed)
<< Msg.str() << AssertExpr->getSourceRange();
Failed = true;
@@ -11298,9 +11387,10 @@
// a tag in front.
if (const RecordType *RT = T->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
-
- std::string InsertionText = std::string(" ") + RD->getKindName();
-
+
+ SmallString<16> InsertionText(" ");
+ InsertionText += RD->getKindName();
+
Diag(TypeRange.getBegin(),
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_unelaborated_friend_type :
@@ -11339,7 +11429,9 @@
// If the type specifier in a friend declaration designates a (possibly
// cv-qualified) class type, that class is declared as a friend; otherwise,
// the friend declaration is ignored.
- return FriendDecl::Create(Context, CurContext, LocStart, TSInfo, FriendLoc);
+ return FriendDecl::Create(Context, CurContext,
+ TSInfo->getTypeLoc().getLocStart(), TSInfo,
+ FriendLoc);
}
/// Handle a friend tag declaration where the scope specifier was
@@ -11358,12 +11450,12 @@
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
- TagLoc, NameLoc, SS, TempParamLists, /*friend*/ true,
+ TagLoc, NameLoc, SS, nullptr, TempParamLists, /*friend*/ true,
isExplicitSpecialization, Invalid)) {
if (TemplateParams->size() > 0) {
// This is a declaration of a class template.
if (Invalid)
- return 0;
+ return nullptr;
return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
SS, Name, NameLoc, Attr,
@@ -11379,7 +11471,7 @@
}
}
- if (Invalid) return 0;
+ if (Invalid) return nullptr;
bool isAllExplicitSpecializations = true;
for (unsigned I = TempParamLists.size(); I-- > 0; ) {
@@ -11414,7 +11506,7 @@
QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc,
*Name, NameLoc);
if (T.isNull())
- return 0;
+ return nullptr;
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
@@ -11494,10 +11586,10 @@
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
- return 0;
+ return nullptr;
if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration))
- return 0;
+ return nullptr;
// This is definitely an error in C++98. It's probably meant to
// be forbidden in C++0x, too, but the specification is just
@@ -11516,7 +11608,7 @@
if (TempParams.size() && !T->isElaboratedTypeSpecifier()) {
Diag(Loc, diag::err_tagless_friend_type_template)
<< DS.getSourceRange();
- return 0;
+ return nullptr;
}
// C++98 [class.friend]p1: A friend of a class is a function
@@ -11541,8 +11633,8 @@
D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI);
if (!D)
- return 0;
-
+ return nullptr;
+
D->setAccess(AS_public);
CurContext->addDecl(D);
@@ -11574,7 +11666,7 @@
// It might be worthwhile to try to recover by creating an
// appropriate declaration.
- return 0;
+ return nullptr;
}
// C++ [namespace.memdef]p3
@@ -11601,7 +11693,7 @@
if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) ||
DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) ||
DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
- return 0;
+ return nullptr;
// The context we found the declaration in, or in which we should
// create the declaration.
@@ -11614,7 +11706,7 @@
// - There's no scope specifier and we're in a local class. Only look
// for functions declared in the immediately-enclosing block scope.
// We recover from invalid scope qualifiers as if they just weren't there.
- FunctionDecl *FunctionContainingLocalClass = 0;
+ FunctionDecl *FunctionContainingLocalClass = nullptr;
if ((SS.isInvalid() || !SS.isSet()) &&
(FunctionContainingLocalClass =
cast<CXXRecordDecl>(CurContext)->isLocalClass())) {
@@ -11707,9 +11799,9 @@
// or function template.
} else if (!SS.getScopeRep()->isDependent()) {
DC = computeDeclContext(SS);
- if (!DC) return 0;
+ if (!DC) return nullptr;
- if (RequireCompleteDeclContext(SS, DC)) return 0;
+ if (RequireCompleteDeclContext(SS, DC)) return nullptr;
LookupQualifiedName(Previous, DC);
@@ -11729,7 +11821,7 @@
D.setInvalidType();
Diag(Loc, diag::err_qualified_friend_not_found)
<< Name << TInfo->getType();
- return 0;
+ return nullptr;
}
// C++ [class.friend]p1: A friend of a class is a function or
@@ -11781,7 +11873,7 @@
Diag(Loc, diag::err_introducing_special_friend) <<
(D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
- return 0;
+ return nullptr;
}
}
@@ -11797,7 +11889,7 @@
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
TemplateParams, AddToScope);
- if (!ND) return 0;
+ if (!ND) return nullptr;
assert(ND->getLexicalDeclContext() == CurContext);
@@ -12089,7 +12181,8 @@
diag::err_covariant_return_inaccessible_base,
diag::err_covariant_return_ambiguous_derived_to_base_conv,
// FIXME: Should this point to the return type?
- New->getLocation(), SourceRange(), New->getDeclName(), 0)) {
+ New->getLocation(), SourceRange(), New->getDeclName(),
+ nullptr)) {
// FIXME: this note won't trigger for delayed access control
// diagnostics, and it's impossible to get an undelayed error
// here from access control during the original parse because
@@ -12159,7 +12252,8 @@
/// class X.
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
- if (D == 0 || D->isInvalidDecl()) return;
+ if (!D || D->isInvalidDecl())
+ return;
// We will always have a nested name specifier here, but this declaration
// might not be out of line if the specifier names the current namespace:
@@ -12179,7 +12273,8 @@
/// initializer for the out-of-line declaration 'D'.
void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
- if (D == 0 || D->isInvalidDecl()) return;
+ if (!D || D->isInvalidDecl())
+ return;
if (isStaticDataMember(D))
PopExpressionEvaluationContext();
@@ -12356,7 +12451,7 @@
// Optionally warn if we're emitting a weak vtable.
if (Class->isExternallyVisible() &&
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
- const FunctionDecl *KeyFunctionDef = 0;
+ const FunctionDecl *KeyFunctionDef = nullptr;
if (!KeyFunction ||
(KeyFunction->hasBody(KeyFunctionDef) &&
KeyFunctionDef->isInlined()))
@@ -12481,7 +12576,7 @@
// Target may not be determinable yet, for instance if this is a dependent
// call in an uninstantiated template.
if (Target) {
- const FunctionDecl *FNTarget = 0;
+ const FunctionDecl *FNTarget = nullptr;
(void)Target->hasBody(FNTarget);
Target = const_cast<CXXConstructorDecl*>(
cast_or_null<CXXConstructorDecl>(FNTarget));
@@ -12489,7 +12584,7 @@
CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
// Avoid dereferencing a null pointer here.
- *TCanonical = Target ? Target->getCanonicalDecl() : 0;
+ *TCanonical = Target? Target->getCanonicalDecl() : nullptr;
if (!Current.insert(Canonical))
return;
@@ -12514,7 +12609,7 @@
CXXConstructorDecl *C = Target;
while (C->getCanonicalDecl() != Canonical) {
- const FunctionDecl *FNTarget = 0;
+ const FunctionDecl *FNTarget = nullptr;
(void)C->getTargetConstructor()->hasBody(FNTarget);
assert(FNTarget && "Ctor cycle through bodiless function");
@@ -12638,7 +12733,7 @@
// Check attributes.
for (const auto *A : Method->attrs()) {
// FIXME: This should be emitted by tblgen.
- Expr *Arg = 0;
+ Expr *Arg = nullptr;
ArrayRef<Expr *> Args;
if (const auto *G = dyn_cast<GuardedByAttr>(A))
Arg = G->getArg();
@@ -12726,7 +12821,7 @@
}
if (!NoexceptExpr->isValueDependent())
- NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, 0,
+ NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, nullptr,
diag::err_noexcept_needs_constant_expression,
/*AllowFold*/ false).take();
EPI.NoexceptExpr = NoexceptExpr;
@@ -12786,7 +12881,7 @@
IdentifierInfo *II = D.getIdentifier();
if (!II) {
Diag(DeclStart, diag::err_anonymous_property);
- return NULL;
+ return nullptr;
}
SourceLocation Loc = D.getIdentifierLoc();
@@ -12811,7 +12906,7 @@
<< DeclSpec::getSpecifierName(TSCS);
// Check to see if this name was declared as a member previously
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
LookupName(Previous, S);
switch (Previous.getResultKind()) {
@@ -12834,11 +12929,11 @@
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
- PrevDecl = 0;
+ PrevDecl = nullptr;
SourceLocation TSSL = D.getLocStart();
const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index d59dd8b..fc9fdb1 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -20,7 +20,6 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Lookup.h"
@@ -71,7 +70,7 @@
} else {
// If this method was declared in a protocol, we can't check
// anything unless we have a receiver type that's an interface.
- const ObjCInterfaceDecl *receiverClass = 0;
+ const ObjCInterfaceDecl *receiverClass = nullptr;
if (isa<ObjCProtocolDecl>(method->getDeclContext())) {
if (receiverTypeIfCall.isNull())
return false;
@@ -304,7 +303,7 @@
/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
/// and user declared, in the method definition's AST.
void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
- assert((getCurMethodDecl() == 0) && "Methodparsing confused");
+ assert((getCurMethodDecl() == nullptr) && "Methodparsing confused");
ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
// If we don't have a valid method decl, simply return.
@@ -376,7 +375,7 @@
dyn_cast<ObjCImplDecl>(MDecl->getDeclContext());
ObjCContainerDecl *ContDeclOfMethodDecl =
dyn_cast<ObjCContainerDecl>(IMD->getDeclContext());
- ObjCImplDecl *ImplDeclOfMethodDecl = 0;
+ ObjCImplDecl *ImplDeclOfMethodDecl = nullptr;
if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl))
ImplDeclOfMethodDecl = OID->getImplementation();
else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl)) {
@@ -398,7 +397,7 @@
if (MDecl->isDesignatedInitializerForTheInterface()) {
getCurFunction()->ObjCIsDesignatedInit = true;
getCurFunction()->ObjCWarnForNoDesignatedInitChain =
- IC->getSuperClass() != 0;
+ IC->getSuperClass() != nullptr;
} else if (IC->hasDesignatedInitializers()) {
getCurFunction()->ObjCIsSecondaryInit = true;
getCurFunction()->ObjCWarnForNoInitDelegation = true;
@@ -438,7 +437,7 @@
// function will reject corrections to that class.
class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
public:
- ObjCInterfaceValidatorCCC() : CurrentIDecl(0) {}
+ ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {}
explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
: CurrentIDecl(IDecl) {}
@@ -524,7 +523,7 @@
ObjCInterfaceValidatorCCC Validator(IDecl);
if (TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
- NULL, Validator)) {
+ nullptr, Validator, CTK_ErrorRecovery)) {
diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
<< SuperName << ClassName);
PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
@@ -543,7 +542,7 @@
if (SuperClassDecl)
(void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
- if (PrevDecl && SuperClassDecl == 0) {
+ if (PrevDecl && !SuperClassDecl) {
// The previous declaration was not a class decl. Check if we have a
// typedef. If we do, get the underlying class type.
if (const TypedefNameDecl *TDecl =
@@ -582,7 +581,7 @@
SuperClassDecl->getDeclName(),
ClassName,
SourceRange(AtInterfaceLoc, ClassLoc))) {
- SuperClassDecl = 0;
+ SuperClassDecl = nullptr;
}
}
IDecl->setSuperClass(SuperClassDecl);
@@ -639,7 +638,7 @@
if (ADecl) {
Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
Diag(ADecl->getLocation(), diag::note_previous_declaration);
- return 0;
+ return nullptr;
}
// Check for class declaration
NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
@@ -656,11 +655,11 @@
}
}
ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);
- if (CDecl == 0) {
+ if (!CDecl) {
Diag(ClassLocation, diag::warn_undef_interface) << ClassName;
if (CDeclU)
Diag(CDeclU->getLocation(), diag::note_previous_declaration);
- return 0;
+ return nullptr;
}
// Everything checked out, instantiate a new alias declaration AST.
@@ -714,8 +713,8 @@
assert(ProtocolName && "Missing protocol identifier");
ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc,
ForRedeclaration);
- ObjCProtocolDecl *PDecl = 0;
- if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : 0) {
+ ObjCProtocolDecl *PDecl = nullptr;
+ if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) {
// If we already have a definition, complain.
Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
Diag(Def->getLocation(), diag::note_previous_definition);
@@ -726,7 +725,7 @@
// FIXME: Can we turn this into an error?
PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
ProtocolLoc, AtProtoInterfaceLoc,
- /*PrevDecl=*/0);
+ /*PrevDecl=*/nullptr);
PDecl->startDefinition();
} else {
if (PrevDecl) {
@@ -794,7 +793,8 @@
DeclFilterCCC<ObjCProtocolDecl> Validator;
TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
- LookupObjCProtocolName, TUScope, NULL, Validator);
+ LookupObjCProtocolName, TUScope, nullptr, Validator,
+ CTK_ErrorRecovery);
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest)
<< ProtocolId[i].first);
@@ -901,7 +901,7 @@
if (!IDecl
|| RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
diag::err_category_forward_interface,
- CategoryName == 0)) {
+ CategoryName == nullptr)) {
// Create an invalid ObjCCategoryDecl to serve as context for
// the enclosing method declarations. We mark the decl invalid
// to make it clear that this isn't a valid AST.
@@ -958,7 +958,7 @@
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *CatName, SourceLocation CatLoc) {
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
- ObjCCategoryDecl *CatIDecl = 0;
+ ObjCCategoryDecl *CatIDecl = nullptr;
if (IDecl && IDecl->hasDefinition()) {
CatIDecl = IDecl->FindCategoryDeclaration(CatName);
if (!CatIDecl) {
@@ -1017,7 +1017,7 @@
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperClassname,
SourceLocation SuperClassLoc) {
- ObjCInterfaceDecl *IDecl = 0;
+ ObjCInterfaceDecl *IDecl = nullptr;
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
= LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
@@ -1034,7 +1034,8 @@
ObjCInterfaceValidatorCCC Validator;
TypoCorrection Corrected =
CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc),
- LookupOrdinaryName, TUScope, NULL, Validator);
+ LookupOrdinaryName, TUScope, nullptr, Validator,
+ CTK_NonError);
if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
// Suggest the (potentially) correct interface name. Don't provide a
// code-modification hint or use the typo name for recovery, because
@@ -1048,7 +1049,7 @@
}
// Check that super class name is valid class name
- ObjCInterfaceDecl* SDecl = 0;
+ ObjCInterfaceDecl *SDecl = nullptr;
if (SuperClassname) {
// Check if a different kind of symbol declared in this scope.
PrevDecl = LookupSingleName(TUScope, SuperClassname, SuperClassLoc,
@@ -1060,7 +1061,7 @@
} else {
SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
if (SDecl && !SDecl->hasDefinition())
- SDecl = 0;
+ SDecl = nullptr;
if (!SDecl)
Diag(SuperClassLoc, diag::err_undef_superclass)
<< SuperClassname << ClassName;
@@ -1081,7 +1082,7 @@
// FIXME: Do we support attributes on the @implementation? If so we should
// copy them over.
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
- ClassName, /*PrevDecl=*/0, ClassLoc,
+ ClassName, /*PrevDecl=*/nullptr, ClassLoc,
true);
IDecl->startDefinition();
if (SDecl) {
@@ -1244,7 +1245,7 @@
ObjCMethodDecl *method,
bool &IncompleteImpl,
unsigned DiagID,
- NamedDecl *NeededFor = 0) {
+ NamedDecl *NeededFor = nullptr) {
// No point warning no definition of method which is 'unavailable'.
switch (method->getAvailability()) {
case AR_Available:
@@ -1688,7 +1689,7 @@
assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");
ObjCInterfaceDecl *Super = IDecl->getSuperClass();
- ObjCInterfaceDecl *NSIDecl = 0;
+ ObjCInterfaceDecl *NSIDecl = nullptr;
// If this protocol is marked 'objc_protocol_requires_explicit_implementation'
// then we should check if any class in the super class hierarchy also
@@ -1712,7 +1713,7 @@
// If no super class conforms to the protocol, we should not search
// for methods in the super class to implicitly satisfy the protocol.
- Super = NULL;
+ Super = nullptr;
}
if (S.getLangOpts().ObjCRuntime.isNeXTFamily()) {
@@ -1751,7 +1752,7 @@
true /* instance */,
false /* shallowCategory */,
true /* followsSuper */,
- NULL /* category */))) {
+ nullptr /* category */))) {
// If a method is not implemented in the category implementation but
// has been declared in its primary class, superclass,
// or in one of their protocols, no need to issue the warning.
@@ -1784,7 +1785,7 @@
false /* class method */,
false /* shallowCategoryLookup */,
true /* followSuper */,
- NULL /* category */))) {
+ nullptr /* category */))) {
// See above comment for instance method lookups.
if (C && IDecl->lookupMethod(method->getSelector(),
false /* class */,
@@ -2220,9 +2221,9 @@
List->setBits(List->getBits()+1);
// If the list is empty, make it a singleton list.
- if (List->Method == 0) {
+ if (List->Method == nullptr) {
List->Method = Method;
- List->setNext(0);
+ List->setNext(nullptr);
return;
}
@@ -2262,7 +2263,7 @@
// We have a new signature for an existing method - add it.
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
- Previous->setNext(new (Mem) ObjCMethodList(Method, 0));
+ Previous->setNext(new (Mem) ObjCMethodList(Method, nullptr));
}
/// \brief Read the contents of the method pool for a given selector from
@@ -2319,7 +2320,7 @@
GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
if (Pos == MethodPool.end())
- return 0;
+ return nullptr;
// Gather the non-hidden methods.
ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
@@ -2337,7 +2338,7 @@
// If there aren't any visible methods, we're done.
// FIXME: Recover if there are any known-but-hidden methods?
if (Methods.empty())
- return 0;
+ return nullptr;
if (Methods.size() == 1)
return Methods[0];
@@ -2399,7 +2400,7 @@
ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
if (Pos == MethodPool.end())
- return 0;
+ return nullptr;
GlobalMethods &Methods = Pos->second;
for (const ObjCMethodList *Method = &Methods.first; Method;
@@ -2411,7 +2412,7 @@
Method = Method->getNext())
if (Method->Method && Method->Method->isDefined())
return Method->Method;
- return 0;
+ return nullptr;
}
static void
@@ -2443,7 +2444,8 @@
return true;
if (S.LookupMethodInObjectType(Sel, ObjectType, true/*Instance method*/))
return true;
- return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) != 0;
+ return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) !=
+ nullptr;
}
const ObjCMethodDecl *
@@ -2455,7 +2457,7 @@
if (ObjectType.isNull())
ObjectIsId = ObjectIsClass = false;
else if (!ObjectType->isObjCObjectPointerType())
- return 0;
+ return nullptr;
else if (const ObjCObjectPointerType *ObjCPtr =
ObjectType->getAsObjCInterfacePointerType()) {
ObjectType = QualType(ObjCPtr->getInterfaceType(), 0);
@@ -2466,8 +2468,8 @@
else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType())
ObjectIsId = false;
else
- return 0;
-
+ return nullptr;
+
for (GlobalMethodPool::iterator b = MethodPool.begin(),
e = MethodPool.end(); b != e; b++) {
// instance methods
@@ -2499,7 +2501,7 @@
HelperSelectorsForTypoCorrection(SelectedMethods,
Sel.getAsString(), Methods[i]);
}
- return (SelectedMethods.size() == 1) ? SelectedMethods[0] : NULL;
+ return (SelectedMethods.size() == 1) ? SelectedMethods[0] : nullptr;
}
/// DiagnoseDuplicateIvars -
@@ -2548,7 +2550,7 @@
Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
ArrayRef<DeclGroupPtrTy> allTUVars) {
if (getObjCContainerKind() == Sema::OCK_None)
- return 0;
+ return nullptr;
assert(AtEnd.isValid() && "Invalid location for '@end'");
@@ -2675,12 +2677,12 @@
DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
- if (IDecl->getSuperClass() == NULL) {
+ if (IDecl->getSuperClass() == nullptr) {
// This class has no superclass, so check that it has been marked with
// __attribute((objc_root_class)).
if (!HasRootClassAttr) {
SourceLocation DeclLoc(IDecl->getLocation());
- SourceLocation SuperClassLoc(PP.getLocForEndOfToken(DeclLoc));
+ SourceLocation SuperClassLoc(getLocForEndOfToken(DeclLoc));
Diag(DeclLoc, diag::warn_objc_root_class_missing)
<< IDecl->getIdentifier();
// See if NSObject is in the current scope, and if it is, suggest
@@ -3058,19 +3060,19 @@
// Make sure we can establish a context for the method.
if (!CurContext->isObjCContainer()) {
Diag(MethodLoc, diag::error_missing_method_context);
- return 0;
+ return nullptr;
}
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
Decl *ClassDecl = cast<Decl>(OCD);
QualType resultDeclType;
bool HasRelatedResultType = false;
- TypeSourceInfo *ReturnTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = nullptr;
if (ReturnType) {
resultDeclType = GetTypeFromParser(ReturnType, &ReturnTInfo);
if (CheckFunctionReturnType(resultDeclType, MethodLoc))
- return 0;
+ return nullptr;
HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType());
} else { // get the type for "id".
@@ -3096,7 +3098,7 @@
if (!ArgInfo[i].Type) {
ArgType = Context.getObjCIdType();
- DI = 0;
+ DI = nullptr;
} else {
ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
}
@@ -3163,7 +3165,7 @@
ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
// Add the method now.
- const ObjCMethodDecl *PrevMethod = 0;
+ const ObjCMethodDecl *PrevMethod = nullptr;
if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(ClassDecl)) {
if (MethodType == tok::minus) {
PrevMethod = ImpDecl->getInstanceMethod(Sel);
@@ -3173,7 +3175,7 @@
ImpDecl->addClassMethod(ObjCMethod);
}
- ObjCMethodDecl *IMD = 0;
+ ObjCMethodDecl *IMD = nullptr;
if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface())
IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),
ObjCMethod->isInstanceMethod());
@@ -3459,15 +3461,15 @@
Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
const ObjCPropertyDecl *&PDecl) const {
if (Method->isClassMethod())
- return 0;
+ return nullptr;
const ObjCInterfaceDecl *IDecl = Method->getClassInterface();
if (!IDecl)
- return 0;
+ return nullptr;
Method = IDecl->lookupMethod(Method->getSelector(), /*isInstance=*/true,
/*shallowCategoryLookup=*/false,
/*followSuper=*/false);
if (!Method || !Method->isPropertyAccessor())
- return 0;
+ return nullptr;
if ((PDecl = Method->findPropertyDecl()))
if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl()) {
// property backing ivar must belong to property's class
@@ -3477,7 +3479,7 @@
IV->getIdentifier());
return IV;
}
- return 0;
+ return nullptr;
}
namespace {
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 59fd85e..24d8222 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -19,7 +19,6 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -284,7 +283,7 @@
case EST_ComputedNoexcept:
OS << "noexcept(";
- OldProto->getNoexceptExpr()->printPretty(OS, 0, getPrintingPolicy());
+ OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy());
OS << ")";
break;
@@ -297,7 +296,7 @@
if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
- FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd());
+ FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd());
}
if (FixItLoc.isInvalid())
@@ -456,7 +455,7 @@
// throw(std::bad_alloc) as equivalent for operator new and operator new[].
// This is because the implicit declaration changed, but old code would break.
if (getLangOpts().CPlusPlus11 && IsOperatorNew) {
- const FunctionProtoType *WithExceptions = 0;
+ const FunctionProtoType *WithExceptions = nullptr;
if (OldEST == EST_None && NewEST == EST_Dynamic)
WithExceptions = New;
else if (OldEST == EST_Dynamic && NewEST == EST_None)
@@ -469,15 +468,8 @@
IdentifierInfo* Name = ExRecord->getIdentifier();
if (Name && Name->getName() == "bad_alloc") {
// It's called bad_alloc, but is it in std?
- DeclContext* DC = ExRecord->getDeclContext();
- DC = DC->getEnclosingNamespaceContext();
- if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) {
- IdentifierInfo* NSName = NS->getIdentifier();
- DC = DC->getParent();
- if (NSName && NSName->getName() == "std" &&
- DC->getEnclosingNamespaceContext()->isTranslationUnit()) {
- return false;
- }
+ if (ExRecord->isInStdNamespace()) {
+ return false;
}
}
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7894682..a9f1197 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -94,11 +94,11 @@
Result = TheEnumDecl->getAvailability(&Message);
}
- const ObjCPropertyDecl *ObjCPDecl = 0;
+ const ObjCPropertyDecl *ObjCPDecl = nullptr;
if (Result == AR_Deprecated || Result == AR_Unavailable) {
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
- AvailabilityResult PDeclResult = PD->getAvailability(0);
+ AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
if (PDeclResult == Result)
ObjCPDecl = PD;
}
@@ -342,7 +342,7 @@
calleeType = CT_Function;
} else if (isa<VarDecl>(D)) {
QualType type = cast<ValueDecl>(D)->getType();
- const FunctionType *fn = 0;
+ const FunctionType *fn = nullptr;
if (const PointerType *ptr = type->getAs<PointerType>()) {
fn = ptr->getPointeeType()->getAs<FunctionType>();
if (!fn) return;
@@ -497,7 +497,7 @@
BaseType = BaseType->getPointeeType();
if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>())
if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) {
- ObjCInterfaceDecl *ClassDeclared = 0;
+ ObjCInterfaceDecl *ClassDeclared = nullptr;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
if (!ClassDeclared->getSuperClass()
&& (*ClassDeclared->ivar_begin()) == IV) {
@@ -590,8 +590,8 @@
}
else if (const ObjCIvarRefExpr *OIRE =
dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
- DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/0);
-
+ DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/nullptr);
+
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
// cv-unqualified version of T. Otherwise, the type of the
@@ -613,7 +613,7 @@
ExprNeedsCleanups = true;
ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
- E, 0, VK_RValue));
+ E, nullptr, VK_RValue));
// C11 6.3.2.1p2:
// ... if the lvalue has atomic type, the value has the non-atomic version
@@ -621,7 +621,7 @@
if (const AtomicType *Atomic = T->getAs<AtomicType>()) {
T = Atomic->getValueType().getUnqualifiedType();
Res = Owned(ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic,
- Res.get(), 0, VK_RValue));
+ Res.get(), nullptr, VK_RValue));
}
return Res;
@@ -806,7 +806,7 @@
switch (VAK) {
case VAK_ValidInCXX11:
DiagRuntimeBehavior(
- E->getLocStart(), 0,
+ E->getLocStart(), nullptr,
PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
<< Ty << CT);
// Fall through.
@@ -814,7 +814,7 @@
if (Ty->isRecordType()) {
// This is unlikely to be what the user intended. If the class has a
// 'c_str' member function, the user probably meant to call that.
- DiagRuntimeBehavior(E->getLocStart(), 0,
+ DiagRuntimeBehavior(E->getLocStart(), nullptr,
PDiag(diag::warn_pass_class_arg_to_vararg)
<< Ty << CT << hasCStrMethod(E) << ".c_str()");
}
@@ -822,7 +822,7 @@
case VAK_Undefined:
DiagRuntimeBehavior(
- E->getLocStart(), 0,
+ E->getLocStart(), nullptr,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< getLangOpts().CPlusPlus11 << Ty << CT);
break;
@@ -830,7 +830,7 @@
case VAK_Invalid:
if (Ty->isObjCObjectType())
DiagRuntimeBehavior(
- E->getLocStart(), 0,
+ E->getLocStart(), nullptr,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
<< Ty << CT);
else
@@ -1302,7 +1302,7 @@
if (ArgTypes[i])
(void) GetTypeFromParser(ArgTypes[i], &Types[i]);
else
- Types[i] = 0;
+ Types[i] = nullptr;
}
ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
@@ -1715,7 +1715,7 @@
TemplateArgs = &Buffer;
} else {
NameInfo = GetNameFromUnqualifiedId(Id);
- TemplateArgs = 0;
+ TemplateArgs = nullptr;
}
}
@@ -1742,7 +1742,7 @@
// original lookup would not have found something because it was a
// dependent name.
DeclContext *DC = (SS.isEmpty() && !CallsUndergoingInstantiation.empty())
- ? CurContext : 0;
+ ? CurContext : nullptr;
while (DC) {
if (isa<CXXRecordDecl>(DC)) {
LookupQualifiedName(R, DC);
@@ -1800,9 +1800,9 @@
CXXDependentScopeMemberExpr::Create(
Context, DepThis, DepThisType, true, SourceLocation(),
SS.getWithLocInContext(Context),
- ULE->getTemplateKeywordLoc(), 0,
+ ULE->getTemplateKeywordLoc(), nullptr,
R.getLookupNameInfo(),
- ULE->hasExplicitTemplateArgs() ? &TList : 0);
+ ULE->hasExplicitTemplateArgs() ? &TList : nullptr);
CallsUndergoingInstantiation.back()->setCallee(DepExpr);
} else {
Diag(R.getNameLoc(), diagnostic) << Name;
@@ -1843,7 +1843,7 @@
// We didn't find anything, so try to correct for a typo.
TypoCorrection Corrected;
if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
- S, &SS, CCC))) {
+ S, &SS, CCC, CTK_ErrorRecovery))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
@@ -1854,7 +1854,8 @@
NamedDecl *ND = Corrected.getCorrectionDecl();
if (ND) {
if (Corrected.isOverloaded()) {
- OverloadCandidateSet OCS(R.getNameLoc());
+ OverloadCandidateSet OCS(R.getNameLoc(),
+ OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
for (TypoCorrection::decl_iterator CD = Corrected.begin(),
CDEnd = Corrected.end();
@@ -2058,9 +2059,9 @@
QualType ThisType = MD->getThisType(Context);
// Since the 'this' expression is synthesized, we don't need to
// perform the double-lookup check.
- NamedDecl *FirstQualifierInScope = 0;
+ NamedDecl *FirstQualifierInScope = nullptr;
return Owned(CXXDependentScopeMemberExpr::Create(
- Context, /*This=*/0, ThisType, /*IsArrow=*/true,
+ Context, /*This=*/nullptr, ThisType, /*IsArrow=*/true,
/*Op=*/SourceLocation(), SS.getWithLocInContext(Context),
TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs));
}
@@ -2167,7 +2168,7 @@
DeclContext *DC = computeDeclContext(SS, false);
if (!DC)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
- NameInfo, /*TemplateArgs=*/0);
+ NameInfo, /*TemplateArgs=*/nullptr);
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
@@ -2180,7 +2181,7 @@
if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
- NameInfo, /*TemplateArgs=*/0);
+ NameInfo, /*TemplateArgs=*/nullptr);
if (R.empty()) {
Diag(NameInfo.getLoc(), diag::err_no_member)
@@ -2195,7 +2196,7 @@
if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand)
return BuildPossibleImplicitMemberExpr(SS,
/*TemplateKWLoc=*/SourceLocation(),
- R, /*TemplateArgs=*/0);
+ R, /*TemplateArgs=*/nullptr);
return BuildDeclarationNameExpr(SS, R, /* ADL */ false);
}
@@ -2237,11 +2238,11 @@
else
LookForIvars = (Lookup.isSingleResult() &&
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
- ObjCInterfaceDecl *IFace = 0;
+ ObjCInterfaceDecl *IFace = nullptr;
if (LookForIvars) {
IFace = CurMethod->getClassInterface();
ObjCInterfaceDecl *ClassDeclared;
- ObjCIvarDecl *IV = 0;
+ ObjCIvarDecl *IV = nullptr;
if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {
// Diagnose using an ivar in a class method.
if (IsClassMethod)
@@ -2337,7 +2338,7 @@
}
}
// Sentinel value saying that we didn't do anything special.
- return Owned((Expr*) 0);
+ return Owned((Expr*) nullptr);
}
/// \brief Cast a base object to a member's actual type.
@@ -2830,7 +2831,7 @@
ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
PredefinedExpr::IdentType IT) {
// Pick the current block, lambda, captured statement or function.
- Decl *currentDecl = 0;
+ Decl *currentDecl = nullptr;
if (const BlockScopeInfo *BSI = getCurBlock())
currentDecl = BSI->TheDecl;
else if (const LambdaScopeInfo *LSI = getCurLambda())
@@ -2872,6 +2873,7 @@
case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
+ case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS]
case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
}
@@ -3128,7 +3130,7 @@
// FIXME: Actually, they don't. We seem to have accidentally invented the
// i128 suffix.
if (Literal.isMicrosoftInteger && MaxWidth < 128 &&
- PP.getTargetInfo().hasInt128Type())
+ Context.getTargetInfo().hasInt128Type())
MaxWidth = 128;
llvm::APInt ResultVal(MaxWidth, 0);
@@ -3199,7 +3201,7 @@
// If it doesn't fit in unsigned long long, and we're using Microsoft
// extensions, then its a 128-bit integer literal.
if (Ty.isNull() && Literal.isMicrosoftInteger &&
- PP.getTargetInfo().hasInt128Type()) {
+ Context.getTargetInfo().hasInt128Type()) {
if (Literal.isUnsigned)
Ty = Context.UnsignedInt128Ty;
else
@@ -3230,7 +3232,7 @@
}
ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E) {
- assert((E != 0) && "ActOnParenExpr() missing expr");
+ assert(E && "ActOnParenExpr() missing expr");
return Owned(new (Context) ParenExpr(L, R, E));
}
@@ -3450,7 +3452,7 @@
return true;
}
- ValueDecl *D = 0;
+ ValueDecl *D = nullptr;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
D = DRE->getDecl();
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
@@ -3585,7 +3587,7 @@
UnaryExprOrTypeTrait ExprKind, bool IsType,
void *TyOrEx, const SourceRange &ArgRange) {
// If error parsing type, ignore.
- if (TyOrEx == 0) return ExprError();
+ if (!TyOrEx) return ExprError();
if (IsType) {
TypeSourceInfo *TInfo;
@@ -3766,7 +3768,8 @@
// Use custom logic if this should be the pseudo-object subscript
// expression.
if (!LangOpts.isSubscriptPointerArithmetic())
- return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
+ return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, nullptr,
+ nullptr);
ResultType = PTy->getPointeeType();
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
@@ -3884,7 +3887,7 @@
// Instantiate the expression.
MultiLevelTemplateArgumentList MutiLevelArgList
- = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
+ = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true);
InstantiatingTemplate Inst(*this, CallLoc, Param,
MutiLevelArgList.getInnermost());
@@ -3974,8 +3977,8 @@
class FunctionCallCCC : public FunctionCallFilterCCC {
public:
FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName,
- unsigned NumArgs, bool HasExplicitTemplateArgs)
- : FunctionCallFilterCCC(SemaRef, NumArgs, HasExplicitTemplateArgs),
+ unsigned NumArgs, MemberExpr *ME)
+ : FunctionCallFilterCCC(SemaRef, NumArgs, false, ME),
FunctionName(FuncName) {}
bool ValidateCandidate(const TypoCorrection &candidate) override {
@@ -3992,17 +3995,21 @@
};
}
-static TypoCorrection TryTypoCorrectionForCall(Sema &S,
- DeclarationNameInfo FuncName,
+static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
+ FunctionDecl *FDecl,
ArrayRef<Expr *> Args) {
- FunctionCallCCC CCC(S, FuncName.getName().getAsIdentifierInfo(),
- Args.size(), false);
- if (TypoCorrection Corrected =
- S.CorrectTypo(FuncName, Sema::LookupOrdinaryName,
- S.getScopeForContext(S.CurContext), NULL, CCC)) {
+ MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
+ DeclarationName FuncName = FDecl->getDeclName();
+ SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getLocStart();
+ FunctionCallCCC CCC(S, FuncName.getAsIdentifierInfo(), Args.size(), ME);
+
+ if (TypoCorrection Corrected = S.CorrectTypo(
+ DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName,
+ S.getScopeForContext(S.CurContext), nullptr, CCC,
+ Sema::CTK_ErrorRecovery)) {
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
if (Corrected.isOverloaded()) {
- OverloadCandidateSet OCS(FuncName.getLoc());
+ OverloadCandidateSet OCS(NameLoc, OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
for (TypoCorrection::decl_iterator CD = Corrected.begin(),
CDEnd = Corrected.end();
@@ -4011,7 +4018,7 @@
S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
OCS);
}
- switch (OCS.BestViableFunction(S, FuncName.getLoc(), Best)) {
+ switch (OCS.BestViableFunction(S, NameLoc, Best)) {
case OR_Success:
ND = Best->Function;
Corrected.setCorrectionDecl(ND);
@@ -4062,13 +4069,8 @@
// arguments for the remaining parameters), don't make the call.
if (Args.size() < NumParams) {
if (Args.size() < MinArgs) {
- MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
TypoCorrection TC;
- if (FDecl && (TC = TryTypoCorrectionForCall(
- *this, DeclarationNameInfo(FDecl->getDeclName(),
- (ME ? ME->getMemberLoc()
- : Fn->getLocStart())),
- Args))) {
+ if (FDecl && (TC = TryTypoCorrectionForCall(*this, Fn, FDecl, Args))) {
unsigned diag_id =
MinArgs == NumParams && !Proto->isVariadic()
? diag::err_typecheck_call_too_few_args_suggest
@@ -4103,13 +4105,8 @@
// them.
if (Args.size() > NumParams) {
if (!Proto->isVariadic()) {
- MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
TypoCorrection TC;
- if (FDecl && (TC = TryTypoCorrectionForCall(
- *this, DeclarationNameInfo(FDecl->getDeclName(),
- (ME ? ME->getMemberLoc()
- : Fn->getLocStart())),
- Args))) {
+ if (FDecl && (TC = TryTypoCorrectionForCall(*this, Fn, FDecl, Args))) {
unsigned diag_id =
MinArgs == NumParams && !Proto->isVariadic()
? diag::err_typecheck_call_too_many_args_suggest
@@ -4168,18 +4165,14 @@
VariadicCallType CallType, bool AllowExplicit,
bool IsListInitialization) {
unsigned NumParams = Proto->getNumParams();
- unsigned NumArgsToCheck = Args.size();
bool Invalid = false;
- if (Args.size() != NumParams)
- // Use default arguments for missing arguments
- NumArgsToCheck = NumParams;
unsigned ArgIx = 0;
// Continue to check argument types (even if we have too few/many args).
- for (unsigned i = FirstParam; i != NumArgsToCheck; i++) {
+ for (unsigned i = FirstParam; i < NumParams; i++) {
QualType ProtoArgType = Proto->getParamType(i);
Expr *Arg;
- ParmVarDecl *Param;
+ ParmVarDecl *Param = FDecl ? FDecl->getParamDecl(i) : nullptr;
if (ArgIx < Args.size()) {
Arg = Args[ArgIx++];
@@ -4188,11 +4181,6 @@
diag::err_call_incomplete_argument, Arg))
return true;
- // Pass the argument
- Param = 0;
- if (FDecl && i < FDecl->getNumParams())
- Param = FDecl->getParamDecl(i);
-
// Strip the unbridged-cast placeholder expression off, if applicable.
bool CFAudited = false;
if (Arg->getType() == Context.ARCUnbridgedCastTy &&
@@ -4213,7 +4201,7 @@
// Remember that parameter belongs to a CF audited API.
if (CFAudited)
Entity.setParameterCFAudited();
-
+
ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(Arg),
@@ -4224,8 +4212,7 @@
Arg = ArgE.takeAs<Expr>();
} else {
- assert(FDecl && "can't use default arguments without a known callee");
- Param = FDecl->getParamDecl(i);
+ assert(Param && "can't use default arguments without a known callee");
ExprResult ArgExpr =
BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
@@ -4494,7 +4481,7 @@
Expr *NakedFn = Fn->IgnoreParens();
- NamedDecl *NDecl = 0;
+ NamedDecl *NDecl = nullptr;
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
if (UnOp->getOpcode() == UO_AddrOf)
NakedFn = UnOp->getSubExpr()->IgnoreParens();
@@ -4536,7 +4523,7 @@
ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
MarkFunctionReferenced(LLLLoc, ConfigDecl);
- return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, 0,
+ return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
/*IsExecConfig=*/true);
}
@@ -4626,7 +4613,7 @@
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
// have type pointer to function".
FuncT = PT->getPointeeType()->getAs<FunctionType>();
- if (FuncT == 0)
+ if (!FuncT)
return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
} else if (const BlockPointerType *BPT =
@@ -4685,7 +4672,7 @@
if (FDecl) {
// Check if we have too few/too many template arguments, based
// on our knowledge of the function definition.
- const FunctionDecl *Def = 0;
+ const FunctionDecl *Def = nullptr;
if (FDecl->hasBody(Def) && Args.size() != Def->param_size()) {
Proto = Def->getType()->getAs<FunctionProtoType>();
if (!Proto || !(Proto->isVariadic() && Args.size() >= Def->param_size()))
@@ -4807,7 +4794,7 @@
return ExprError();
LiteralExpr = Result.get();
- bool isFileScope = getCurFunctionOrMethodDecl() == 0;
+ bool isFileScope = getCurFunctionOrMethodDecl() == nullptr;
if (isFileScope &&
!LiteralExpr->isTypeDependent() &&
!LiteralExpr->isValueDependent() &&
@@ -4860,7 +4847,7 @@
E = ImplicitCastExpr::Create(S.Context, E.get()->getType(),
CK_ARCExtendBlockObject, E.get(),
- /*base path*/ 0, VK_RValue);
+ /*base path*/ nullptr, VK_RValue);
S.ExprNeedsCleanups = true;
}
@@ -5155,7 +5142,7 @@
Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
Declarator &D, ParsedType &Ty,
SourceLocation RParenLoc, Expr *CastExpr) {
- assert(!D.isInvalidType() && (CastExpr != 0) &&
+ assert(!D.isInvalidType() && (CastExpr != nullptr) &&
"ActOnCastExpr(): missing type or expr");
TypeSourceInfo *castTInfo = GetTypeForDeclaratorCast(D, CastExpr->getType());
@@ -5210,6 +5197,8 @@
if (getLangOpts().CPlusPlus && !castType->isVoidType() &&
!getSourceManager().isInSystemMacro(LParenLoc))
Diag(LParenLoc, diag::warn_old_style_cast) << CastExpr->getSourceRange();
+
+ CheckTollFreeBridgeCast(castType, CastExpr);
return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr);
}
@@ -5974,9 +5963,9 @@
Expr *RHSExpr) {
// If this is the gnu "x ?: y" extension, analyze the types as though the LHS
// was the condition.
- OpaqueValueExpr *opaqueValue = 0;
- Expr *commonExpr = 0;
- if (LHSExpr == 0) {
+ OpaqueValueExpr *opaqueValue = nullptr;
+ Expr *commonExpr = nullptr;
+ if (!LHSExpr) {
commonExpr = CondExpr;
// Lower out placeholder types first. This is important so that we don't
// try to capture a placeholder. This happens in few cases in C++; such
@@ -6552,7 +6541,7 @@
// The field to initialize within the transparent union.
RecordDecl *UD = UT->getDecl();
- FieldDecl *InitField = 0;
+ FieldDecl *InitField = nullptr;
// It's compatible if the expression matches any of the fields.
for (auto *it : UD->fields()) {
if (it->getType()->isPointerType()) {
@@ -6788,8 +6777,9 @@
return LHSType;
}
if (!LHSVecType && isa<ExtVectorType>(RHSVecType)) {
- if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? 0 : &LHS), LHSType,
- RHSVecType->getElementType(), RHSType))
+ if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS),
+ LHSType, RHSVecType->getElementType(),
+ RHSType))
return RHSType;
}
@@ -7269,7 +7259,7 @@
return QualType();
// Check array bounds for pointer arithemtic
- CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/0,
+ CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/nullptr,
/*AllowOnePastEnd*/true, /*IndexNegated*/true);
if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
@@ -7519,7 +7509,7 @@
(LHSType->isMemberPointerType() && RHSType->isMemberPointerType()));
bool NonStandardCompositeType = false;
- bool *BoolPtr = S.isSFINAEContext() ? 0 : &NonStandardCompositeType;
+ bool *BoolPtr = S.isSFINAEContext() ? nullptr : &NonStandardCompositeType;
QualType T = S.FindCompositePointerType(Loc, LHS, RHS, BoolPtr);
if (T.isNull()) {
diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true);
@@ -7756,7 +7746,7 @@
if (Mem->isImplicitAccess())
return Mem->getMemberDecl();
}
- return 0;
+ return nullptr;
}
// C99 6.5.8, C++ [expr.rel]
@@ -7799,7 +7789,7 @@
ValueDecl *DL = getCompareDecl(LHSStripped);
ValueDecl *DR = getCompareDecl(RHSStripped);
if (DL && DR && DL == DR && !IsWithinTemplateSpecialization(DL)) {
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always)
<< 0 // self-
<< (Opc == BO_EQ
|| Opc == BO_LE
@@ -7821,7 +7811,7 @@
always_evals_to = 2; // e.g. array1 <= array2
break;
}
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always)
<< 1 // array
<< always_evals_to);
}
@@ -7833,8 +7823,8 @@
// Warn about comparisons against a string constant (unless the other
// operand is null), the user probably wants strcmp.
- Expr *literalString = 0;
- Expr *literalStringStripped = 0;
+ Expr *literalString = nullptr;
+ Expr *literalStringStripped = nullptr;
if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
!RHSStripped->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
@@ -7849,7 +7839,7 @@
}
if (literalString) {
- DiagRuntimeBehavior(Loc, 0,
+ DiagRuntimeBehavior(Loc, nullptr,
PDiag(diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(literalStringStripped)
<< literalString->getSourceRange());
@@ -8194,7 +8184,7 @@
if (DeclRefExpr* DRR
= dyn_cast<DeclRefExpr>(RHS.get()->IgnoreParenImpCasts()))
if (DRL->getDecl() == DRR->getDecl())
- DiagRuntimeBehavior(Loc, 0,
+ DiagRuntimeBehavior(Loc, nullptr,
PDiag(diag::warn_comparison_always)
<< 0 // self-
<< 2 // "a constant"
@@ -8272,7 +8262,8 @@
// Parens on the RHS are ignored.
llvm::APSInt Result;
if (RHS.get()->EvaluateAsInt(Result, Context))
- if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType()) ||
+ if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType() &&
+ !RHS.get()->getExprLoc().isMacroID()) ||
(Result != 0 && Result != 1)) {
Diag(Loc, diag::warn_logical_instead_of_bitwise)
<< RHS.get()->getSourceRange()
@@ -8350,7 +8341,7 @@
ObjCMessageExpr *Base =
dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts());
if (!Base) return false;
- return Base->getMethodDecl() != 0;
+ return Base->getMethodDecl() != nullptr;
}
/// Is the given expression (which must be 'const') a reference to a
@@ -8373,7 +8364,7 @@
assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
// Decide whether the first capture was for a block or a lambda.
- DeclContext *DC = S.CurContext, *Prev = 0;
+ DeclContext *DC = S.CurContext, *Prev = nullptr;
while (DC != var->getDeclContext()) {
Prev = DC;
DC = DC->getParent();
@@ -8753,7 +8744,7 @@
// the base's value, so the object the base refers to is
// irrelevant.
if (cast<MemberExpr>(E)->isArrow())
- return 0;
+ return nullptr;
// Otherwise, the expression refers to a part of the base
return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
case Stmt::ArraySubscriptExprClass: {
@@ -8764,7 +8755,7 @@
if (ICE->getSubExpr()->getType()->isArrayType())
return getPrimaryDecl(ICE->getSubExpr());
}
- return 0;
+ return nullptr;
}
case Stmt::UnaryOperatorClass: {
UnaryOperator *UO = cast<UnaryOperator>(E);
@@ -8775,7 +8766,7 @@
case UO_Extension:
return getPrimaryDecl(UO->getSubExpr());
default:
- return 0;
+ return nullptr;
}
}
case Stmt::ParenExprClass:
@@ -8785,7 +8776,7 @@
// the sub-expression; otherwise, the result here doesn't matter.
return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr());
default:
- return 0;
+ return nullptr;
}
}
@@ -8886,7 +8877,7 @@
return QualType();
// Materialize the temporary as an lvalue so that we can take its address.
OrigOp = op = new (Context)
- MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true, 0);
+ MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true);
} else if (isa<ObjCSelectorExpr>(op)) {
return Context.getPointerType(op->getType());
} else if (lval == Expr::LV_MemberFunction) {
@@ -9027,10 +9018,6 @@
Op->getSourceRange());
}
- // Note that per both C89 and C99, indirection is always legal, even if OpTy
- // is an incomplete type or void. It would be possible to warn about
- // dereferencing a void pointer, but it's completely well-defined, and such a
- // warning is unlikely to catch any mistakes.
if (const PointerType *PT = OpTy->getAs<PointerType>())
Result = PT->getPointeeType();
else if (const ObjCObjectPointerType *OPT =
@@ -9049,6 +9036,19 @@
return QualType();
}
+ // Note that per both C89 and C99, indirection is always legal, even if Result
+ // is an incomplete type or void. It would be possible to warn about
+ // dereferencing a void pointer, but it's completely well-defined, and such a
+ // warning is unlikely to catch any mistakes. In C++, indirection is not valid
+ // for pointers to 'void' but is fine for any other pointer type:
+ //
+ // C++ [expr.unary.op]p1:
+ // [...] the expression to which [the unary * operator] is applied shall
+ // be a pointer to an object type, or a pointer to a function type
+ if (S.getLangOpts().CPlusPlus && Result->isVoidType())
+ S.Diag(OpLoc, diag::ext_typecheck_indirection_through_void_pointer)
+ << OpTy << Op->getSourceRange();
+
// Dereferences are usually l-values...
VK = VK_LValue;
@@ -9161,7 +9161,7 @@
if (!S.getLangOpts().ObjC1)
return;
- const Expr *ObjCPointerExpr = 0, *OtherExpr = 0;
+ const Expr *ObjCPointerExpr = nullptr, *OtherExpr = nullptr;
const Expr *LHS = L.get();
const Expr *RHS = R.get();
@@ -9585,8 +9585,8 @@
tok::TokenKind Kind,
Expr *LHSExpr, Expr *RHSExpr) {
BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind);
- assert((LHSExpr != 0) && "ActOnBinOp(): missing left expression");
- assert((RHSExpr != 0) && "ActOnBinOp(): missing right expression");
+ assert(LHSExpr && "ActOnBinOp(): missing left expression");
+ assert(RHSExpr && "ActOnBinOp(): missing right expression");
// Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr);
@@ -9965,11 +9965,11 @@
static Expr *maybeRebuildARCConsumingStmt(Stmt *Statement) {
// Should always be wrapped with one of these.
ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(Statement);
- if (!cleanups) return 0;
+ if (!cleanups) return nullptr;
ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(cleanups->getSubExpr());
if (!cast || cast->getCastKind() != CK_ARCConsumeObject)
- return 0;
+ return nullptr;
// Splice out the cast. This shouldn't modify any interesting
// features of the statement.
@@ -10004,7 +10004,7 @@
PopExpressionEvaluationContext();
bool isFileScope
- = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0);
+ = (getCurFunctionOrMethodDecl() == nullptr) && (getCurBlock() == nullptr);
if (isFileScope)
return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope));
@@ -10018,7 +10018,7 @@
bool StmtExprMayBindToTemp = false;
if (!Compound->body_empty()) {
Stmt *LastStmt = Compound->body_back();
- LabelStmt *LastLabelStmt = 0;
+ LabelStmt *LastLabelStmt = nullptr;
// If LastStmt is a label, skip down through into the body.
while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) {
LastLabelStmt = Label;
@@ -10054,7 +10054,7 @@
if (LastExpr.isInvalid())
return ExprError();
- if (LastExpr.get() != 0) {
+ if (LastExpr.get() != nullptr) {
if (!LastLabelStmt)
Compound->setLastStmt(LastExpr.take());
else
@@ -10176,7 +10176,7 @@
: diag::warn_offsetof_non_pod_type;
if (!IsSafe && !DidWarnAboutNonPOD &&
- DiagRuntimeBehavior(BuiltinLoc, 0,
+ DiagRuntimeBehavior(BuiltinLoc, nullptr,
PDiag(DiagID)
<< SourceRange(CompPtr[0].LocStart, OC.LocEnd)
<< CurrentType))
@@ -10187,7 +10187,7 @@
LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
LookupQualifiedName(R, RD);
FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
- IndirectFieldDecl *IndirectMemberDecl = 0;
+ IndirectFieldDecl *IndirectMemberDecl = nullptr;
if (!MemberDecl) {
if ((IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>()))
MemberDecl = IndirectMemberDecl->getAnonField();
@@ -10342,7 +10342,8 @@
void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
Scope *CurScope) {
- assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
+ assert(ParamInfo.getIdentifier() == nullptr &&
+ "block-id should have no identifier!");
assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
BlockScopeInfo *CurBlock = getCurBlock();
@@ -10413,7 +10414,7 @@
if (ExplicitSignature) {
for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
ParmVarDecl *Param = ExplicitSignature.getParam(I);
- if (Param->getIdentifier() == 0 &&
+ if (Param->getIdentifier() == nullptr &&
!Param->isImplicit() &&
!Param->isInvalidDecl() &&
!getLangOpts().CPlusPlus)
@@ -10550,7 +10551,6 @@
// If needed, diagnose invalid gotos and switches in the block.
if (getCurFunction()->NeedsScopeChecking() &&
- !hasAnyUnrecoverableErrorsInThisFunction() &&
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
@@ -10561,7 +10561,7 @@
// to deduce an implicit return type.
if (getLangOpts().CPlusPlus && RetTy->isRecordType() &&
!BSI->TheDecl->isDependentContext())
- computeNRVO(Body, getCurBlock());
+ computeNRVO(Body, BSI);
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
@@ -11084,7 +11084,7 @@
// FIXME: This does the right thing, but maybe we need a more general
// fix to TreeTransform?
StmtResult TransformLabelStmt(LabelStmt *S) {
- S->getDecl()->setStmt(0);
+ S->getDecl()->setStmt(nullptr);
return BaseTransform::TransformLabelStmt(S);
}
@@ -11512,7 +11512,7 @@
if (Diagnose)
diagnoseUncapturableValueReference(S, Loc, Var, DC);
}
- return 0;
+ return nullptr;
}
// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
@@ -11589,7 +11589,7 @@
QualType &DeclRefType,
const bool Nested,
Sema &S) {
- Expr *CopyExpr = 0;
+ Expr *CopyExpr = nullptr;
bool ByRef = false;
// Blocks are not allowed to capture arrays.
@@ -11686,18 +11686,17 @@
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
CaptureType = S.Context.getLValueReferenceType(DeclRefType);
- Expr *CopyExpr = 0;
+ Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
// The current implementation assumes that all variables are captured
- // by references. Since there is no capture by copy, no expression evaluation
- // will be needed.
- //
+ // by references. Since there is no capture by copy, no expression
+ // evaluation will be needed.
RecordDecl *RD = RSI->TheRecordDecl;
FieldDecl *Field
- = FieldDecl::Create(S.Context, RD, Loc, Loc, 0, CaptureType,
+ = FieldDecl::Create(S.Context, RD, Loc, Loc, nullptr, CaptureType,
S.Context.getTrivialTypeSourceInfo(CaptureType, Loc),
- 0, false, ICIS_NoInit);
+ nullptr, false, ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
RD->addDecl(Field);
@@ -11729,9 +11728,9 @@
// Build the non-static data member.
FieldDecl *Field
- = FieldDecl::Create(S.Context, Lambda, Loc, Loc, 0, FieldType,
+ = FieldDecl::Create(S.Context, Lambda, Loc, Loc, nullptr, FieldType,
S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
- 0, false, ICIS_NoInit);
+ nullptr, false, ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
Lambda->addDecl(Field);
@@ -11769,7 +11768,7 @@
while (const ConstantArrayType *Array
= S.Context.getAsConstantArrayType(BaseType)) {
// Create the iteration variable for this array index.
- IdentifierInfo *IterationVarName = 0;
+ IdentifierInfo *IterationVarName = nullptr;
{
SmallString<8> Str;
llvm::raw_svector_ostream OS(Str);
@@ -11917,7 +11916,7 @@
}
// Capture this variable in the lambda.
- Expr *CopyExpr = 0;
+ Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
ExprResult Result = addAsFieldToClosureType(S, LSI, Var,
CaptureType, DeclRefType, Loc,
@@ -12097,7 +12096,7 @@
QualType DeclRefType;
return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,
/*BuildAndDiagnose=*/true, CaptureType,
- DeclRefType, 0);
+ DeclRefType, nullptr);
}
QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
@@ -12107,7 +12106,7 @@
// Determine whether we can capture this variable.
if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
/*BuildAndDiagnose=*/false, CaptureType,
- DeclRefType, 0))
+ DeclRefType, nullptr))
return QualType();
return DeclRefType;
@@ -12124,7 +12123,7 @@
if (Var->getType()->isDependentType())
return false;
- const VarDecl *DefVD = 0;
+ const VarDecl *DefVD = nullptr;
Var->getAnyInitializer(DefVD);
if (!DefVD)
return false;
@@ -12150,7 +12149,7 @@
// variable.
if (LambdaScopeInfo *LSI = getCurLambda()) {
Expr *SansParensExpr = E->IgnoreParens();
- VarDecl *Var = 0;
+ VarDecl *Var = nullptr;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))
Var = dyn_cast<VarDecl>(DRE->getFoundDecl());
else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr))
@@ -12189,7 +12188,8 @@
llvm_unreachable("Unexpcted expression");
}
- MarkVarDeclODRUsed(Var, Loc, *this, /*MaxFunctionScopeIndex Pointer*/ 0);
+ MarkVarDeclODRUsed(Var, Loc, *this,
+ /*MaxFunctionScopeIndex Pointer*/ nullptr);
}
MaybeODRUseExprs.clear();
@@ -12300,14 +12300,15 @@
if (!Var->getType()->isReferenceType())
SemaRef.MaybeODRUseExprs.insert(E);
} else
- MarkVarDeclODRUsed(Var, Loc, SemaRef, /*MaxFunctionScopeIndex ptr*/0);
+ MarkVarDeclODRUsed(Var, Loc, SemaRef,
+ /*MaxFunctionScopeIndex ptr*/ nullptr);
}
/// \brief Mark a variable referenced, and check whether it is odr-used
/// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be
/// used directly for normal expressions referring to VarDecl.
void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
- DoMarkVarDeclReferenced(*this, Loc, Var, 0);
+ DoMarkVarDeclReferenced(*this, Loc, Var, nullptr);
}
static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
@@ -12369,9 +12370,9 @@
}
/// \brief Perform marking for a reference to an arbitrary declaration. It
-/// marks the declaration referenced, and performs odr-use checking for functions
-/// and variables. This method should not be used when building an normal
-/// expression which refers to a variable.
+/// marks the declaration referenced, and performs odr-use checking for
+/// functions and variables. This method should not be used when building a
+/// normal expression which refers to a variable.
void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse) {
if (OdrUse) {
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
@@ -12405,7 +12406,7 @@
}
bool MarkReferencedDecls::TraverseTemplateArgument(
- const TemplateArgument &Arg) {
+ const TemplateArgument &Arg) {
if (Arg.getKind() == TemplateArgument::Declaration) {
if (Decl *D = Arg.getAsDecl())
S.MarkAnyDeclReferenced(Loc, D, true);
@@ -12452,7 +12453,7 @@
S.MarkDeclRefReferenced(E);
}
-
+
void VisitMemberExpr(MemberExpr *E) {
S.MarkMemberReferenced(E);
Inherited::VisitMemberExpr(E);
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 8b9c0e2..e84f2f3 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -106,7 +106,7 @@
// For this reason, we're currently only doing the C++03 version of this
// code; the C++0x version has to wait until we get a proper spec.
QualType SearchType;
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
bool isDependent = false;
bool LookInScope = false;
@@ -121,34 +121,29 @@
bool AlreadySearched = false;
bool LookAtPrefix = true;
- // C++ [basic.lookup.qual]p6:
+ // C++11 [basic.lookup.qual]p6:
// If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier,
// the type-names are looked up as types in the scope designated by the
- // nested-name-specifier. In a qualified-id of the form:
+ // nested-name-specifier. Similarly, in a qualified-id of the form:
//
- // ::[opt] nested-name-specifier ~ class-name
+ // nested-name-specifier[opt] class-name :: ~ class-name
//
- // where the nested-name-specifier designates a namespace scope, and in
- // a qualified-id of the form:
+ // the second class-name is looked up in the same scope as the first.
//
- // ::opt nested-name-specifier class-name :: ~ class-name
- //
- // the class-names are looked up as types in the scope designated by
- // the nested-name-specifier.
- //
- // Here, we check the first case (completely) and determine whether the
- // code below is permitted to look at the prefix of the
- // nested-name-specifier.
+ // Here, we determine whether the code below is permitted to look at the
+ // prefix of the nested-name-specifier.
DeclContext *DC = computeDeclContext(SS, EnteringContext);
if (DC && DC->isFileContext()) {
AlreadySearched = true;
LookupCtx = DC;
isDependent = false;
- } else if (DC && isa<CXXRecordDecl>(DC))
+ } else if (DC && isa<CXXRecordDecl>(DC)) {
LookAtPrefix = false;
+ LookInScope = true;
+ }
// The second case from the C++03 rules quoted further above.
- NestedNameSpecifier *Prefix = 0;
+ NestedNameSpecifier *Prefix = nullptr;
if (AlreadySearched) {
// Nothing left to do.
} else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
@@ -163,8 +158,6 @@
LookupCtx = computeDeclContext(SS, EnteringContext);
isDependent = LookupCtx && LookupCtx->isDependentContext();
}
-
- LookInScope = false;
} else if (ObjectTypePtr) {
// C++ [basic.lookup.classref]p3:
// If the unqualified-id is ~type-name, the type-name is looked up
@@ -184,7 +177,7 @@
LookInScope = true;
}
- TypeDecl *NonMatchingTypeDecl = 0;
+ TypeDecl *NonMatchingTypeDecl = nullptr;
LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
for (unsigned Step = 0; Step != 2; ++Step) {
// Look for the name first in the computed lookup context (if we
@@ -477,7 +470,7 @@
if (isType) {
// The operand is a type; handle it as such.
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
&TInfo);
if (T.isNull())
@@ -553,7 +546,7 @@
if (isType) {
// The operand is a type; handle it as such.
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
&TInfo);
if (T.isNull())
@@ -692,13 +685,13 @@
// operation from the operand to the exception object (15.1) can be
// omitted by constructing the automatic object directly into the
// exception object
- const VarDecl *NRVOVariable = 0;
+ const VarDecl *NRVOVariable = nullptr;
if (IsThrownVarInScope)
NRVOVariable = getCopyElisionCandidate(QualType(), E, false);
-
+
InitializedEntity Entity =
InitializedEntity::InitializeException(ThrowLoc, E->getType(),
- /*NRVO=*/NRVOVariable != 0);
+ /*NRVO=*/NRVOVariable != nullptr);
Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
QualType(), E,
IsThrownVarInScope);
@@ -755,8 +748,8 @@
{
if (!Enabled || !ContextDecl)
return;
-
- CXXRecordDecl *Record = 0;
+
+ CXXRecordDecl *Record = nullptr;
if (ClassTemplateDecl *Template = dyn_cast<ClassTemplateDecl>(ContextDecl))
Record = Template->getTemplatedDecl();
else
@@ -779,9 +772,9 @@
static Expr *captureThis(ASTContext &Context, RecordDecl *RD,
QualType ThisTy, SourceLocation Loc) {
FieldDecl *Field
- = FieldDecl::Create(Context, RD, Loc, Loc, 0, ThisTy,
+ = FieldDecl::Create(Context, RD, Loc, Loc, nullptr, ThisTy,
Context.getTrivialTypeSourceInfo(ThisTy, Loc),
- 0, false, ICIS_NoInit);
+ nullptr, false, ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
RD->addDecl(Field);
@@ -836,7 +829,7 @@
for (unsigned idx = MaxFunctionScopesIndex; NumClosures;
--idx, --NumClosures) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
- Expr *ThisExpr = 0;
+ Expr *ThisExpr = nullptr;
QualType ThisTy = getCurrentThisType();
if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI))
// For lambda expressions, build a field and an initializing expression.
@@ -965,7 +958,7 @@
QualType ResultType = Result.get()->getType();
Result = Owned(CXXFunctionalCastExpr::Create(
Context, ResultType, Expr::getValueKindForType(TInfo->getType()), TInfo,
- CK_NoOp, Result.take(), /*Path=*/ 0, LParenLoc, RParenLoc));
+ CK_NoOp, Result.take(), /*Path=*/ nullptr, LParenLoc, RParenLoc));
}
// FIXME: Improve AST representation?
@@ -1051,7 +1044,7 @@
Declarator &D, Expr *Initializer) {
bool TypeContainsAuto = D.getDeclSpec().containsPlaceholderType();
- Expr *ArraySize = 0;
+ Expr *ArraySize = nullptr;
// If the specified type is an array, unwrap it and save the expression.
if (D.getNumTypeObjects() > 0 &&
D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
@@ -1092,7 +1085,7 @@
.take();
} else {
Array.NumElts
- = VerifyIntegerConstantExpression(NumElts, 0,
+ = VerifyIntegerConstantExpression(NumElts, nullptr,
diag::err_new_array_nonconst)
.take();
}
@@ -1103,7 +1096,7 @@
}
}
- TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/nullptr);
QualType AllocType = TInfo->getType();
if (D.isInvalidType())
return ExprError();
@@ -1230,7 +1223,8 @@
if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
return ExprError();
- if (initStyle == CXXNewExpr::ListInit && isStdInitializerList(AllocType, 0)) {
+ if (initStyle == CXXNewExpr::ListInit &&
+ isStdInitializerList(AllocType, nullptr)) {
Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
diag::warn_dangling_std_initializer_list)
<< /*at end of FE*/0 << Inits[0]->getSourceRange();
@@ -1394,8 +1388,8 @@
// be signed, larger than size_t, whatever.
}
- FunctionDecl *OperatorNew = 0;
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorNew = nullptr;
+ FunctionDecl *OperatorDelete = nullptr;
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
@@ -1414,12 +1408,14 @@
SmallVector<Expr *, 8> AllPlaceArgs;
if (OperatorNew) {
- // Add default arguments, if any.
const FunctionProtoType *Proto =
- OperatorNew->getType()->getAs<FunctionProtoType>();
- VariadicCallType CallType =
- Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+ OperatorNew->getType()->getAs<FunctionProtoType>();
+ VariadicCallType CallType = Proto->isVariadic() ? VariadicFunction
+ : VariadicDoesNotApply;
+ // We've already converted the placement args, just fill in any default
+ // arguments. Skip the first parameter because we don't have a corresponding
+ // argument.
if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto, 1,
PlacementArgs, AllPlaceArgs, CallType))
return ExprError();
@@ -1427,6 +1423,7 @@
if (!AllPlaceArgs.empty())
PlacementArgs = AllPlaceArgs;
+ // FIXME: This is wrong: PlacementArgs misses out the first (size) argument.
DiagnoseSentinelCalls(OperatorNew, PlacementLParen, PlacementArgs);
// FIXME: Missing call to CheckFunctionCall or equivalent
@@ -1680,15 +1677,10 @@
// We don't need an operator delete if we're running under
// -fno-exceptions.
if (!getLangOpts().Exceptions) {
- OperatorDelete = 0;
+ OperatorDelete = nullptr;
return false;
}
- // FindAllocationOverload can change the passed in arguments, so we need to
- // copy them back.
- if (!PlaceArgs.empty())
- std::copy(AllocArgs.begin() + 1, AllocArgs.end(), PlaceArgs.data());
-
// C++ [expr.new]p19:
//
// If the new-expression begins with a unary :: operator, the
@@ -1756,13 +1748,14 @@
for (LookupResult::iterator D = FoundDelete.begin(),
DEnd = FoundDelete.end();
D != DEnd; ++D) {
- FunctionDecl *Fn = 0;
+ FunctionDecl *Fn = nullptr;
if (FunctionTemplateDecl *FnTmpl
= dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
// Perform template argument deduction to try to match the
// expected function type.
TemplateDeductionInfo Info(StartLoc);
- if (DeduceTemplateArguments(FnTmpl, 0, ExpectedFunctionType, Fn, Info))
+ if (DeduceTemplateArguments(FnTmpl, nullptr, ExpectedFunctionType, Fn,
+ Info))
continue;
} else
Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
@@ -1832,8 +1825,22 @@
return false;
}
-/// FindAllocationOverload - Find an fitting overload for the allocation
-/// function in the specified scope.
+/// \brief Find an fitting overload for the allocation function
+/// in the specified scope.
+///
+/// \param StartLoc The location of the 'new' token.
+/// \param Range The range of the placement arguments.
+/// \param Name The name of the function ('operator new' or 'operator new[]').
+/// \param Args The placement arguments specified.
+/// \param Ctx The scope in which we should search; either a class scope or the
+/// translation unit.
+/// \param AllowMissing If \c true, report an error if we can't find any
+/// allocation functions. Otherwise, succeed but don't fill in \p
+/// Operator.
+/// \param Operator Filled in with the found allocation function. Unchanged if
+/// no allocation function was found.
+/// \param Diagnose If \c true, issue errors if the allocation function is not
+/// usable.
bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
DeclarationName Name, MultiExprArg Args,
DeclContext *Ctx,
@@ -1853,7 +1860,7 @@
R.suppressDiagnostics();
- OverloadCandidateSet Candidates(StartLoc);
+ OverloadCandidateSet Candidates(StartLoc, OverloadCandidateSet::CSK_Normal);
for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
Alloc != AllocEnd; ++Alloc) {
// Even member operator new/delete are implicitly treated as
@@ -1862,7 +1869,7 @@
if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
- /*ExplicitTemplateArgs=*/0,
+ /*ExplicitTemplateArgs=*/nullptr,
Args, Candidates,
/*SuppressUserConversions=*/false);
continue;
@@ -1879,33 +1886,11 @@
case OR_Success: {
// Got one!
FunctionDecl *FnDecl = Best->Function;
- MarkFunctionReferenced(StartLoc, FnDecl);
- // The first argument is size_t, and the first parameter must be size_t,
- // too. This is checked on declaration and can be assumed. (It can't be
- // asserted on, though, since invalid decls are left in there.)
- // Watch out for variadic allocator function.
- unsigned NumArgsInFnDecl = FnDecl->getNumParams();
- for (unsigned i = 0; (i < Args.size() && i < NumArgsInFnDecl); ++i) {
- InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
- FnDecl->getParamDecl(i));
-
- if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i])))
- return true;
-
- ExprResult Result
- = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i]));
- if (Result.isInvalid())
- return true;
-
- Args[i] = Result.takeAs<Expr>();
- }
-
- Operator = FnDecl;
-
if (CheckAllocationAccess(StartLoc, Range, R.getNamingClass(),
Best->FoundDecl, Diagnose) == AR_inaccessible)
return true;
+ Operator = FnDecl;
return false;
}
@@ -2005,7 +1990,7 @@
getOrCreateStdNamespace(),
SourceLocation(), SourceLocation(),
&PP.getIdentifierTable().get("bad_alloc"),
- 0);
+ nullptr);
getStdBadAlloc()->setImplicit(true);
}
@@ -2103,7 +2088,7 @@
FunctionDecl *Alloc =
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
SourceLocation(), Name,
- FnType, /*TInfo=*/0, SC_None, false, true);
+ FnType, /*TInfo=*/nullptr, SC_None, false, true);
Alloc->setImplicit();
if (AddMallocAttr)
@@ -2112,17 +2097,15 @@
ParmVarDecl *ParamDecls[2];
for (unsigned I = 0; I != NumParams; ++I) {
ParamDecls[I] = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
- SourceLocation(), 0,
- Params[I], /*TInfo=*/0,
- SC_None, 0);
+ SourceLocation(), nullptr,
+ Params[I], /*TInfo=*/nullptr,
+ SC_None, nullptr);
ParamDecls[I]->setImplicit();
}
Alloc->setParams(ArrayRef<ParmVarDecl*>(ParamDecls, NumParams));
- // FIXME: Also add this declaration to the IdentifierResolver, but
- // make sure it is at the end of the chain to coincide with the
- // global scope.
Context.getTranslationUnitDecl()->addDecl(Alloc);
+ IdResolver.tryAddTopLevelDecl(Alloc, Name);
}
FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
@@ -2240,7 +2223,7 @@
return true;
}
- Operator = 0;
+ Operator = nullptr;
return false;
}
@@ -2259,7 +2242,7 @@
// DR599 amends "pointer type" to "pointer to object type" in both cases.
ExprResult Ex = Owned(ExE);
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
bool ArrayFormAsWritten = ArrayForm;
bool UsualArrayDeleteWantsSize = false;
@@ -2341,7 +2324,7 @@
diag::err_address_space_qualified_delete)
<< Pointee.getUnqualifiedType() << AddressSpace;
- CXXRecordDecl *PointeeRD = 0;
+ CXXRecordDecl *PointeeRD = nullptr;
if (Pointee->isVoidType() && !isSFINAEContext()) {
// The C++ standard bans deleting a pointer to a non-object type, which
// effectively bans deletion of "void*". However, most compilers support
@@ -2597,10 +2580,10 @@
Result = S.Owned(ImplicitCastExpr::Create(S.Context,
Result.get()->getType(),
CK_UserDefinedConversion,
- Result.get(), 0,
+ Result.get(), nullptr,
Result.get()->getValueKind()));
- S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ 0, FoundDecl);
+ S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ nullptr, FoundDecl);
return S.MaybeBindToTemporary(Result.get());
}
@@ -2781,13 +2764,13 @@
case ICK_Array_To_Pointer:
FromType = Context.getArrayDecayedType(FromType);
From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
case ICK_Function_To_Pointer:
FromType = Context.getPointerType(FromType);
From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
default:
@@ -2811,7 +2794,7 @@
return ExprError();
From = ImpCastExprToType(From, ToType, CK_NoOp,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
case ICK_Integral_Promotion:
@@ -2821,17 +2804,17 @@
SCS.Second == ICK_Integral_Promotion &&
"only enums with fixed underlying type can promote to bool");
From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
} else {
From = ImpCastExprToType(From, ToType, CK_IntegralCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
}
break;
case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
From = ImpCastExprToType(From, ToType, CK_FloatingCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
case ICK_Complex_Promotion:
@@ -2850,22 +2833,22 @@
CK = CK_IntegralComplexCast;
}
From = ImpCastExprToType(From, ToType, CK,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
}
case ICK_Floating_Integral:
if (ToType->isRealFloatingType())
From = ImpCastExprToType(From, ToType, CK_IntegralToFloating,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
else
From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
case ICK_Compatible_Conversion:
From = ImpCastExprToType(From, ToType, CK_NoOp,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
case ICK_Writeback_Conversion:
@@ -2940,7 +2923,7 @@
From = ImpCastExprToType(From, Context.BoolTy,
ScalarTypeToBooleanCastKind(FromType),
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
case ICK_Derived_To_Base: {
@@ -2961,12 +2944,12 @@
case ICK_Vector_Conversion:
From = ImpCastExprToType(From, ToType, CK_BitCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
case ICK_Vector_Splat:
From = ImpCastExprToType(From, ToType, CK_VectorSplat,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
case ICK_Complex_Real:
@@ -3003,7 +2986,7 @@
From = ImpCastExprToType(From, ElType,
isFloatingComplex ? CK_FloatingComplexToReal
: CK_IntegralComplexToReal,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
// x -> y
if (Context.hasSameUnqualifiedType(ElType, ToType)) {
@@ -3011,19 +2994,19 @@
} else if (ToType->isRealFloatingType()) {
From = ImpCastExprToType(From, ToType,
isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
} else {
assert(ToType->isIntegerType());
From = ImpCastExprToType(From, ToType,
isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
}
}
break;
case ICK_Block_Pointer_Conversion: {
From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).take();
break;
}
@@ -3065,7 +3048,7 @@
ExprValueKind VK = ToType->isReferenceType() ?
From->getValueKind() : VK_RValue;
From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
- CK_NoOp, VK, /*BasePath=*/0, CCK).take();
+ CK_NoOp, VK, /*BasePath=*/nullptr, CCK).take();
if (SCS.DeprecatedStringLiteralToCharPtr &&
!getLangOpts().WritableStrings) {
@@ -3088,7 +3071,7 @@
assert(Context.hasSameType(
ToAtomicType->castAs<AtomicType>()->getValueType(), From->getType()));
From = ImpCastExprToType(From, ToAtomicType, CK_NonAtomicToAtomic,
- VK_RValue, 0, CCK).take();
+ VK_RValue, nullptr, CCK).take();
}
return Owned(From);
@@ -3656,6 +3639,11 @@
if (Args[0]->getType()->isIncompleteType())
return false;
+ // Make sure the first argument is not an abstract type.
+ CXXRecordDecl *RD = Args[0]->getType()->getAsCXXRecordDecl();
+ if (RD && RD->isAbstract())
+ return false;
+
SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs;
SmallVector<Expr *, 2> ArgExprs;
ArgExprs.reserve(Args.size() - 1);
@@ -3903,7 +3891,8 @@
EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated);
Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
- ExprResult Result = Self.BuildBinOp(/*S=*/0, KeyLoc, BO_Assign, &Lhs, &Rhs);
+ ExprResult Result = Self.BuildBinOp(/*S=*/nullptr, KeyLoc, BO_Assign, &Lhs,
+ &Rhs);
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;
@@ -4298,7 +4287,8 @@
static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc) {
Expr *Args[2] = { LHS.get(), RHS.get() };
- OverloadCandidateSet CandidateSet(QuestionLoc);
+ OverloadCandidateSet CandidateSet(QuestionLoc,
+ OverloadCandidateSet::CSK_Operator);
Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args,
CandidateSet);
@@ -4590,7 +4580,8 @@
// operand. The result is of the common type.
bool NonStandardCompositeType = false;
QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS,
- isSFINAEContext()? 0 : &NonStandardCompositeType);
+ isSFINAEContext() ? nullptr
+ : &NonStandardCompositeType);
if (!Composite.isNull()) {
if (NonStandardCompositeType)
Diag(QuestionLoc,
@@ -4714,7 +4705,7 @@
QualifierUnion.push_back(
Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
- MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0));
+ MemberOfClass.push_back(std::make_pair(nullptr, nullptr));
continue;
}
@@ -4903,7 +4894,7 @@
// actual method. FIXME: we should infer retention by selector in
// cases where we don't have an actual method.
} else {
- ObjCMethodDecl *D = 0;
+ ObjCMethodDecl *D = nullptr;
if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) {
D = Send->getMethodDecl();
} else if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) {
@@ -4933,7 +4924,7 @@
CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject
: CK_ARCReclaimReturnedObject);
- return Owned(ImplicitCastExpr::Create(Context, E->getType(), ck, E, 0,
+ return Owned(ImplicitCastExpr::Create(Context, E->getType(), ck, E, nullptr,
VK_RValue));
}
@@ -4943,7 +4934,7 @@
// Search for the base element type (cf. ASTContext::getBaseElementType) with
// a fast path for the common case that the type is directly a RecordType.
const Type *T = Context.getCanonicalType(E->getType().getTypePtr());
- const RecordType *RT = 0;
+ const RecordType *RT = nullptr;
while (!RT) {
switch (T->getTypeClass()) {
case Type::Record:
@@ -4967,7 +4958,7 @@
return Owned(E);
bool IsDecltype = ExprEvalContexts.back().IsDecltype;
- CXXDestructorDecl *Destructor = IsDecltype ? 0 : LookupDestructor(RD);
+ CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
if (Destructor) {
MarkFunctionReferenced(E->getExprLoc(), Destructor);
@@ -5085,11 +5076,12 @@
}
CXXBindTemporaryExpr *TopBind = dyn_cast<CXXBindTemporaryExpr>(E);
- CallExpr *TopCall = TopBind ? dyn_cast<CallExpr>(TopBind->getSubExpr()) : 0;
+ CallExpr *TopCall = TopBind ? dyn_cast<CallExpr>(TopBind->getSubExpr())
+ : nullptr;
if (TopCall)
E = TopCall;
else
- TopBind = 0;
+ TopBind = nullptr;
// Disable the special decltype handling now.
ExprEvalContexts.back().IsDecltype = false;
@@ -5227,7 +5219,7 @@
// separate note) instead of having the error reported back to here
// and giving a diagnostic with a fixit attached to the error itself.
(FirstIteration && CurFD && CurFD->isFunctionTemplateSpecialization())
- ? 0
+ ? nullptr
: &NoArrowOperatorFound);
if (Result.isInvalid()) {
if (NoArrowOperatorFound) {
@@ -5241,7 +5233,7 @@
Diag(OpLoc, diag::err_typecheck_member_reference_arrow)
<< BaseType << Base->getSourceRange();
CallExpr *CE = dyn_cast<CallExpr>(Base);
- if (Decl *CD = (CE ? CE->getCalleeDecl() : 0)) {
+ if (Decl *CD = (CE ? CE->getCalleeDecl() : nullptr)) {
Diag(CD->getLocStart(),
diag::note_member_reference_arrow_from_operator_arrow);
}
@@ -5313,7 +5305,7 @@
<< isa<CXXPseudoDestructorExpr>(MemExpr)
<< FixItHint::CreateInsertion(ExpectedLParenLoc, "()");
- return ActOnCallExpr(/*Scope*/ 0,
+ return ActOnCallExpr(/*Scope*/ nullptr,
MemExpr,
/*LPLoc*/ ExpectedLParenLoc,
None,
@@ -5372,10 +5364,11 @@
!ObjectType->isVectorType()) {
if (getLangOpts().MSVCCompat && ObjectType->isVoidType())
Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange();
- else
+ else {
Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
<< ObjectType << Base->getSourceRange();
- return ExprError();
+ return ExprError();
+ }
}
// C++ [expr.pseudo]p2:
@@ -5435,7 +5428,7 @@
<< ScopeTypeInfo->getTypeLoc().getLocalSourceRange();
ScopeType = QualType();
- ScopeTypeInfo = 0;
+ ScopeTypeInfo = nullptr;
}
}
@@ -5487,7 +5480,7 @@
// Convert the name of the type being destructed (following the ~) into a
// type (with source-location information).
QualType DestructedType;
- TypeSourceInfo *DestructedTypeInfo = 0;
+ TypeSourceInfo *DestructedTypeInfo = nullptr;
PseudoDestructorTypeStorage Destructed;
if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
ParsedType T = getTypeName(*SecondTypeName.Identifier,
@@ -5542,7 +5535,7 @@
}
// Convert the name of the scope type (the type prior to '::') into a type.
- TypeSourceInfo *ScopeTypeInfo = 0;
+ TypeSourceInfo *ScopeTypeInfo = nullptr;
QualType ScopeType;
if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
FirstTypeName.Identifier) {
@@ -5611,7 +5604,7 @@
PseudoDestructorTypeStorage Destructed(DestructedTypeInfo);
return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(),
- 0, SourceLocation(), TildeLoc,
+ nullptr, SourceLocation(), TildeLoc,
Destructed, HasTrailingLParen);
}
@@ -5644,9 +5637,8 @@
return Exp;
}
}
-
- ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0,
+ ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr,
FoundDecl, Method);
if (Exp.isInvalid())
return true;
@@ -5811,7 +5803,7 @@
static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
ASTContext &Context) {
if (isa<ParmVarDecl>(Var)) return true;
- const VarDecl *DefVD = 0;
+ const VarDecl *DefVD = nullptr;
// If there is no initializer - this can not be a constant expression.
if (!Var->getAnyInitializer(DefVD)) return true;
@@ -5857,8 +5849,8 @@
const unsigned NumPotentialCaptures =
CurrentLSI->getNumPotentialVariableCaptures();
for (unsigned I = 0; I != NumPotentialCaptures; ++I) {
- Expr *VarExpr = 0;
- VarDecl *Var = 0;
+ Expr *VarExpr = nullptr;
+ VarDecl *Var = nullptr;
CurrentLSI->getPotentialVariableCapture(I, Var, VarExpr);
// If the variable is clearly identified as non-odr-used and the full
// expression is not instantiation dependent, only then do we not
@@ -5898,13 +5890,13 @@
if (S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,
/*EllipsisLoc*/ SourceLocation(),
/*BuildAndDiagnose*/false, CaptureType,
- DeclRefType, 0)) {
+ DeclRefType, nullptr)) {
// We will never be able to capture this variable, and we need
// to be able to in any and all instantiations, so diagnose it.
S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,
/*EllipsisLoc*/ SourceLocation(),
/*BuildAndDiagnose*/true, CaptureType,
- DeclRefType, 0);
+ DeclRefType, nullptr);
}
}
}
@@ -5915,7 +5907,7 @@
// 'this' in that lambda (and all its enclosing lambdas).
if (const Optional<unsigned> Index =
getStackIndexOfNearestEnclosingCaptureCapableLambda(
- FunctionScopesArrayRef, /*0 is 'this'*/ 0, S)) {
+ FunctionScopesArrayRef, /*0 is 'this'*/ nullptr, S)) {
const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
/*Explicit*/ false, /*BuildAndDiagnose*/ true,
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index c4a1780..5e9ccff 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -206,7 +206,7 @@
DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);
- CXXRecordDecl *ContextClass = Method ? Method->getParent() : 0;
+ CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;
CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());
bool InStaticMethod = Method && Method->isStatic();
@@ -306,7 +306,7 @@
// This flag determines whether or not CompName has an 's' char prefix,
// indicating that it is a string of hex values to be used as vector indices.
- bool HexSwizzle = *compStr == 's' || *compStr == 'S';
+ bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1];
bool HasRepeated = false;
bool HasIndex[16] = {};
@@ -406,7 +406,7 @@
Context))
return D;
}
- return 0;
+ return nullptr;
}
static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
@@ -414,7 +414,7 @@
const Selector &Sel,
ASTContext &Context) {
// Check protocols on qualified interfaces.
- Decl *GDecl = 0;
+ Decl *GDecl = nullptr;
for (const auto *I : QIdTy->quals()) {
if (Member)
if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(Member)) {
@@ -607,7 +607,7 @@
QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
bool MOUS;
- SemaRef.LookupTemplateName(R, 0, SS, ObjectType, false, MOUS);
+ SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS);
return false;
}
@@ -643,8 +643,9 @@
DeclarationName Name = R.getLookupName();
RecordMemberExprValidatorCCC Validator(RTy);
TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), NULL,
- &SS, Validator, DC);
+ R.getLookupKind(), nullptr,
+ &SS, Validator,
+ Sema::CTK_ErrorRecovery, DC);
R.clear();
if (Corrected.isResolved() && !Corrected.isKeyword()) {
R.setLookupName(Corrected.getCorrection());
@@ -659,7 +660,7 @@
// information to do overload resolution, so we don't know which previous
// declaration to point to.
if (Corrected.isOverloaded())
- Corrected.setCorrectionDecl(0);
+ Corrected.setCorrectionDecl(nullptr);
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() &&
Name.getAsString() == Corrected.getAsString(SemaRef.getLangOpts());
@@ -694,7 +695,7 @@
if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
if (LookupMemberExprInRecord(*this, R, SourceRange(),
RecordTy->getAs<RecordType>(),
- OpLoc, SS, TemplateArgs != 0))
+ OpLoc, SS, TemplateArgs != nullptr))
return ExprError();
// Explicit member accesses.
@@ -702,7 +703,7 @@
ExprResult BaseResult = Owned(Base);
ExprResult Result =
LookupMemberExpr(R, BaseResult, IsArrow, OpLoc,
- SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0);
+ SS, /*ObjCImpDecl*/ nullptr, TemplateArgs != nullptr);
if (BaseResult.isInvalid())
return ExprError();
@@ -858,16 +859,13 @@
}
/// \brief Build a MemberExpr AST node.
-static MemberExpr *BuildMemberExpr(Sema &SemaRef,
- ASTContext &C, Expr *Base, bool isArrow,
- const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- ValueDecl *Member,
- DeclAccessPair FoundDecl,
- const DeclarationNameInfo &MemberNameInfo,
- QualType Ty,
- ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs = 0) {
+static MemberExpr *
+BuildMemberExpr(Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow,
+ const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ ValueDecl *Member, DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo, QualType Ty,
+ ExprValueKind VK, ExprObjectKind OK,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr) {
assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
MemberExpr *E =
MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
@@ -1238,7 +1236,7 @@
// Returning valid-but-null is how we indicate to the caller that
// the lookup result was filled in.
- return Owned((Expr*) 0);
+ return Owned((Expr*) nullptr);
}
// Handle ivar access to Objective-C objects.
@@ -1277,8 +1275,8 @@
if (RequireCompleteType(OpLoc, BaseType, diag::err_typecheck_incomplete_tag,
BaseExpr.get()))
return ExprError();
-
- ObjCInterfaceDecl *ClassDeclared = 0;
+
+ ObjCInterfaceDecl *ClassDeclared = nullptr;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
if (!IV) {
@@ -1286,8 +1284,9 @@
DeclFilterCCC<ObjCIvarDecl> Validator;
Validator.IsObjCIvarLookup = IsArrow;
if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
- LookupMemberName, NULL, NULL,
- Validator, IDecl)) {
+ LookupMemberName, nullptr,
+ nullptr, Validator,
+ CTK_ErrorRecovery, IDecl)) {
IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
diagnoseTypo(Corrected,
PDiag(diag::err_typecheck_member_reference_ivar_suggest)
@@ -1328,7 +1327,7 @@
return ExprError();
if (IV->getAccessControl() != ObjCIvarDecl::Public &&
IV->getAccessControl() != ObjCIvarDecl::Package) {
- ObjCInterfaceDecl *ClassOfMethodDecl = 0;
+ ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;
if (ObjCMethodDecl *MD = getCurMethodDecl())
ClassOfMethodDecl = MD->getClassInterface();
else if (ObjCImpDecl && getCurFunctionDecl()) {
@@ -1446,8 +1445,9 @@
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
PP.getSelectorTable(),
Member);
- ObjCMethodDecl *SMD = 0;
- if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0,
+ ObjCMethodDecl *SMD = nullptr;
+ if (Decl *SDecl = FindGetterSetterNameDecl(OPT,
+ /*Property id*/nullptr,
SetterSel, Context))
SMD = dyn_cast<ObjCMethodDecl>(SDecl);
@@ -1637,7 +1637,7 @@
bool IsArrow = (OpKind == tok::arrow);
NamedDecl *FirstQualifierInScope
- = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S, SS.getScopeRep()));
+ = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep()));
// This is a postfix expression, so get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
@@ -1654,7 +1654,7 @@
LookupResult R(*this, NameInfo, LookupMemberName);
ExprResult BaseResult = Owned(Base);
Result = LookupMemberExpr(R, BaseResult, IsArrow, OpLoc,
- SS, ObjCImpDecl, TemplateArgs != 0);
+ SS, ObjCImpDecl, TemplateArgs != nullptr);
if (BaseResult.isInvalid())
return ExprError();
Base = BaseResult.take();
@@ -1767,8 +1767,8 @@
// 'this' expression now.
QualType ThisTy = getCurrentThisType();
assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
-
- Expr *baseExpr = 0; // null signifies implicit access
+
+ Expr *baseExpr = nullptr; // null signifies implicit access
if (IsKnownInstance) {
SourceLocation Loc = R.getNameLoc();
if (SS.getRange().isValid())
@@ -1776,11 +1776,11 @@
CheckCXXThisCapture(Loc);
baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
}
-
+
return BuildMemberReferenceExpr(baseExpr, ThisTy,
/*OpLoc*/ SourceLocation(),
/*IsArrow*/ true,
SS, TemplateKWLoc,
- /*FirstQualifierInScope*/ 0,
+ /*FirstQualifierInScope*/ nullptr,
R, TemplateArgs);
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 5bffdd1..d9e2828 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -93,7 +93,7 @@
if (!Ty.isNull()) {
Ty = Context.getObjCObjectPointerType(Ty);
} else if (getLangOpts().NoConstantCFStrings) {
- IdentifierInfo *NSIdent=0;
+ IdentifierInfo *NSIdent=nullptr;
std::string StringClass(getLangOpts().ObjCConstantStringClass);
if (StringClass.empty())
@@ -133,7 +133,7 @@
ObjCInterfaceDecl::Create (Context,
Context.getTranslationUnitDecl(),
SourceLocation(), NSIdent,
- 0, SourceLocation());
+ nullptr, SourceLocation());
Ty = Context.getObjCInterfaceType(NSStringIDecl);
Context.setObjCNSStringType(Ty);
}
@@ -182,7 +182,7 @@
S.Diag(Loc, diag::err_invalid_nsnumber_type)
<< NumberType << R;
}
- return 0;
+ return nullptr;
}
// If we already looked up this method, we're done.
@@ -208,15 +208,15 @@
S.NSNumberDecl = ObjCInterfaceDecl::Create(CX,
CX.getTranslationUnitDecl(),
SourceLocation(), NSNumberId,
- 0, SourceLocation());
+ nullptr, SourceLocation());
} else {
// Otherwise, require a declaration of NSNumber.
S.Diag(Loc, diag::err_undeclared_nsnumber);
- return 0;
+ return nullptr;
}
} else if (!S.NSNumberDecl->hasDefinition()) {
S.Diag(Loc, diag::err_undeclared_nsnumber);
- return 0;
+ return nullptr;
}
// generate the pointer to NSNumber type.
@@ -228,7 +228,7 @@
ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);
if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
// create a stub definition this NSNumber factory method.
- TypeSourceInfo *ReturnTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = nullptr;
Method =
ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl,
@@ -240,13 +240,13 @@
ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
SourceLocation(), SourceLocation(),
&CX.Idents.get("value"),
- NumberType, /*TInfo=*/0, SC_None,
- 0);
+ NumberType, /*TInfo=*/nullptr,
+ SC_None, nullptr);
Method->setMethodParams(S.Context, value, None);
}
if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method))
- return 0;
+ return nullptr;
// Note: if the parameter type is out-of-line, we'll catch it later in the
// implicit conversion.
@@ -444,10 +444,10 @@
ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
if (ValueExpr->isTypeDependent()) {
ObjCBoxedExpr *BoxedExpr =
- new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, NULL, SR);
+ new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR);
return Owned(BoxedExpr);
}
- ObjCMethodDecl *BoxingMethod = NULL;
+ ObjCMethodDecl *BoxingMethod = nullptr;
QualType BoxedType;
// Convert the expression to an RValue, so we can check for pointer types...
ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr);
@@ -473,7 +473,7 @@
NSStringDecl = ObjCInterfaceDecl::Create(Context, TU,
SourceLocation(),
NSStringId,
- 0, SourceLocation());
+ nullptr, SourceLocation());
} else {
Diag(SR.getBegin(), diag::err_undeclared_nsstring);
return ExprError();
@@ -495,7 +495,7 @@
BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);
if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
// Debugger needs to work even if NSString hasn't been defined.
- TypeSourceInfo *ReturnTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = nullptr;
ObjCMethodDecl *M = ObjCMethodDecl::Create(
Context, SourceLocation(), SourceLocation(), stringWithUTF8String,
NSStringPointer, ReturnTInfo, NSStringDecl,
@@ -510,8 +510,8 @@
SourceLocation(), SourceLocation(),
&Context.Idents.get("value"),
Context.getPointerType(ConstCharType),
- /*TInfo=*/0,
- SC_None, 0);
+ /*TInfo=*/nullptr,
+ SC_None, nullptr);
M->setMethodParams(Context, value, None);
BoxingMethod = M;
}
@@ -646,7 +646,7 @@
Context.getTranslationUnitDecl(),
SourceLocation(),
NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
- 0, SourceLocation());
+ nullptr, SourceLocation());
if (!NSArrayDecl) {
Diag(SR.getBegin(), diag::err_undeclared_nsarray);
@@ -661,7 +661,7 @@
Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);
ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);
if (!Method && getLangOpts().DebuggerObjCLiteral) {
- TypeSourceInfo *ReturnTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = nullptr;
Method = ObjCMethodDecl::Create(
Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,
Context.getTranslationUnitDecl(), false /*Instance*/,
@@ -675,14 +675,16 @@
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr,
+ SC_None, nullptr);
Params.push_back(objects);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
Params.push_back(cnt);
Method->setMethodParams(Context, Params, None);
}
@@ -759,7 +761,7 @@
Context.getTranslationUnitDecl(),
SourceLocation(),
NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
- 0, SourceLocation());
+ nullptr, SourceLocation());
if (!NSDictionaryDecl) {
Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
@@ -778,7 +780,7 @@
Method = ObjCMethodDecl::Create(Context,
SourceLocation(), SourceLocation(), Sel,
IdT,
- 0 /*TypeSourceInfo */,
+ nullptr /*TypeSourceInfo */,
Context.getTranslationUnitDecl(),
false /*Instance*/, false/*isVariadic*/,
/*isPropertyAccessor=*/false,
@@ -791,21 +793,24 @@
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
Params.push_back(objects);
ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("keys"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
Params.push_back(keys);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
Params.push_back(cnt);
Method->setMethodParams(Context, Params, None);
}
@@ -1049,8 +1054,9 @@
} else
DiagnoseMismatchedSelectors(*this, AtLoc, Method);
- if (!Method ||
- Method->getImplementationControl() != ObjCMethodDecl::Optional) {
+ if (Method &&
+ Method->getImplementationControl() != ObjCMethodDecl::Optional &&
+ !getSourceManager().isInSystemHeader(Method->getLocation())) {
llvm::DenseMap<Selector, SourceLocation>::iterator Pos
= ReferencedSelectors.find(Sel);
if (Pos == ReferencedSelectors.end())
@@ -1114,7 +1120,7 @@
// still have a 'self', and we really do still need to capture it!
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC);
if (!method)
- return 0;
+ return nullptr;
tryCaptureVariable(method->getSelfDecl(), Loc);
@@ -1199,7 +1205,7 @@
return result;
}
- return 0;
+ return nullptr;
}
void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
@@ -1406,7 +1412,7 @@
continue;
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
- 0);
+ nullptr);
IsError |= Arg.isInvalid();
Args[i] = Arg.take();
}
@@ -1468,7 +1474,7 @@
if (ObjCMethodDecl *method = I->lookupMethod(sel, isInstance))
return method;
- return 0;
+ return nullptr;
}
/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
@@ -1477,13 +1483,13 @@
const ObjCObjectPointerType *OPT,
bool Instance)
{
- ObjCMethodDecl *MD = 0;
+ ObjCMethodDecl *MD = nullptr;
for (const auto *PROTO : OPT->quals()) {
if ((MD = PROTO->lookupMethod(Sel, Instance))) {
return MD;
}
}
- return 0;
+ return nullptr;
}
static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) {
@@ -1496,8 +1502,8 @@
Expr *RExpr = Receiver->IgnoreParenImpCasts();
SourceLocation Loc = RExpr->getLocStart();
QualType T = RExpr->getType();
- const ObjCPropertyDecl *PDecl = 0;
- const ObjCMethodDecl *GDecl = 0;
+ const ObjCPropertyDecl *PDecl = nullptr;
+ const ObjCMethodDecl *GDecl = nullptr;
if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) {
RExpr = POE->getSyntacticForm();
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) {
@@ -1668,8 +1674,8 @@
// Attempt to correct for typos in property names.
DeclFilterCCC<ObjCPropertyDecl> Validator;
if (TypoCorrection Corrected = CorrectTypo(
- DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
- NULL, Validator, IFace, false, OPT)) {
+ DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName,
+ nullptr, nullptr, Validator, CTK_ErrorRecovery, IFace, false, OPT)) {
diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest)
<< MemberName << QualType(OPT, 0));
DeclarationName TypoResult = Corrected.getCorrection();
@@ -1716,7 +1722,7 @@
receiverNameLoc);
bool IsSuper = false;
- if (IFace == 0) {
+ if (!IFace) {
// If the "receiver" is 'super' in a method, handle it as an expression-like
// property reference.
if (receiverNamePtr->isStr("super")) {
@@ -1734,9 +1740,9 @@
}
QualType T = Context.getObjCInterfaceType(Super);
T = Context.getObjCObjectPointerType(T);
-
+
return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
- /*BaseExpr*/0,
+ /*BaseExpr*/nullptr,
SourceLocation()/*OpLoc*/,
&propertyName,
propertyNameLoc,
@@ -1748,8 +1754,8 @@
IFace = CurMethod->getClassInterface()->getSuperClass();
}
}
-
- if (IFace == 0) {
+
+ if (!IFace) {
Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier
<< tok::l_paren;
return ExprError();
@@ -1762,10 +1768,7 @@
// If this reference is in an @implementation, check for 'private' methods.
if (!Getter)
- if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
- if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
- if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
- Getter = ImpDecl->getClassMethod(Sel);
+ Getter = IFace->lookupPrivateClassMethod(Sel);
if (Getter) {
// FIXME: refactor/share with ActOnMemberReference().
@@ -1784,10 +1787,7 @@
if (!Setter) {
// If this reference is in an @implementation, also check for 'private'
// methods.
- if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
- if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
- if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
- Setter = ImpDecl->getClassMethod(SetterSel);
+ Setter = IFace->lookupPrivateClassMethod(SetterSel);
}
// Look through local category implementations associated with the class.
if (!Setter)
@@ -1907,7 +1907,8 @@
ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
if (TypoCorrection Corrected =
CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S,
- NULL, Validator, NULL, false, NULL, false)) {
+ nullptr, Validator, CTK_ErrorRecovery, nullptr, false,
+ nullptr, false)) {
if (Corrected.isKeyword()) {
// If we've found the keyword "super" (the only keyword that would be
// returned by CorrectTypo), this is a send to super.
@@ -1970,16 +1971,16 @@
// message to the superclass instance.
QualType SuperTy = Context.getObjCInterfaceType(Super);
SuperTy = Context.getObjCObjectPointerType(SuperTy);
- return BuildInstanceMessage(0, SuperTy, SuperLoc,
- Sel, /*Method=*/0,
+ return BuildInstanceMessage(nullptr, SuperTy, SuperLoc,
+ Sel, /*Method=*/nullptr,
LBracLoc, SelectorLocs, RBracLoc, Args);
}
// Since we are in a class method, this is a class message to
// the superclass.
- return BuildClassMessage(/*ReceiverTypeInfo=*/0,
+ return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,
Context.getObjCInterfaceType(Super),
- SuperLoc, Sel, /*Method=*/0,
+ SuperLoc, Sel, /*Method=*/nullptr,
LBracLoc, SelectorLocs, RBracLoc, Args);
}
@@ -1990,7 +1991,7 @@
Selector Sel,
ObjCMethodDecl *Method,
MultiExprArg Args) {
- TypeSourceInfo *receiverTypeInfo = 0;
+ TypeSourceInfo *receiverTypeInfo = nullptr;
if (!ReceiverType.isNull())
receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType);
@@ -2104,13 +2105,13 @@
assert(SuperLoc.isInvalid() && "Message to super with dependent type");
return Owned(ObjCMessageExpr::Create(Context, ReceiverType,
VK_RValue, LBracLoc, ReceiverTypeInfo,
- Sel, SelectorLocs, /*Method=*/0,
+ Sel, SelectorLocs, /*Method=*/nullptr,
makeArrayRef(Args, NumArgs),RBracLoc,
isImplicit));
}
// Find the class to which we are sending this message.
- ObjCInterfaceDecl *Class = 0;
+ ObjCInterfaceDecl *Class = nullptr;
const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
if (!ClassType || !(Class = ClassType->getInterface())) {
Diag(Loc, diag::err_invalid_receiver_class_message)
@@ -2206,8 +2207,9 @@
ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
- /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
- LBracLoc, SelectorLocs, RBracLoc, Args);
+ /*SuperLoc=*/SourceLocation(), Sel,
+ /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc,
+ Args);
}
ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver,
@@ -2297,7 +2299,7 @@
assert(SuperLoc.isInvalid() && "Message to super with dependent type");
return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy,
VK_RValue, LBracLoc, Receiver, Sel,
- SelectorLocs, /*Method=*/0,
+ SelectorLocs, /*Method=*/nullptr,
makeArrayRef(Args, NumArgs),
RBracLoc, isImplicit));
}
@@ -2421,7 +2423,7 @@
}
}
} else {
- ObjCInterfaceDecl* ClassDecl = 0;
+ ObjCInterfaceDecl *ClassDecl = nullptr;
// We allow sending a message to a qualified ID ("id<foo>"), which is ok as
// long as one of the protocols implements the selector (if not, warn).
@@ -2441,7 +2443,7 @@
// Try to complete the type. Under ARC, this is a hard error from which
// we don't try to recover.
- const ObjCInterfaceDecl *forwardClass = 0;
+ const ObjCInterfaceDecl *forwardClass = nullptr;
if (RequireCompleteType(Loc, OCIType->getPointeeType(),
getLangOpts().ObjCAutoRefCount
? diag::err_arc_receiver_forward_instance
@@ -2454,7 +2456,7 @@
forwardClass = OCIType->getInterfaceDecl();
Diag(Receiver ? Receiver->getLocStart()
: SuperLoc, diag::note_receiver_is_id);
- Method = 0;
+ Method = nullptr;
} else {
Method = ClassDecl->lookupInstanceMethod(Sel);
}
@@ -2501,8 +2503,8 @@
FunctionScopeInfo *DIFunctionScopeInfo =
(Method && Method->getMethodFamily() == OMF_init)
- ? getEnclosingFunction() : 0;
-
+ ? getEnclosingFunction() : nullptr;
+
if (DIFunctionScopeInfo &&
DIFunctionScopeInfo->ObjCIsDesignatedInit &&
(SuperLoc.isValid() || isSelfExpr(Receiver))) {
@@ -2522,7 +2524,7 @@
}
}
if (!isDesignatedInitChain) {
- const ObjCMethodDecl *InitMethod = 0;
+ const ObjCMethodDecl *InitMethod = nullptr;
bool isDesignated =
getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod);
assert(isDesignated && InitMethod);
@@ -2740,10 +2742,11 @@
}
if (Sel == RespondsToSelectorSel)
RemoveSelectorFromWarningCache(*this, Args[0]);
-
+
return BuildInstanceMessage(Receiver, Receiver->getType(),
- /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
- LBracLoc, SelectorLocs, RBracLoc, Args);
+ /*SuperLoc=*/SourceLocation(), Sel,
+ /*Method=*/nullptr, LBracLoc, SelectorLocs,
+ RBracLoc, Args);
}
enum ARCConversionTypeClass {
@@ -3153,7 +3156,7 @@
if (RecordDecl *RD = RT->getDecl())
return RD->getAttr<T>();
}
- return 0;
+ return nullptr;
}
static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T,
@@ -3165,7 +3168,7 @@
return ObjCBAttr;
T = TDNDecl->getUnderlyingType();
}
- return 0;
+ return nullptr;
}
static void
@@ -3182,7 +3185,7 @@
return;
QualType castExprType = castExpr->getType();
- TypedefNameDecl *TDNDecl = 0;
+ TypedefNameDecl *TDNDecl = nullptr;
if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) ||
(exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&
@@ -3228,9 +3231,10 @@
DiagnosticBuilder DiagB =
(CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
-
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
- castType, castExpr, realCast, "__bridge ", 0);
+ castType, castExpr, realCast, "__bridge ",
+ nullptr);
}
if (CreateRule != ACC_plusZero)
{
@@ -3240,15 +3244,15 @@
S.Diag(br ? castExpr->getExprLoc() : noteLoc,
diag::note_arc_bridge_transfer)
<< castExprType << br;
-
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
castType, castExpr, realCast, "__bridge_transfer ",
- br ? "CFBridgingRelease" : 0);
+ br ? "CFBridgingRelease" : nullptr);
}
return;
}
-
+
// Bridge from a CF type to an ARC type.
if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
bool br = S.isKnownName("CFBridgingRetain");
@@ -3269,7 +3273,8 @@
(CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
- castType, castExpr, realCast, "__bridge ", 0);
+ castType, castExpr, realCast, "__bridge ",
+ nullptr);
}
if (CreateRule != ACC_plusZero)
{
@@ -3279,10 +3284,10 @@
S.Diag(br ? castExpr->getExprLoc() : noteLoc,
diag::note_arc_bridge_retained)
<< castType << br;
-
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
castType, castExpr, realCast, "__bridge_retained ",
- br ? "CFBridgingRetain" : 0);
+ br ? "CFBridgingRetain" : nullptr);
}
return;
@@ -3295,13 +3300,13 @@
}
template <typename TB>
-static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
+static void CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
QualType T = castExpr->getType();
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
TypedefNameDecl *TDNDecl = TD->getDecl();
if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
- NamedDecl *Target = 0;
+ NamedDecl *Target = nullptr;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
Sema::LookupOrdinaryName);
@@ -3315,23 +3320,23 @@
= InterfacePointerType->getObjectType()->getInterface();
if ((CastClass == ExprClass) ||
(CastClass && ExprClass->isSuperClassOf(CastClass)))
- return true;
+ return;
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
<< T << Target->getName() << castType->getPointeeType();
- return true;
+ return;
} else if (castType->isObjCIdType() ||
(S.Context.ObjCObjectAdoptsQTypeProtocols(
castType, ExprClass)))
// ok to cast to 'id'.
// casting to id<p-list> is ok if bridge type adopts all of
// p-list protocols.
- return true;
+ return;
else {
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
<< T << Target->getName() << castType;
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
S.Diag(Target->getLocStart(), diag::note_declared_at);
- return true;
+ return;
}
}
}
@@ -3341,21 +3346,20 @@
if (Target)
S.Diag(Target->getLocStart(), diag::note_declared_at);
}
- return true;
+ return;
}
T = TDNDecl->getUnderlyingType();
}
- return false;
}
template <typename TB>
-static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
+static void CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
QualType T = castType;
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
TypedefNameDecl *TDNDecl = TD->getDecl();
if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
- NamedDecl *Target = 0;
+ NamedDecl *Target = nullptr;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
Sema::LookupOrdinaryName);
@@ -3369,24 +3373,24 @@
= InterfacePointerType->getObjectType()->getInterface();
if ((CastClass == ExprClass) ||
(ExprClass && CastClass->isSuperClassOf(ExprClass)))
- return true;
+ return;
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
<< castExpr->getType()->getPointeeType() << T;
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
- return true;
+ return;
} else if (castExpr->getType()->isObjCIdType() ||
(S.Context.QIdProtocolsAdoptObjCObjectProtocols(
castExpr->getType(), CastClass)))
// ok to cast an 'id' expression to a CFtype.
// ok to cast an 'id<plist>' expression to CFtype provided plist
// adopts all of CFtype's ObjetiveC's class plist.
- return true;
+ return;
else {
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
<< castExpr->getType() << castType;
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
S.Diag(Target->getLocStart(), diag::note_declared_at);
- return true;
+ return;
}
}
}
@@ -3396,27 +3400,44 @@
if (Target)
S.Diag(Target->getLocStart(), diag::note_declared_at);
}
- return true;
+ return;
}
T = TDNDecl->getUnderlyingType();
}
- return false;
}
void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
+ if (!getLangOpts().ObjC1)
+ return;
// warn in presence of __bridge casting to or from a toll free bridge cast.
ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType());
ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);
if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) {
- (void)CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr);
- (void)CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr);
+ CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr);
+ CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr);
}
else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) {
- (void)CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr);
- (void)CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr);
+ CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr);
+ CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr);
}
}
+bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
+ CastKind &Kind) {
+ if (!getLangOpts().ObjC1)
+ return false;
+ ARCConversionTypeClass exprACTC =
+ classifyTypeForARCConversion(castExpr->getType());
+ ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);
+ if ((castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) ||
+ (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable)) {
+ CheckTollFreeBridgeCast(castType, castExpr);
+ Kind = (castACTC == ACTC_coreFoundation) ? CK_BitCast
+ : CK_CPointerToObjCPointerCast;
+ return true;
+ }
+ return false;
+}
bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
QualType DestType, QualType SrcType,
@@ -3435,7 +3456,7 @@
IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
if (!RCId)
return false;
- NamedDecl *Target = 0;
+ NamedDecl *Target = nullptr;
// Check for an existing type with this name.
LookupResult R(*this, DeclarationName(RCId), SourceLocation(),
Sema::LookupOrdinaryName);
@@ -3495,9 +3516,9 @@
return false;
ObjCInterfaceDecl *RelatedClass;
- ObjCMethodDecl *ClassMethod = 0;
- ObjCMethodDecl *InstanceMethod = 0;
- TypedefNameDecl *TDNDecl = 0;
+ ObjCMethodDecl *ClassMethod = nullptr;
+ ObjCMethodDecl *InstanceMethod = nullptr;
+ TypedefNameDecl *TDNDecl = nullptr;
if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,
ClassMethod, InstanceMethod, TDNDecl, CfToNs))
return false;
@@ -3627,19 +3648,6 @@
if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
CCK != CCK_ImplicitConversion)
return ACR_okay;
-
- if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation &&
- (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
- if (CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr) ||
- CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr))
- return ACR_okay;
-
- if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
- (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
- if (CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr) ||
- CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr))
- return ACR_okay;
-
switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
// For invalid casts, fall through.
@@ -3655,7 +3663,7 @@
case ACC_plusOne:
castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),
CK_ARCConsumeObject, castExpr,
- 0, VK_RValue);
+ nullptr, VK_RValue);
ExprNeedsCleanups = true;
return ACR_okay;
}
@@ -3857,7 +3865,7 @@
// Produce the object before casting it.
SubExpr = ImplicitCastExpr::Create(Context, FromType,
CK_ARCProduceObject,
- SubExpr, 0, VK_RValue);
+ SubExpr, nullptr, VK_RValue);
break;
case OBC_BridgeTransfer: {
@@ -3896,7 +3904,7 @@
if (MustConsume) {
ExprNeedsCleanups = true;
Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,
- 0, VK_RValue);
+ nullptr, VK_RValue);
}
return Result;
@@ -3909,7 +3917,7 @@
ParsedType Type,
SourceLocation RParenLoc,
Expr *SubExpr) {
- TypeSourceInfo *TSInfo = 0;
+ TypeSourceInfo *TSInfo = nullptr;
QualType T = GetTypeFromParser(Type, &TSInfo);
if (Kind == OBC_Bridge)
CheckTollFreeBridgeCast(T, SubExpr);
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 3829016..a169602 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -17,7 +17,6 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaInternal.h"
@@ -70,7 +69,7 @@
// Otherwise we can only handle string literals.
StringLiteral *SL = dyn_cast<StringLiteral>(Init);
- if (SL == 0)
+ if (!SL)
return SIF_Other;
const QualType ElemTy =
@@ -499,7 +498,7 @@
ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
ElementEntity.setElementIndex(Init);
- Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : 0);
+ Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr);
if (!InitExpr && !ILE->hasArrayFiller()) {
InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
true);
@@ -557,7 +556,7 @@
hadError = false;
FullyStructuredList =
- getStructuredSubobjectInit(IL, 0, T, 0, 0, IL->getSourceRange());
+ getStructuredSubobjectInit(IL, 0, T, nullptr, 0, IL->getSourceRange());
CheckExplicitInitList(Entity, IL, T, FullyStructuredList,
/*TopLevelObject=*/true);
@@ -654,13 +653,13 @@
if (T->isArrayType() || T->isRecordType()) {
SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
diag::warn_missing_braces)
- << StructuredSubobjectInitList->getSourceRange()
- << FixItHint::CreateInsertion(
- StructuredSubobjectInitList->getLocStart(), "{")
- << FixItHint::CreateInsertion(
- SemaRef.PP.getLocForEndOfToken(
- StructuredSubobjectInitList->getLocEnd()),
- "}");
+ << StructuredSubobjectInitList->getSourceRange()
+ << FixItHint::CreateInsertion(
+ StructuredSubobjectInitList->getLocStart(), "{")
+ << FixItHint::CreateInsertion(
+ SemaRef.getLocForEndOfToken(
+ StructuredSubobjectInitList->getLocEnd()),
+ "}");
}
}
}
@@ -1031,7 +1030,7 @@
SemaRef.Owned(expr),
/*TopLevelOfInitList=*/true);
- Expr *ResultExpr = 0;
+ Expr *ResultExpr = nullptr;
if (Result.isInvalid())
hadError = true; // types weren't compatible.
@@ -1142,7 +1141,7 @@
SemaRef.Owned(Init),
/*TopLevelOfInitList=*/true);
- Expr *ResultExpr = 0;
+ Expr *ResultExpr = nullptr;
if (Result.isInvalid())
hadError = true; // types weren't compatible.
else {
@@ -1288,7 +1287,7 @@
// Handle this designated initializer. elementIndex will be
// updated to be the next array element we'll initialize.
if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
- DeclType, 0, &elementIndex, Index,
+ DeclType, nullptr, &elementIndex, Index,
StructuredList, StructuredIndex, true,
false)) {
hadError = true;
@@ -1463,7 +1462,7 @@
// Handle this designated initializer. Field will be updated to
// the next field that we'll be initializing.
if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
- DeclType, &Field, 0, Index,
+ DeclType, &Field, nullptr, Index,
StructuredList, StructuredIndex,
true, TopLevelObject))
hadError = true;
@@ -1587,12 +1586,12 @@
for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
PE = IndirectField->chain_end(); PI != PE; ++PI) {
if (PI + 1 == PE)
- Replacements.push_back(Designator((IdentifierInfo *)0,
+ Replacements.push_back(Designator((IdentifierInfo *)nullptr,
DIE->getDesignator(DesigIdx)->getDotLoc(),
DIE->getDesignator(DesigIdx)->getFieldLoc()));
else
- Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
- SourceLocation()));
+ Replacements.push_back(Designator((IdentifierInfo *)nullptr,
+ SourceLocation(), SourceLocation()));
assert(isa<FieldDecl>(*PI));
Replacements.back().setField(cast<FieldDecl>(*PI));
}
@@ -1609,7 +1608,7 @@
static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
IdentifierInfo *FieldName) {
if (!FieldName)
- return 0;
+ return nullptr;
assert(AnonField->isAnonymousStructOrUnion());
Decl *NextDecl = AnonField->getNextDeclInContext();
@@ -1619,7 +1618,7 @@
return IF;
NextDecl = NextDecl->getNextDeclInContext();
}
- return 0;
+ return nullptr;
}
static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef,
@@ -1808,15 +1807,15 @@
// may find nothing, or may find a member of an anonymous
// struct/union.
DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
- FieldDecl *ReplacementField = 0;
+ FieldDecl *ReplacementField = nullptr;
if (Lookup.empty()) {
// Name lookup didn't find anything. Determine whether this
// was a typo for another field name.
FieldInitializerValidatorCCC Validator(RT->getDecl());
if (TypoCorrection Corrected = SemaRef.CorrectTypo(
DeclarationNameInfo(FieldName, D->getFieldLoc()),
- Sema::LookupMemberName, /*Scope=*/ 0, /*SS=*/ 0, Validator,
- RT->getDecl())) {
+ Sema::LookupMemberName, /*Scope=*/ nullptr, /*SS=*/ nullptr,
+ Validator, Sema::CTK_ErrorRecovery, RT->getDecl())) {
SemaRef.diagnoseTypo(
Corrected,
SemaRef.PDiag(diag::err_field_designator_unknown_suggest)
@@ -1881,7 +1880,7 @@
// remove existing initializer
StructuredList->resizeInits(SemaRef.Context, 0);
- StructuredList->setInitializedFieldInUnion(0);
+ StructuredList->setInitializedFieldInUnion(nullptr);
}
StructuredList->setInitializedFieldInUnion(*Field);
@@ -1979,7 +1978,7 @@
InitializedEntity MemberEntity =
InitializedEntity::InitializeMember(*Field, &Entity);
if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
- FieldType, 0, 0, Index,
+ FieldType, nullptr, nullptr, Index,
StructuredList, newStructuredIndex,
true, false))
return true;
@@ -2038,7 +2037,7 @@
return true;
}
- Expr *IndexExpr = 0;
+ Expr *IndexExpr = nullptr;
llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
if (D->isArrayDesignator()) {
IndexExpr = DIE->getArrayIndex(*D);
@@ -2123,7 +2122,7 @@
Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
if (CharTy != PromotedCharTy)
Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
- Init, 0, VK_RValue);
+ Init, nullptr, VK_RValue);
StructuredList->updateInit(Context, i, Init);
}
} else {
@@ -2145,7 +2144,7 @@
Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
if (CharTy != PromotedCharTy)
Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
- Init, 0, VK_RValue);
+ Init, nullptr, VK_RValue);
StructuredList->updateInit(Context, i, Init);
}
}
@@ -2175,7 +2174,7 @@
ElementEntity.setElementIndex(ElementIndex);
if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
- ElementType, 0, 0, Index,
+ ElementType, nullptr, nullptr, Index,
StructuredList, ElementIndex,
(DesignatedStartIndex == DesignatedEndIndex),
false))
@@ -2215,8 +2214,8 @@
unsigned StructuredIndex,
SourceRange InitRange) {
if (VerifyOnly)
- return 0; // No structured list in verification-only mode.
- Expr *ExistingInit = 0;
+ return nullptr; // No structured list in verification-only mode.
+ Expr *ExistingInit = nullptr;
if (!StructuredList)
ExistingInit = SyntacticToSemantic.lookup(IList);
else if (StructuredIndex < StructuredList->getNumInits())
@@ -2478,7 +2477,7 @@
bool IsInheritedVirtualBase) {
InitializedEntity Result;
Result.Kind = EK_Base;
- Result.Parent = 0;
+ Result.Parent = nullptr;
Result.Base = reinterpret_cast<uintptr_t>(Base);
if (IsInheritedVirtualBase)
Result.Base |= 0x01;
@@ -2543,7 +2542,7 @@
case EK_LambdaCapture:
case EK_CompoundLiteralInit:
case EK_RelatedResult:
- return 0;
+ return nullptr;
}
llvm_unreachable("Invalid EntityKind!");
@@ -3020,7 +3019,7 @@
bool SuppressUserConversions = false;
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
@@ -3051,7 +3050,7 @@
(!OnlyListConstructors || S.isInitListConstructor(Constructor))) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0, Args,
+ /*ExplicitArgs*/ nullptr, Args,
CandidateSet, SuppressUserConversions);
else {
// C++ [over.match.copy]p1:
@@ -3237,7 +3236,7 @@
const InitializedEntity &Entity,
const InitializationKind &Kind,
InitializationSequence &Sequence,
- InitListExpr *InitList = 0);
+ InitListExpr *InitList = nullptr);
/// \brief Attempt list initialization of a reference.
static void TryReferenceListInitialization(Sema &S,
@@ -3436,7 +3435,7 @@
bool AllowExplicit = Kind.AllowExplicit();
bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding();
- const RecordType *T1RecordType = 0;
+ const RecordType *T1RecordType = nullptr;
if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
!S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
// The type we're converting to is a class type. Enumerate its constructors
@@ -3454,7 +3453,7 @@
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
@@ -3466,7 +3465,7 @@
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
else
@@ -3479,7 +3478,7 @@
if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
return OR_No_Viable_Function;
- const RecordType *T2RecordType = 0;
+ const RecordType *T2RecordType = nullptr;
if ((T2RecordType = T2->getAs<RecordType>()) &&
!S.RequireCompleteType(Kind.getLocation(), T2, 0)) {
// The type we're converting from is a class type, enumerate its conversion
@@ -4082,7 +4081,7 @@
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
@@ -4095,7 +4094,7 @@
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
else
@@ -4411,7 +4410,7 @@
const InitializationKind &Kind,
MultiExprArg Args,
bool TopLevelOfInitList)
- : FailedCandidateSet(Kind.getLocation()) {
+ : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) {
InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList);
}
@@ -4455,7 +4454,7 @@
setSequenceKind(NormalSequence);
QualType SourceType;
- Expr *Initializer = 0;
+ Expr *Initializer = nullptr;
if (Args.size() == 1) {
Initializer = Args[0];
if (S.getLangOpts().ObjC1) {
@@ -4817,7 +4816,7 @@
for (SmallVectorImpl<NamedDecl *>::iterator
CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
NamedDecl *D = *CI;
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
if ((Constructor = dyn_cast<CXXConstructorDecl>(D))) {
// Handle copy/moveconstructors, only.
@@ -4847,7 +4846,7 @@
// candidates?
DeclAccessPair FoundDecl
= DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0,
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, nullptr,
CurInitExpr, CandidateSet, true);
}
}
@@ -4913,7 +4912,7 @@
bool IsExtraneousCopy) {
// Determine which class type we're copying to.
Expr *CurInitExpr = (Expr *)CurInit.get();
- CXXRecordDecl *Class = 0;
+ CXXRecordDecl *Class = nullptr;
if (const RecordType *Record = T->getAs<RecordType>())
Class = cast<CXXRecordDecl>(Record->getDecl());
if (!Class)
@@ -4945,7 +4944,7 @@
// Only consider constructors and constructor templates. Per
// C++0x [dcl.init]p16, second bullet to class types, this initialization
// is direct-initialization.
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
LookupCopyAndMoveConstructors(S, CandidateSet, Class, CurInitExpr);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -5053,7 +5052,7 @@
return;
// Find constructors which would have been considered.
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
LookupCopyAndMoveConstructors(
S, CandidateSet, cast<CXXRecordDecl>(Record->getDecl()), CurInitExpr);
@@ -5170,7 +5169,7 @@
S.DefineImplicitDefaultConstructor(Loc, Constructor);
}
- ExprResult CurInit = S.Owned((Expr *)0);
+ ExprResult CurInit = S.Owned((Expr *)nullptr);
// C++ [over.match.copy]p1:
// - When initializing a temporary to be bound to the first parameter
@@ -5311,25 +5310,25 @@
/// Determine the declaration which an initialized entity ultimately refers to,
/// for the purpose of lifetime-extending a temporary bound to a reference in
/// the initialization of \p Entity.
-static const ValueDecl *
-getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
- const ValueDecl *FallbackDecl = 0) {
+static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
+ const InitializedEntity *Entity,
+ const InitializedEntity *FallbackDecl = nullptr) {
// C++11 [class.temporary]p5:
- switch (Entity.getKind()) {
+ switch (Entity->getKind()) {
case InitializedEntity::EK_Variable:
// The temporary [...] persists for the lifetime of the reference
- return Entity.getDecl();
+ return Entity;
case InitializedEntity::EK_Member:
// For subobjects, we look at the complete object.
- if (Entity.getParent())
- return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
- Entity.getDecl());
+ if (Entity->getParent())
+ return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+ Entity);
// except:
// -- A temporary bound to a reference member in a constructor's
// ctor-initializer persists until the constructor exits.
- return Entity.getDecl();
+ return Entity;
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
@@ -5344,7 +5343,7 @@
// -- A temporary bound to a reference in a new-initializer persists
// until the completion of the full-expression containing the
// new-initializer.
- return 0;
+ return nullptr;
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
@@ -5352,12 +5351,12 @@
// We don't yet know the storage duration of the surrounding temporary.
// Assume it's got full-expression duration for now, it will patch up our
// storage duration if that's not correct.
- return 0;
+ return nullptr;
case InitializedEntity::EK_ArrayElement:
// For subobjects, we look at the complete object.
- return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
- FallbackDecl);
+ return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+ FallbackDecl);
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
@@ -5372,17 +5371,20 @@
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_ComplexElement:
- return 0;
+ return nullptr;
}
llvm_unreachable("unknown entity kind");
}
-static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD);
+static void performLifetimeExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity);
/// Update a glvalue expression that is used as the initializer of a reference
/// to note that its lifetime is extended.
/// \return \c true if any temporary had its lifetime extended.
-static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) {
+static bool
+performReferenceExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity) {
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
// This is just redundant braces around an initializer. Step over it.
@@ -5416,8 +5418,9 @@
if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) {
// Update the storage duration of the materialized temporary.
// FIXME: Rebuild the expression instead of mutating it.
- ME->setExtendingDecl(ExtendingD);
- performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingD);
+ ME->setExtendingDecl(ExtendingEntity->getDecl(),
+ ExtendingEntity->allocateManglingNumber());
+ performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
return true;
}
@@ -5426,7 +5429,8 @@
/// Update a prvalue expression that is going to be materialized as a
/// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
+static void performLifetimeExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity) {
// Dig out the expression which constructs the extended temporary.
SmallVector<const Expr *, 2> CommaLHSs;
SmallVector<SubobjectAdjustment, 2> Adjustments;
@@ -5438,14 +5442,14 @@
if (CXXStdInitializerListExpr *ILE =
dyn_cast<CXXStdInitializerListExpr>(Init)) {
- performReferenceExtension(ILE->getSubExpr(), ExtendingD);
+ performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
return;
}
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
if (ILE->getType()->isArrayType()) {
for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
- performLifetimeExtension(ILE->getInit(I), ExtendingD);
+ performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
return;
}
@@ -5457,7 +5461,7 @@
// bound to temporaries, those temporaries are also lifetime-extended.
if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
- performReferenceExtension(ILE->getInit(0), ExtendingD);
+ performReferenceExtension(ILE->getInit(0), ExtendingEntity);
else {
unsigned Index = 0;
for (const auto *I : RD->fields()) {
@@ -5467,13 +5471,13 @@
continue;
Expr *SubInit = ILE->getInit(Index);
if (I->getType()->isReferenceType())
- performReferenceExtension(SubInit, ExtendingD);
+ performReferenceExtension(SubInit, ExtendingEntity);
else if (isa<InitListExpr>(SubInit) ||
isa<CXXStdInitializerListExpr>(SubInit))
// This may be either aggregate-initialization of a member or
// initialization of a std::initializer_list object. Either way,
// we should recursively lifetime-extend that initializer.
- performLifetimeExtension(SubInit, ExtendingD);
+ performLifetimeExtension(SubInit, ExtendingEntity);
++Index;
}
}
@@ -5562,7 +5566,7 @@
*ResultType
= S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
- /*NumElts=*/0,
+ /*NumElts=*/nullptr,
ArrayT->getSizeModifier(),
ArrayT->getIndexTypeCVRQualifiers(),
Brackets);
@@ -5585,7 +5589,7 @@
// No steps means no initialization.
if (Steps.empty())
- return S.Owned((Expr *)0);
+ return S.Owned((Expr *)nullptr);
if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() &&
Args.size() == 1 && isa<InitListExpr>(Args[0]) &&
@@ -5618,7 +5622,7 @@
*ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
Entity.getType();
- ExprResult CurInit = S.Owned((Expr *)0);
+ ExprResult CurInit = S.Owned((Expr *)nullptr);
// For initialization steps that start with a single initializer,
// grab the only argument out the Args and place it into the "current"
@@ -5733,7 +5737,7 @@
S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
<< Entity.getType().isVolatileQualified()
<< (BitField ? BitField->getDeclName() : DeclarationName())
- << (BitField != NULL)
+ << (BitField != nullptr)
<< CurInit.get()->getSourceRange();
if (BitField)
S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
@@ -5759,12 +5763,12 @@
// Even though we didn't materialize a temporary, the binding may still
// extend the lifetime of a temporary. This happens if we bind a reference
// to the result of a cast to reference type.
- if (const ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity)) {
- if (performReferenceExtension(CurInit.get(), ExtendingDecl))
- warnOnLifetimeExtension(S, Entity, CurInit.get(), false,
- ExtendingDecl);
- }
+ if (const InitializedEntity *ExtendingEntity =
+ getEntityForTemporaryLifetimeExtension(&Entity))
+ if (performReferenceExtension(CurInit.get(), ExtendingEntity))
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),
+ /*IsInitializerList=*/false,
+ ExtendingEntity->getDecl());
break;
@@ -5776,19 +5780,18 @@
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
- // Maybe lifetime-extend the temporary's subobjects to match the
- // entity's lifetime.
- const ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity);
- if (ExtendingDecl) {
- performLifetimeExtension(CurInit.get(), ExtendingDecl);
- warnOnLifetimeExtension(S, Entity, CurInit.get(), false, ExtendingDecl);
- }
-
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr(
Entity.getType().getNonReferenceType(), CurInit.get(),
- Entity.getType()->isLValueReferenceType(), ExtendingDecl);
+ Entity.getType()->isLValueReferenceType());
+
+ // Maybe lifetime-extend the temporary's subobjects to match the
+ // entity's lifetime.
+ if (const InitializedEntity *ExtendingEntity =
+ getEntityForTemporaryLifetimeExtension(&Entity))
+ if (performReferenceExtension(MTE, ExtendingEntity))
+ warnOnLifetimeExtension(S, Entity, CurInit.get(), /*IsInitializerList=*/false,
+ ExtendingEntity->getDecl());
// If we're binding to an Objective-C object that has lifetime, we
// need cleanups. Likewise if we're extending this temporary to automatic
@@ -5858,7 +5861,7 @@
} else {
// Build a call to the conversion function.
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
- S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0,
+ S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), nullptr,
FoundFn);
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
return ExprError();
@@ -5867,7 +5870,8 @@
// derived-to-base conversion? I believe the answer is "no", because
// we don't want to turn off access control here for c-style casts.
ExprResult CurInitExprRes =
- S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0,
+ S.PerformObjectArgumentInitialization(CurInit.take(),
+ /*Qualifier=*/nullptr,
FoundFn, Conversion);
if(CurInitExprRes.isInvalid())
return ExprError();
@@ -5902,7 +5906,8 @@
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
CurInit.get()->getType(),
- CastKind, CurInit.get(), 0,
+ CastKind, CurInit.get(),
+ nullptr,
CurInit.get()->getValueKind()));
if (MaybeBindToTemp)
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
@@ -5931,7 +5936,7 @@
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type,
CK_LValueToRValue,
CurInit.take(),
- /*BasePath=*/0,
+ /*BasePath=*/nullptr,
VK_RValue));
break;
}
@@ -6168,7 +6173,8 @@
case SK_ProduceObjCObject:
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type,
CK_ARCProduceObject,
- CurInit.take(), 0, VK_RValue));
+ CurInit.take(), nullptr,
+ VK_RValue));
break;
case SK_StdInitializerList: {
@@ -6176,19 +6182,19 @@
diag::warn_cxx98_compat_initializer_list_init)
<< CurInit.get()->getSourceRange();
- // Maybe lifetime-extend the array temporary's subobjects to match the
- // entity's lifetime.
- const ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity);
- if (ExtendingDecl) {
- performLifetimeExtension(CurInit.get(), ExtendingDecl);
- warnOnLifetimeExtension(S, Entity, CurInit.get(), true, ExtendingDecl);
- }
-
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = new (S.Context)
MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(),
- /*lvalue reference*/ false, ExtendingDecl);
+ /*BoundToLvalueReference=*/false);
+
+ // Maybe lifetime-extend the array temporary's subobjects to match the
+ // entity's lifetime.
+ if (const InitializedEntity *ExtendingEntity =
+ getEntityForTemporaryLifetimeExtension(&Entity))
+ if (performReferenceExtension(MTE, ExtendingEntity))
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),
+ /*IsInitializerList=*/true,
+ ExtendingEntity->getDecl());
// Wrap it in a construction of a std::initializer_list<T>.
CurInit = S.Owned(
@@ -6509,7 +6515,7 @@
else
R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd());
- R.setBegin(S.PP.getLocForEndOfToken(R.getBegin()));
+ R.setBegin(S.getLocForEndOfToken(R.getBegin()));
if (Kind.isCStyleOrFunctionalCast())
S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
<< R;
@@ -6974,7 +6980,7 @@
QualType PreNarrowingType,
QualType EntityType,
const Expr *PostInit) {
- const StandardConversionSequence *SCS = 0;
+ const StandardConversionSequence *SCS = nullptr;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
SCS = &ICS.Standard;
@@ -7051,11 +7057,11 @@
return;
}
OS << ">(";
- S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_override)
- << PostInit->getSourceRange()
- << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str())
- << FixItHint::CreateInsertion(
- S.getPreprocessor().getLocForEndOfToken(PostInit->getLocEnd()), ")");
+ S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_silence)
+ << PostInit->getSourceRange()
+ << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str())
+ << FixItHint::CreateInsertion(
+ S.getLocForEndOfToken(PostInit->getLocEnd()), ")");
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 0d287f7..ef92e7c 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -15,7 +15,6 @@
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
@@ -317,18 +316,18 @@
if ((IsInNonspecializedTemplate &&
!(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) ||
isInInlineFunction(CurContext)) {
- ManglingContextDecl = 0;
+ ManglingContextDecl = nullptr;
return &Context.getManglingNumberContext(DC);
}
- ManglingContextDecl = 0;
- return 0;
+ ManglingContextDecl = nullptr;
+ return nullptr;
case StaticDataMember:
// -- the initializers of nonspecialized static members of template classes
if (!IsInNonspecializedTemplate) {
- ManglingContextDecl = 0;
- return 0;
+ ManglingContextDecl = nullptr;
+ return nullptr;
}
// Fall through to get the current context.
@@ -404,7 +403,7 @@
FunctionTemplateDecl::Create(Context, Class,
Method->getLocation(), MethodName,
TemplateParams,
- Method) : 0;
+ Method) : nullptr;
if (TemplateMethod) {
TemplateMethod->setLexicalDeclContext(CurContext);
TemplateMethod->setAccess(AS_public);
@@ -505,7 +504,7 @@
= dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
return cast<EnumDecl>(D->getDeclContext());
}
- return 0;
+ return nullptr;
}
// - it is a comma expression whose RHS is an enumerator-like
@@ -513,7 +512,7 @@
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
if (BO->getOpcode() == BO_Comma)
return findEnumForBlockReturn(BO->getRHS());
- return 0;
+ return nullptr;
}
// - it is a statement-expression whose value expression is an
@@ -521,7 +520,7 @@
if (StmtExpr *SE = dyn_cast<StmtExpr>(E)) {
if (Expr *last = dyn_cast_or_null<Expr>(SE->getSubStmt()->body_back()))
return findEnumForBlockReturn(last);
- return 0;
+ return nullptr;
}
// - it is a ternary conditional operator (not the GNU ?:
@@ -531,7 +530,7 @@
if (EnumDecl *ED = findEnumForBlockReturn(CO->getTrueExpr()))
if (ED == findEnumForBlockReturn(CO->getFalseExpr()))
return ED;
- return 0;
+ return nullptr;
}
// (implicitly:)
@@ -552,7 +551,7 @@
}
// Otherwise, nope.
- return 0;
+ return nullptr;
}
/// Attempt to find a type T for which the returned expression of the
@@ -560,7 +559,7 @@
static EnumDecl *findEnumForBlockReturn(ReturnStmt *ret) {
if (Expr *retValue = ret->getRetValue())
return findEnumForBlockReturn(retValue);
- return 0;
+ return nullptr;
}
/// Attempt to find a common type T for which all of the returned
@@ -571,16 +570,16 @@
// Try to find one for the first return.
EnumDecl *ED = findEnumForBlockReturn(*i);
- if (!ED) return 0;
+ if (!ED) return nullptr;
// Check that the rest of the returns have the same enum.
for (++i; i != e; ++i) {
if (findEnumForBlockReturn(*i) != ED)
- return 0;
+ return nullptr;
}
// Never infer an anonymous enum type.
- if (!ED->hasNameForLinkage()) return 0;
+ if (!ED->hasNameForLinkage()) return nullptr;
return ED;
}
@@ -604,7 +603,7 @@
Expr *E = (cleanups ? cleanups->getSubExpr() : retValue);
E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast,
- E, /*base path*/ 0, VK_RValue);
+ E, /*base path*/ nullptr, VK_RValue);
if (cleanups) {
cleanups->setSubExpr(E);
} else {
@@ -820,7 +819,8 @@
FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) {
FieldDecl *Field = FieldDecl::Create(
Context, LSI->Lambda, Var->getLocation(), Var->getLocation(),
- 0, Var->getType(), Var->getTypeSourceInfo(), 0, false, ICIS_NoInit);
+ nullptr, Var->getType(), Var->getTypeSourceInfo(), nullptr, false,
+ ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
LSI->Lambda->addDecl(Field);
@@ -846,7 +846,7 @@
// has template params, only then are we in a dependent scope.
if (TemplateParams) {
TmplScope = TmplScope->getParent();
- TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0;
+ TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : nullptr;
}
if (TmplScope && !TmplScope->decl_empty())
KnownDependent = true;
@@ -899,10 +899,7 @@
ExplicitResultType = FTI.hasTrailingReturnType();
- if (FTI.NumParams == 1 && !FTI.isVariadic && FTI.Params[0].Ident == 0 &&
- cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType()) {
- // Empty arg list, don't push any params.
- } else {
+ if (FTIHasNonVoidParameters(FTI)) {
Params.reserve(FTI.NumParams);
for (unsigned i = 0, e = FTI.NumParams; i != e; ++i)
Params.push_back(cast<ParmVarDecl>(FTI.Params[i].Param));
@@ -958,21 +955,17 @@
// Handle explicit captures.
SourceLocation PrevCaptureLoc
= Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
- for (SmallVectorImpl<LambdaCapture>::const_iterator
- C = Intro.Captures.begin(),
- E = Intro.Captures.end();
- C != E;
+ for (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E;
PrevCaptureLoc = C->Loc, ++C) {
if (C->Kind == LCK_This) {
// C++11 [expr.prim.lambda]p8:
// An identifier or this shall not appear more than once in a
// lambda-capture.
if (LSI->isCXXThisCaptured()) {
- Diag(C->Loc, diag::err_capture_more_than_once)
- << "'this'"
- << SourceRange(LSI->getCXXThisCapture().getLocation())
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ Diag(C->Loc, diag::err_capture_more_than_once)
+ << "'this'" << SourceRange(LSI->getCXXThisCapture().getLocation())
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
@@ -981,8 +974,8 @@
// lambda-capture shall not contain this [...].
if (Intro.Default == LCD_ByCopy) {
Diag(C->Loc, diag::err_this_capture_with_copy_default)
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
@@ -1004,7 +997,7 @@
if (C->Init.isInvalid())
continue;
- VarDecl *Var = 0;
+ VarDecl *Var = nullptr;
if (C->Init.isUsable()) {
Diag(C->Loc, getLangOpts().CPlusPlus1y
? diag::warn_cxx11_compat_init_capture
@@ -1035,13 +1028,13 @@
// each identifier it contains shall be preceded by &.
if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
Diag(C->Loc, diag::err_reference_capture_with_reference_default)
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
} else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
Diag(C->Loc, diag::err_copy_capture_with_copy_default)
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
@@ -1072,9 +1065,9 @@
if (!CaptureNames.insert(C->Id)) {
if (Var && LSI->isCaptured(Var)) {
Diag(C->Loc, diag::err_capture_more_than_once)
- << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
} else
// Previous capture captured something different (one or both was
// an init-cpature): no fixit.
@@ -1139,6 +1132,8 @@
void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
bool IsInstantiation) {
+ LambdaScopeInfo *LSI = getCurLambda();
+
// Leave the expression-evaluation context.
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
@@ -1148,12 +1143,11 @@
PopDeclContext();
// Finalize the lambda.
- LambdaScopeInfo *LSI = getCurLambda();
CXXRecordDecl *Class = LSI->Lambda;
Class->setInvalidDecl();
SmallVector<Decl*, 4> Fields(Class->fields());
- ActOnFields(0, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), 0);
+ ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
+ SourceLocation(), nullptr);
CheckCompletedCXXClass(Class);
PopFunctionScopeInfo();
@@ -1260,7 +1254,7 @@
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
- /*DefaultArg=*/0));
+ /*DefaultArg=*/nullptr));
CallOpConvTL.setParam(I, From);
CallOpConvNameTL.setParam(I, From);
}
@@ -1380,7 +1374,7 @@
Scope *CurScope,
bool IsInstantiation) {
// Collect information from the lambda scope.
- SmallVector<LambdaExpr::Capture, 4> Captures;
+ SmallVector<LambdaCapture, 4> Captures;
SmallVector<Expr *, 4> CaptureInits;
LambdaCaptureDefault CaptureDefault;
SourceLocation CaptureDefaultLoc;
@@ -1413,9 +1407,8 @@
// Handle 'this' capture.
if (From.isThisCapture()) {
- Captures.push_back(LambdaExpr::Capture(From.getLocation(),
- IsImplicit,
- LCK_This));
+ Captures.push_back(
+ LambdaCapture(From.getLocation(), IsImplicit, LCK_This));
CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
getCurrentThisType(),
/*isImplicit=*/true));
@@ -1424,8 +1417,8 @@
VarDecl *Var = From.getVariable();
LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
- Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit,
- Kind, Var, From.getEllipsisLoc()));
+ Captures.push_back(LambdaCapture(From.getLocation(), IsImplicit, Kind,
+ Var, From.getEllipsisLoc()));
CaptureInits.push_back(From.getInitExpr());
}
@@ -1512,8 +1505,8 @@
// Finalize the lambda class.
SmallVector<Decl*, 4> Fields(Class->fields());
- ActOnFields(0, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), 0);
+ ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
+ SourceLocation(), nullptr);
CheckCompletedCXXClass(Class);
}
@@ -1603,7 +1596,7 @@
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
- /*DefaultArg=*/0));
+ /*DefaultArg=*/nullptr));
}
Block->setParams(BlockParams);
@@ -1615,7 +1608,7 @@
TypeSourceInfo *CapVarTSI =
Context.getTrivialTypeSourceInfo(Src->getType());
VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation,
- ConvLocation, 0,
+ ConvLocation, nullptr,
Src->getType(), CapVarTSI,
SC_None);
BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false,
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index ac6fb25..eb6366c 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Lex/ModuleLoader.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Overload.h"
@@ -244,10 +245,11 @@
IDNS = Decl::IDNS_Tag;
}
break;
+
case Sema::LookupLabel:
IDNS = Decl::IDNS_Label;
break;
-
+
case Sema::LookupMemberName:
IDNS = Decl::IDNS_Member;
if (CPlusPlus)
@@ -263,8 +265,10 @@
break;
case Sema::LookupUsingDeclName:
- IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag
- | Decl::IDNS_Member | Decl::IDNS_Using;
+ assert(Redeclaration && "should only be used for redecl lookup");
+ IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member |
+ Decl::IDNS_Using | Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend |
+ Decl::IDNS_LocalExtern;
break;
case Sema::LookupObjCProtocolName:
@@ -320,9 +324,9 @@
assert(ResultKind != Ambiguous || Decls.size() > 1 ||
(Decls.size() == 1 && (Ambiguity == AmbiguousBaseSubobjects ||
Ambiguity == AmbiguousBaseSubobjectTypes)));
- assert((Paths != NULL) == (ResultKind == Ambiguous &&
- (Ambiguity == AmbiguousBaseSubobjectTypes ||
- Ambiguity == AmbiguousBaseSubobjects)));
+ assert((Paths != nullptr) == (ResultKind == Ambiguous &&
+ (Ambiguity == AmbiguousBaseSubobjectTypes ||
+ Ambiguity == AmbiguousBaseSubobjects)));
return true;
}
@@ -720,7 +724,7 @@
// specialization into the result set. We do this to avoid forcing all
// callers to perform special deduction for conversion functions.
TemplateDeductionInfo Info(R.getNameLoc());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
const FunctionProtoType *ConvProto
= ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>();
@@ -739,7 +743,7 @@
// Perform template argument deduction against the type that we would
// expect the function to have.
- if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
+ if (R.getSema().DeduceTemplateArguments(ConvTemplate, nullptr, ExpectedType,
Specialization, Info)
== Sema::TDK_Success) {
R.addDecl(Specialization);
@@ -789,7 +793,7 @@
// it leaves the current template parameter scope.
static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
DeclContext *DC = S->getEntity();
- DeclContext *Lexical = 0;
+ DeclContext *Lexical = nullptr;
for (Scope *OuterS = S->getParent(); OuterS;
OuterS = OuterS->getParent()) {
if (OuterS->getEntity()) {
@@ -912,7 +916,7 @@
UnqualUsingDirectiveSet UDirs;
bool VisitedUsingDirectives = false;
bool LeftStartingScope = false;
- DeclContext *OutsideOfTemplateParamDC = 0;
+ DeclContext *OutsideOfTemplateParamDC = nullptr;
// When performing a scope lookup, we want to find local extern decls.
FindLocalExternScope FindLocals(R);
@@ -969,7 +973,7 @@
// findOuterContext(). This implements the name lookup behavior
// of C++ [temp.local]p8.
Ctx = OutsideOfTemplateParamDC;
- OutsideOfTemplateParamDC = 0;
+ OutsideOfTemplateParamDC = nullptr;
}
if (Ctx) {
@@ -1112,7 +1116,7 @@
// findOuterContext(). This implements the name lookup behavior
// of C++ [temp.local]p8.
Ctx = OutsideOfTemplateParamDC;
- OutsideOfTemplateParamDC = 0;
+ OutsideOfTemplateParamDC = nullptr;
}
if (Ctx) {
@@ -1210,7 +1214,7 @@
I != N; ++I) {
Module *M = getDefiningModule(ActiveTemplateInstantiations[I].Entity);
if (M && !LookupModulesCache.insert(M).second)
- M = 0;
+ M = nullptr;
ActiveTemplateInstantiationLookupModules.push_back(M);
}
return LookupModulesCache;
@@ -1271,7 +1275,7 @@
}
}
- return 0;
+ return nullptr;
}
NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
@@ -1366,10 +1370,10 @@
// then we'll need to perform our checks based on the matching
// DeclContexts rather than matching scopes.
if (S && isNamespaceOrTranslationUnitScope(S))
- S = 0;
+ S = nullptr;
// Compute the DeclContext, if we need it.
- DeclContext *DC = 0;
+ DeclContext *DC = nullptr;
if (!S)
DC = (*I)->getDeclContext()->getRedeclContext();
@@ -1650,7 +1654,7 @@
Paths.setOrigin(LookupRec);
// Look for this member in our base classes
- CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0;
+ CXXRecordDecl::BaseMatchesCallback *BaseCallback = nullptr;
switch (R.getLookupKind()) {
case LookupObjCImplicitSelfParam:
case LookupOrdinaryName:
@@ -2308,43 +2312,6 @@
}
}
-/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
-/// an acceptable non-member overloaded operator for a call whose
-/// arguments have types T1 (and, if non-empty, T2). This routine
-/// implements the check in C++ [over.match.oper]p3b2 concerning
-/// enumeration types.
-static bool
-IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
- QualType T1, QualType T2,
- ASTContext &Context) {
- if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
- return true;
-
- if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
- return true;
-
- const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
- if (Proto->getNumParams() < 1)
- return false;
-
- if (T1->isEnumeralType()) {
- QualType ArgType = Proto->getParamType(0).getNonReferenceType();
- if (Context.hasSameUnqualifiedType(T1, ArgType))
- return true;
- }
-
- if (Proto->getNumParams() < 2)
- return false;
-
- if (!T2.isNull() && T2->isEnumeralType()) {
- QualType ArgType = Proto->getParamType(1).getNonReferenceType();
- if (Context.hasSameUnqualifiedType(T2, ArgType))
- return true;
- }
-
- return false;
-}
-
NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
SourceLocation Loc,
LookupNameKind NameKind,
@@ -2371,37 +2338,13 @@
// unqualified lookup of operator@ in the context of the
// expression according to the usual rules for name lookup in
// unqualified function calls (3.4.2) except that all member
- // functions are ignored. However, if no operand has a class
- // type, only those non-member functions in the lookup set
- // that have a first parameter of type T1 or "reference to
- // (possibly cv-qualified) T1", when T1 is an enumeration
- // type, or (if there is a right operand) a second parameter
- // of type T2 or "reference to (possibly cv-qualified) T2",
- // when T2 is an enumeration type, are candidate functions.
+ // functions are ignored.
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName);
LookupName(Operators, S);
assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
-
- if (Operators.empty())
- return;
-
- for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
- Op != OpEnd; ++Op) {
- NamedDecl *Found = (*Op)->getUnderlyingDecl();
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Found)) {
- if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
- Functions.addDecl(*Op, Op.getAccess()); // FIXME: canonical FD
- } else if (FunctionTemplateDecl *FunTmpl
- = dyn_cast<FunctionTemplateDecl>(Found)) {
- // FIXME: friend operators?
- // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
- // later?
- if (!FunTmpl->getDeclContext()->isRecord())
- Functions.addDecl(*Op, Op.getAccess());
- }
- }
+ Functions.append(Operators.begin(), Operators.end());
}
Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
@@ -2458,7 +2401,7 @@
// if necessary and make sure that implicit functions are declared.
CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(RD));
DeclarationName Name;
- Expr *Arg = 0;
+ Expr *Arg = nullptr;
unsigned NumArgs;
QualType ArgType = CanTy;
@@ -2522,7 +2465,7 @@
// Now we perform lookup on the name we computed earlier and do overload
// resolution. Lookup is only performed directly into the class since there
// will always be a (possibly implicit) declaration to shadow any others.
- OverloadCandidateSet OCS(RD->getLocation());
+ OverloadCandidateSet OCS(RD->getLocation(), OverloadCandidateSet::CSK_Normal);
DeclContext::lookup_result R = RD->lookup(Name);
assert(!R.empty() &&
"lookup for a constructor or assignment operator was empty");
@@ -2562,12 +2505,12 @@
dyn_cast<FunctionTemplateDecl>(Cand)) {
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
- RD, 0, ThisTy, Classification,
+ RD, nullptr, ThisTy, Classification,
llvm::makeArrayRef(&Arg, NumArgs),
OCS, true);
else
AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
- 0, llvm::makeArrayRef(&Arg, NumArgs),
+ nullptr, llvm::makeArrayRef(&Arg, NumArgs),
OCS, true);
} else {
assert(isa<UsingDecl>(Cand) && "illegal Kind of operator = Decl");
@@ -2587,12 +2530,12 @@
break;
case OR_Ambiguous:
- Result->setMethod(0);
+ Result->setMethod(nullptr);
Result->setKind(SpecialMemberOverloadResult::Ambiguous);
break;
case OR_No_Viable_Function:
- Result->setMethod(0);
+ Result->setMethod(nullptr);
Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted);
break;
}
@@ -2816,7 +2759,7 @@
// If we haven't yet seen a decl for this key, or the last decl
// was exactly this one, we're done.
- if (Old == 0 || Old == New) {
+ if (Old == nullptr || Old == New) {
Old = New;
return;
}
@@ -2842,9 +2785,8 @@
Old = New;
}
-void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
- SourceLocation Loc, ArrayRef<Expr *> Args,
- ADLResult &Result) {
+void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
+ ArrayRef<Expr *> Args, ADLResult &Result) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
@@ -2853,13 +2795,6 @@
AssociatedNamespaces,
AssociatedClasses);
- QualType T1, T2;
- if (Operator) {
- T1 = Args[0]->getType();
- if (Args.size() >= 2)
- T2 = Args[1]->getType();
- }
-
// C++ [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
// and let Y be the lookup set produced by argument dependent
@@ -2912,12 +2847,7 @@
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
- if (isa<FunctionDecl>(D)) {
- if (Operator &&
- !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D),
- T1, T2, Context))
- continue;
- } else if (!isa<FunctionTemplateDecl>(D))
+ if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D))
continue;
Result.insert(D);
@@ -3038,7 +2968,7 @@
}
}
- return 0;
+ return nullptr;
}
static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
@@ -3188,14 +3118,14 @@
for (auto *D : S->decls()) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
if ((ND = Result.getAcceptableDecl(ND))) {
- Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), nullptr, false);
Visited.add(ND);
}
}
}
// FIXME: C++ [temp.local]p8
- DeclContext *Entity = 0;
+ DeclContext *Entity = nullptr;
if (S->getEntity()) {
// Look into this scope's declaration context, along with any of its
// parent lookup contexts (e.g., enclosing classes), up to the point
@@ -3305,7 +3235,7 @@
LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
SourceLocation GnuLabelLoc) {
// Do a lookup to see if we have a label with this name already.
- NamedDecl *Res = 0;
+ NamedDecl *Res = nullptr;
if (GnuLabelLoc.isValid()) {
// Local label definitions always shadow existing labels.
@@ -3320,8 +3250,8 @@
// If we found a label, check to see if it is in the same context as us.
// When in a Block, we don't want to reuse a label in an enclosing function.
if (Res && Res->getDeclContext() != CurContext)
- Res = 0;
- if (Res == 0) {
+ Res = nullptr;
+ if (!Res) {
// If not forward referenced or defined already, create the backing decl.
Res = LabelDecl::Create(Context, CurContext, Loc, II);
Scope *S = CurScope->getFnParent();
@@ -3367,8 +3297,8 @@
bool InBaseClass) override;
void FoundName(StringRef Name);
void addKeywordResult(StringRef Keyword);
- void addName(StringRef Name, NamedDecl *ND, NestedNameSpecifier *NNS = NULL,
- bool isKeyword = false);
+ void addName(StringRef Name, NamedDecl *ND,
+ NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
void addCorrection(TypoCorrection Correction);
typedef TypoResultsMap::iterator result_iterator;
@@ -3424,13 +3354,13 @@
void TypoCorrectionConsumer::FoundName(StringRef Name) {
// Compute the edit distance between the typo and the name of this
// entity, and add the identifier to the list of results.
- addName(Name, NULL);
+ addName(Name, nullptr);
}
void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) {
// Compute the edit distance between the typo and this keyword,
// and add the keyword to the list of results.
- addName(Keyword, NULL, NULL, true);
+ addName(Keyword, nullptr, nullptr, true);
}
void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
@@ -3492,7 +3422,7 @@
else
Identifiers.clear();
- const IdentifierInfo *II = NULL;
+ const IdentifierInfo *II = nullptr;
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
@@ -3561,7 +3491,7 @@
: Context(Context), CurContextChain(BuildContextChain(CurContext)),
isSorted(false) {
if (NestedNameSpecifier *NNS =
- CurScopeSpec ? CurScopeSpec->getScopeRep() : 0) {
+ CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) {
llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier);
NNS->print(SpecifierOStream, Context.getPrintingPolicy());
@@ -3601,7 +3531,7 @@
DeclContextList NamespaceSpecifierSet::BuildContextChain(DeclContext *Start) {
assert(Start && "Building a context chain from a null context");
DeclContextList Chain;
- for (DeclContext *DC = Start->getPrimaryContext(); DC != NULL;
+ for (DeclContext *DC = Start->getPrimaryContext(); DC != nullptr;
DC = DC->getLookupParent()) {
NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(DC);
if (!DC->isInlineNamespace() && !DC->isTransparentContext() &&
@@ -3649,7 +3579,7 @@
}
void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) {
- NestedNameSpecifier *NNS = NULL;
+ NestedNameSpecifier *NNS = nullptr;
unsigned NumSpecifiers = 0;
DeclContextList NamespaceDeclChain(BuildContextChain(Ctx));
DeclContextList FullNamespaceDeclChain(NamespaceDeclChain);
@@ -3995,6 +3925,7 @@
Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS,
CorrectionCandidateCallback &CCC,
+ CorrectTypoKind Mode,
DeclContext *MemberContext,
bool EnteringContext,
const ObjCObjectPointerType *OPT,
@@ -4049,10 +3980,19 @@
if (getLangOpts().AltiVec && Typo->isStr("vector"))
return TypoCorrection();
- NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
-
TypoCorrectionConsumer Consumer(*this, Typo);
+ // If we're handling a missing symbol error, using modules, and the
+ // special search all modules option is used, look for a missing import.
+ if ((Mode == CTK_ErrorRecovery) && getLangOpts().Modules &&
+ getLangOpts().ModulesSearchAll) {
+ // The following has the side effect of loading the missing module.
+ getModuleLoader().lookupMissingImports(Typo->getName(),
+ TypoName.getLocStart());
+ }
+
+ NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
+
// If a callback object considers an empty typo correction candidate to be
// viable, assume it does not do any actual validation of the candidates.
TypoCorrection EmptyCorrection;
@@ -4181,7 +4121,7 @@
bool SSIsTemplate = false;
if (NestedNameSpecifier *NNS =
- (SS && SS->isValid()) ? SS->getScopeRep() : 0) {
+ (SS && SS->isValid()) ? SS->getScopeRep() : nullptr) {
if (const Type *T = NNS->getAsType())
SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization;
}
@@ -4263,14 +4203,14 @@
case LookupResult::FoundUnresolvedValue:
if (TempSS) {
// Immediately retry the lookup without the given CXXScopeSpec
- TempSS = NULL;
+ TempSS = nullptr;
Candidate.WillReplaceSpecifier(true);
goto retry_lookup;
}
if (TempMemberContext) {
if (SS && !TempSS)
TempSS = SS;
- TempMemberContext = NULL;
+ TempMemberContext = nullptr;
goto retry_lookup;
}
QualifiedResults.push_back(Candidate);
@@ -4334,7 +4274,7 @@
// it as it is unlikely a qualified version of the class' constructor
// is an appropriate correction.
if (CXXRecordDecl *NSDecl =
- NSType ? NSType->getAsCXXRecordDecl() : 0) {
+ NSType ? NSType->getAsCXXRecordDecl() : nullptr) {
if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
continue;
}
@@ -4378,7 +4318,8 @@
TRDEnd = TmpRes.end();
TRD != TRDEnd; ++TRD) {
if (CheckMemberAccess(TC.getCorrectionRange().getBegin(),
- NSType ? NSType->getAsCXXRecordDecl() : 0,
+ NSType ? NSType->getAsCXXRecordDecl()
+ : nullptr,
TRD.getPair()) == AR_accessible)
TC.addCorrectionDecl(*TRD);
}
@@ -4511,10 +4452,9 @@
FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
bool HasExplicitTemplateArgs,
- bool AllowNonStaticMethods)
+ MemberExpr *ME)
: NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs),
- AllowNonStaticMethods(AllowNonStaticMethods),
- CurContext(SemaRef.CurContext) {
+ CurContext(SemaRef.CurContext), MemberFn(ME) {
WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus;
WantRemainingKeywords = false;
}
@@ -4526,7 +4466,7 @@
for (TypoCorrection::const_decl_iterator DI = candidate.begin(),
DIEnd = candidate.end();
DI != DIEnd; ++DI) {
- FunctionDecl *FD = 0;
+ FunctionDecl *FD = nullptr;
NamedDecl *ND = (*DI)->getUnderlyingDecl();
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
FD = FTD->getTemplatedDecl();
@@ -4550,15 +4490,18 @@
FD->getMinRequiredArguments() <= NumArgs))
continue;
- // If the current candidate is a non-static C++ method and non-static
- // methods are being excluded, then skip the candidate unless the current
- // DeclContext is a method in the same class or a descendent class of the
- // candidate's parent class.
+ // If the current candidate is a non-static C++ method, skip the candidate
+ // unless the method being corrected--or the current DeclContext, if the
+ // function being corrected is not a method--is a method in the same class
+ // or a descendent class of the candidate's parent class.
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- if (!AllowNonStaticMethods && !MD->isStatic()) {
- CXXMethodDecl *CurMD = dyn_cast_or_null<CXXMethodDecl>(CurContext);
+ if (MemberFn || !MD->isStatic()) {
+ CXXMethodDecl *CurMD =
+ MemberFn
+ ? dyn_cast_or_null<CXXMethodDecl>(MemberFn->getMemberDecl())
+ : dyn_cast_or_null<CXXMethodDecl>(CurContext);
CXXRecordDecl *CurRD =
- CurMD ? CurMD->getParent()->getCanonicalDecl() : 0;
+ CurMD ? CurMD->getParent()->getCanonicalDecl() : nullptr;
CXXRecordDecl *RD = MD->getParent()->getCanonicalDecl();
if (!CurRD || (CurRD != RD && !CurRD->isDerivedFrom(RD)))
continue;
@@ -4582,7 +4525,7 @@
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
return VD->getDefinition();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->isDefined(FD) ? FD : 0;
+ return FD->isDefined(FD) ? FD : nullptr;
if (const TagDecl *TD = dyn_cast<TagDecl>(D))
return TD->getDefinition();
if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
@@ -4591,7 +4534,7 @@
return PD->getDefinition();
if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
return getDefinitionToImport(TD->getTemplatedDecl());
- return 0;
+ return nullptr;
}
/// \brief Diagnose a successfully-corrected typo. Separated from the correction
@@ -4634,9 +4577,9 @@
Diag(Def->getLocation(), diag::note_previous_declaration);
// Recover by implicitly importing this module.
- if (!isSFINAEContext() && ErrorRecovery)
- createImplicitModuleImport(Correction.getCorrectionRange().getBegin(),
- Owner);
+ if (ErrorRecovery)
+ createImplicitModuleImportForErrorRecovery(
+ Correction.getCorrectionRange().getBegin(), Owner);
return;
}
@@ -4644,7 +4587,7 @@
<< CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint());
NamedDecl *ChosenDecl =
- Correction.isKeyword() ? 0 : Correction.getCorrectionDecl();
+ Correction.isKeyword() ? nullptr : Correction.getCorrectionDecl();
if (PrevNote.getDiagID() && ChosenDecl)
Diag(ChosenDecl->getLocation(), PrevNote)
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 3f37efa..bc98299 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -19,7 +19,6 @@
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
@@ -165,7 +164,7 @@
// Proceed with constructing the ObjCPropertyDecls.
ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
- ObjCPropertyDecl *Res = 0;
+ ObjCPropertyDecl *Res = nullptr;
if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
if (CDecl->IsClassExtension()) {
Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
@@ -176,7 +175,7 @@
isOverridingProperty, TSI,
MethodImplKind);
if (!Res)
- return 0;
+ return nullptr;
}
}
@@ -293,8 +292,7 @@
Token Tok;
do {
lexer.LexFromRawLexer(Tok);
- if (Tok.is(tok::raw_identifier) &&
- StringRef(Tok.getRawIdentifierData(), Tok.getLength()) == attrName) {
+ if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) {
Loc = Tok.getLocation();
return true;
}
@@ -339,7 +337,7 @@
= ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) {
Diag(AtLoc, diag::err_duplicate_property);
Diag(prevDecl->getLocation(), diag::note_property_declare);
- return 0;
+ return nullptr;
}
}
}
@@ -371,7 +369,7 @@
if (!CCPrimary) {
Diag(CDecl->getLocation(), diag::err_continuation_class);
*isOverridingProperty = true;
- return 0;
+ return nullptr;
}
// Find the property in continuation class's primary class only.
@@ -389,12 +387,14 @@
// A case of continuation class adding a new property in the class. This
// is not what it was meant for. However, gcc supports it and so should we.
// Make sure setter/getters are declared here.
- ProcessPropertyDecl(PrimaryPDecl, CCPrimary, /* redeclaredProperty = */ 0,
+ ProcessPropertyDecl(PrimaryPDecl, CCPrimary,
+ /* redeclaredProperty = */ nullptr,
/* lexicalDC = */ CDecl);
PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());
PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());
if (ASTMutationListener *L = Context.getASTMutationListener())
- L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/0, CDecl);
+ L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr,
+ CDecl);
return PrimaryPDecl;
}
if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
@@ -414,7 +414,7 @@
Diag(AtLoc,
diag::err_type_mismatch_continuation_class) << PDecl->getType();
Diag(PIDecl->getLocation(), diag::note_property_declare);
- return 0;
+ return nullptr;
}
}
@@ -505,7 +505,7 @@
Diag(AtLoc, diag)
<< CCPrimary->getDeclName();
Diag(PIDecl->getLocation(), diag::note_property_declare);
- return 0;
+ return nullptr;
}
*isOverridingProperty = true;
// Make sure setter decl is synthesized, and added to primary class's list.
@@ -550,7 +550,7 @@
if (T->isObjCObjectType()) {
SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd();
- StarLoc = PP.getLocForEndOfToken(StarLoc);
+ StarLoc = getLocForEndOfToken(StarLoc);
Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(StarLoc, "*");
T = Context.getObjCObjectPointerType(T);
@@ -805,19 +805,19 @@
// Make sure we have a context for the property implementation declaration.
if (!ClassImpDecl) {
Diag(AtLoc, diag::error_missing_property_context);
- return 0;
+ return nullptr;
}
if (PropertyIvarLoc.isInvalid())
PropertyIvarLoc = PropertyLoc;
SourceLocation PropertyDiagLoc = PropertyLoc;
if (PropertyDiagLoc.isInvalid())
PropertyDiagLoc = ClassImpDecl->getLocStart();
- ObjCPropertyDecl *property = 0;
- ObjCInterfaceDecl* IDecl = 0;
+ ObjCPropertyDecl *property = nullptr;
+ ObjCInterfaceDecl *IDecl = nullptr;
// Find the class or category class where this property must have
// a declaration.
- ObjCImplementationDecl *IC = 0;
- ObjCCategoryImplDecl* CatImplClass = 0;
+ ObjCImplementationDecl *IC = nullptr;
+ ObjCCategoryImplDecl *CatImplClass = nullptr;
if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
IDecl = IC->getClassInterface();
// We always synthesize an interface for an implementation
@@ -829,7 +829,7 @@
property = IDecl->FindPropertyDeclaration(PropertyId);
if (!property) {
Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
- return 0;
+ return nullptr;
}
unsigned PIkind = property->getPropertyAttributesAsWritten();
if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic |
@@ -846,7 +846,7 @@
if (!CD->IsClassExtension()) {
Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
Diag(property->getLocation(), diag::note_property_declare);
- return 0;
+ return nullptr;
}
}
if (Synthesize&&
@@ -889,12 +889,12 @@
} else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
if (Synthesize) {
Diag(AtLoc, diag::error_synthesize_category_decl);
- return 0;
+ return nullptr;
}
IDecl = CatImplClass->getClassInterface();
if (!IDecl) {
Diag(AtLoc, diag::error_missing_property_interface);
- return 0;
+ return nullptr;
}
ObjCCategoryDecl *Category =
IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
@@ -902,19 +902,19 @@
// If category for this implementation not found, it is an error which
// has already been reported eralier.
if (!Category)
- return 0;
+ return nullptr;
// Look for this property declaration in @implementation's category
property = Category->FindPropertyDeclaration(PropertyId);
if (!property) {
Diag(PropertyLoc, diag::error_bad_category_property_decl)
<< Category->getDeclName();
- return 0;
+ return nullptr;
}
} else {
Diag(AtLoc, diag::error_bad_property_context);
- return 0;
+ return nullptr;
}
- ObjCIvarDecl *Ivar = 0;
+ ObjCIvarDecl *Ivar = nullptr;
bool CompleteTypeErr = false;
bool compat = true;
// Check that we have a valid, previously declared ivar for @synthesize
@@ -962,14 +962,14 @@
// an ivar matching property name and issue warning; since this
// is the most common case of not using an ivar used for backing
// property in non-default synthesis case.
- ObjCInterfaceDecl *ClassDeclared=0;
+ ObjCInterfaceDecl *ClassDeclared=nullptr;
ObjCIvarDecl *originalIvar =
IDecl->lookupInstanceVariable(property->getIdentifier(),
ClassDeclared);
if (originalIvar) {
Diag(PropertyDiagLoc,
diag::warn_autosynthesis_property_ivar_match)
- << PropertyId << (Ivar == 0) << PropertyIvar
+ << PropertyId << (Ivar == nullptr) << PropertyIvar
<< originalIvar->getIdentifier();
Diag(property->getLocation(), diag::note_property_declare);
Diag(originalIvar->getLocation(), diag::note_ivar_decl);
@@ -1028,9 +1028,9 @@
Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
- PropertyIvarType, /*Dinfo=*/0,
+ PropertyIvarType, /*Dinfo=*/nullptr,
ObjCIvarDecl::Private,
- (Expr *)0, true);
+ (Expr *)nullptr, true);
if (RequireNonAbstractType(PropertyIvarLoc,
PropertyIvarType,
diag::err_abstract_type_in_decl,
@@ -1146,7 +1146,8 @@
MarkDeclRefReferenced(SelfExpr);
Expr *LoadSelfExpr =
ImplicitCastExpr::Create(Context, SelfDecl->getType(),
- CK_LValueToRValue, SelfExpr, 0, VK_RValue);
+ CK_LValueToRValue, SelfExpr, nullptr,
+ VK_RValue);
Expr *IvarRefExpr =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
Ivar->getLocation(),
@@ -1195,7 +1196,8 @@
MarkDeclRefReferenced(SelfExpr);
Expr *LoadSelfExpr =
ImplicitCastExpr::Create(Context, SelfDecl->getType(),
- CK_LValueToRValue, SelfExpr, 0, VK_RValue);
+ CK_LValueToRValue, SelfExpr, nullptr,
+ VK_RValue);
Expr *lhs =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
Ivar->getLocation(),
@@ -1241,7 +1243,7 @@
= IC->FindPropertyImplDecl(PropertyId)) {
Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
- return 0;
+ return nullptr;
}
IC->addPropertyImplementation(PIDecl);
if (getLangOpts().ObjCDefaultSynthProperties &&
@@ -1250,8 +1252,8 @@
// Diagnose if an ivar was lazily synthesdized due to a previous
// use and if 1) property is @dynamic or 2) property is synthesized
// but it requires an ivar of different name.
- ObjCInterfaceDecl *ClassDeclared=0;
- ObjCIvarDecl *Ivar = 0;
+ ObjCInterfaceDecl *ClassDeclared=nullptr;
+ ObjCIvarDecl *Ivar = nullptr;
if (!Synthesize)
Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
else {
@@ -1280,7 +1282,7 @@
CatImplClass->FindPropertyImplDecl(PropertyId)) {
Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId;
Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
- return 0;
+ return nullptr;
}
CatImplClass->addPropertyImplementation(PIDecl);
}
@@ -1624,7 +1626,7 @@
// class's protocol, or one of it super classes. This is because,
// the class is going to implement them.
if (!SMap.count(Method) &&
- (PrimaryClass == 0 ||
+ (PrimaryClass == nullptr ||
!PrimaryClass->lookupPropertyAccessor(Method, C))) {
S.Diag(IMPDecl->getLocation(),
isa<ObjCCategoryDecl>(CDecl) ?
@@ -1679,7 +1681,7 @@
// Lazily construct a set of all the properties in the @interface
// of the class, without looking at the superclass. We cannot
// use the call to CollectImmediateProperties() above as that
- // utilizes information fromt he super class's properties as well
+ // utilizes information from the super class's properties as well
// as scans the adopted protocols. This work only triggers for protocols
// with the attribute, which is very rare, and only occurs when
// analyzing the @implementation.
@@ -1712,7 +1714,7 @@
InsMap.insert(I->getSelector());
ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
- ObjCInterfaceDecl *PrimaryClass = 0;
+ ObjCInterfaceDecl *PrimaryClass = nullptr;
if (C && !C->IsClassExtension())
if ((PrimaryClass = C->getClassInterface()))
// Report unimplemented properties in the category as well.
@@ -1751,8 +1753,8 @@
if (getLangOpts().getGC() != LangOptions::NonGC)
return;
for (const auto *Property : IDecl->properties()) {
- ObjCMethodDecl *GetterMethod = 0;
- ObjCMethodDecl *SetterMethod = 0;
+ ObjCMethodDecl *GetterMethod = nullptr;
+ ObjCMethodDecl *SetterMethod = nullptr;
bool LookedUpGetterSetter = false;
unsigned Attributes = Property->getPropertyAttributes();
@@ -1794,8 +1796,8 @@
(GetterMethod ? GetterMethod->getLocation()
: SetterMethod->getLocation());
Diag(MethodLoc, diag::warn_atomic_property_rule)
- << Property->getIdentifier() << (GetterMethod != 0)
- << (SetterMethod != 0);
+ << Property->getIdentifier() << (GetterMethod != nullptr)
+ << (SetterMethod != nullptr);
// fixit stuff.
if (!AttributesAsWritten) {
if (Property->getLParenLoc().isValid()) {
@@ -1905,6 +1907,9 @@
ObjCMethodDecl *GetterMethod, *SetterMethod;
+ if (CD->isInvalidDecl())
+ return;
+
GetterMethod = CD->getInstanceMethod(property->getGetterName());
SetterMethod = CD->getInstanceMethod(property->getSetterName());
DiagnosePropertyAccessorMismatch(property, GetterMethod,
@@ -1945,8 +1950,9 @@
GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
property->getGetterName(),
- property->getType(), 0, CD, /*isInstance=*/true,
- /*isVariadic=*/false, /*isPropertyAccessor=*/true,
+ property->getType(), nullptr, CD,
+ /*isInstance=*/true, /*isVariadic=*/false,
+ /*isPropertyAccessor=*/true,
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
(property->getPropertyImplementation() ==
ObjCPropertyDecl::Optional) ?
@@ -1969,8 +1975,9 @@
ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
if (const SectionAttr *SA = property->getAttr<SectionAttr>())
- GetterMethod->addAttr(SectionAttr::CreateImplicit(Context, SA->getName(),
- Loc));
+ GetterMethod->addAttr(
+ SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
+ SA->getName(), Loc));
if (getLangOpts().ObjCAutoRefCount)
CheckARCMethodDecl(GetterMethod);
@@ -1993,8 +2000,9 @@
SetterMethod =
ObjCMethodDecl::Create(Context, Loc, Loc,
- property->getSetterName(), Context.VoidTy, 0,
- CD, /*isInstance=*/true, /*isVariadic=*/false,
+ property->getSetterName(), Context.VoidTy,
+ nullptr, CD, /*isInstance=*/true,
+ /*isVariadic=*/false,
/*isPropertyAccessor=*/true,
/*isImplicitlyDeclared=*/true,
/*isDefined=*/false,
@@ -2009,9 +2017,9 @@
Loc, Loc,
property->getIdentifier(),
property->getType().getUnqualifiedType(),
- /*TInfo=*/0,
+ /*TInfo=*/nullptr,
SC_None,
- 0);
+ nullptr);
SetterMethod->setMethodParams(Context, Argument, None);
AddPropertyAttrs(*this, SetterMethod, property);
@@ -2022,8 +2030,9 @@
if (lexicalDC)
SetterMethod->setLexicalDeclContext(lexicalDC);
if (const SectionAttr *SA = property->getAttr<SectionAttr>())
- SetterMethod->addAttr(SectionAttr::CreateImplicit(Context,
- SA->getName(), Loc));
+ SetterMethod->addAttr(
+ SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
+ SA->getName(), Loc));
// It's possible for the user to have set a very odd custom
// setter selector that causes it to have a method family.
if (getLangOpts().ObjCAutoRefCount)
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index 78f73c0..603dd56 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -1,4 +1,4 @@
-//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ----------===//
+//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,13 +12,14 @@
///
//===----------------------------------------------------------------------===//
-#include "clang/Basic/OpenMPKinds.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/OpenMPKinds.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
@@ -34,9 +35,9 @@
namespace {
/// \brief Default data sharing attributes, which can be applied to directive.
enum DefaultDataSharingAttributes {
- DSA_unspecified = 0, /// \brief Data sharing attribute not specified.
- DSA_none = 1 << 0, /// \brief Default data sharing attribute 'none'.
- DSA_shared = 1 << 1 /// \brief Default data sharing attribute 'shared'.
+ DSA_unspecified = 0, /// \brief Data sharing attribute not specified.
+ DSA_none = 1 << 0, /// \brief Default data sharing attribute 'none'.
+ DSA_shared = 1 << 1 /// \brief Default data sharing attribute 'shared'.
};
/// \brief Stack for tracking declarations used in OpenMP directives and
@@ -47,8 +48,9 @@
OpenMPDirectiveKind DKind;
OpenMPClauseKind CKind;
DeclRefExpr *RefExpr;
- DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(0) { }
+ DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr) {}
};
+
private:
struct DSAInfo {
OpenMPClauseKind Attributes;
@@ -62,15 +64,13 @@
OpenMPDirectiveKind Directive;
DeclarationNameInfo DirectiveName;
Scope *CurScope;
- SharingMapTy(OpenMPDirectiveKind DKind,
- const DeclarationNameInfo &Name,
+ SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope)
- : SharingMap(), DefaultAttr(DSA_unspecified), Directive(DKind),
- DirectiveName(Name), CurScope(CurScope) { }
+ : SharingMap(), DefaultAttr(DSA_unspecified), Directive(DKind),
+ DirectiveName(std::move(Name)), CurScope(CurScope) {}
SharingMapTy()
- : SharingMap(), DefaultAttr(DSA_unspecified),
- Directive(OMPD_unknown), DirectiveName(),
- CurScope(0) { }
+ : SharingMap(), DefaultAttr(DSA_unspecified), Directive(OMPD_unknown),
+ DirectiveName(), CurScope(nullptr) {}
};
typedef SmallVector<SharingMapTy, 64> StackTy;
@@ -85,8 +85,9 @@
/// \brief Checks if the variable is a local for OpenMP region.
bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
+
public:
- explicit DSAStackTy(Sema &S) : Stack(1), Actions(S) { }
+ explicit DSAStackTy(Sema &S) : Stack(1), Actions(S) {}
void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
Scope *CurScope) {
@@ -134,7 +135,7 @@
Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
};
-} // end anonymous namespace.
+} // namespace
DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
VarDecl *D) {
@@ -166,8 +167,7 @@
// inside the construct are private.
if (DVar.DKind != OMPD_parallel) {
if (isOpenMPLocal(D, Iter) && D->isLocalVarDecl() &&
- (D->getStorageClass() == SC_Auto ||
- D->getStorageClass() == SC_None)) {
+ (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) {
DVar.CKind = OMPC_private;
return DVar;
}
@@ -212,23 +212,25 @@
for (StackTy::reverse_iterator I = std::next(Iter),
EE = std::prev(Stack.rend());
I != EE; ++I) {
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
+ // Referenced
// in a Construct, implicitly determined, p.6]
// In a task construct, if no default clause is present, a variable
// whose data-sharing attribute is not determined by the rules above is
// firstprivate.
DVarTemp = getDSA(I, D);
if (DVarTemp.CKind != OMPC_shared) {
- DVar.RefExpr = 0;
+ DVar.RefExpr = nullptr;
DVar.DKind = OMPD_task;
DVar.CKind = OMPC_firstprivate;
return DVar;
}
- if (I->Directive == OMPD_parallel) break;
+ if (I->Directive == OMPD_parallel)
+ break;
}
DVar.DKind = OMPD_task;
DVar.CKind =
- (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
+ (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
return DVar;
}
}
@@ -251,17 +253,16 @@
}
}
-bool
-DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
if (Stack.size() > 2) {
reverse_iterator I = Iter, E = Stack.rend() - 1;
- Scope *TopScope = 0;
- while (I != E &&
- I->Directive != OMPD_parallel) {
+ Scope *TopScope = nullptr;
+ while (I != E && I->Directive != OMPD_parallel) {
++I;
}
- if (I == E) return false;
- TopScope = I->CurScope ? I->CurScope->getParent() : 0;
+ if (I == E)
+ return false;
+ TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
Scope *CurScope = getCurScope();
while (CurScope != TopScope && !CurScope->isDeclScope(D)) {
CurScope = CurScope->getParent();
@@ -294,17 +295,18 @@
OpenMPDirectiveKind Kind = getCurrentDirective();
if (Kind != OMPD_parallel) {
if (isOpenMPLocal(D, std::next(Stack.rbegin())) && D->isLocalVarDecl() &&
- (D->getStorageClass() == SC_Auto ||
- D->getStorageClass() == SC_None))
+ (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) {
DVar.CKind = OMPC_private;
return DVar;
+ }
}
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.4]
// Static data memebers are shared.
if (D->isStaticDataMember()) {
- // Variables with const-qualified type having no mutable member may be listed
+ // Variables with const-qualified type having no mutable member may be
+ // listed
// in a firstprivate clause, even if they are static data members.
DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
@@ -324,8 +326,8 @@
// in a Construct, C/C++, predetermined, p.6]
// Variables with const qualified type having no mutable member are
// shared.
- CXXRecordDecl *RD = Actions.getLangOpts().CPlusPlus ?
- Type->getAsCXXRecordDecl() : 0;
+ CXXRecordDecl *RD =
+ Actions.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
if (IsConstant &&
!(Actions.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
// Variables with const-qualified type having no mutable member may be
@@ -366,7 +368,8 @@
for (StackTy::reverse_iterator I = std::next(Stack.rbegin()),
E = std::prev(Stack.rend());
I != E; ++I) {
- if (DKind != OMPD_unknown && DKind != I->Directive) continue;
+ if (DKind != OMPD_unknown && DKind != I->Directive)
+ continue;
DSAVarData DVar = getDSA(I, D);
if (DVar.CKind == CKind)
return DVar;
@@ -380,9 +383,7 @@
#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
-void Sema::DestroyDataSharingAttributesStack() {
- delete DSAStack;
-}
+void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
const DeclarationNameInfo &DirName,
@@ -402,8 +403,9 @@
class VarDeclFilterCCC : public CorrectionCandidateCallback {
private:
Sema &Actions;
+
public:
- VarDeclFilterCCC(Sema &S) : Actions(S) { }
+ VarDeclFilterCCC(Sema &S) : Actions(S) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
@@ -414,7 +416,7 @@
return false;
}
};
-}
+} // namespace
ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
CXXScopeSpec &ScopeSpec,
@@ -428,12 +430,14 @@
VarDecl *VD;
if (!Lookup.isSingleResult()) {
VarDeclFilterCCC Validator(*this);
- if (TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope,
- 0, Validator)) {
+ if (TypoCorrection Corrected =
+ CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, Validator,
+ CTK_ErrorRecovery)) {
diagnoseTypo(Corrected,
- PDiag(Lookup.empty()? diag::err_undeclared_var_use_suggest
- : diag::err_omp_expected_var_arg_suggest)
- << Id.getName());
+ PDiag(Lookup.empty()
+ ? diag::err_undeclared_var_use_suggest
+ : diag::err_omp_expected_var_arg_suggest)
+ << Id.getName());
VD = Corrected.getCorrectionDeclAs<VarDecl>();
} else {
Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
@@ -443,8 +447,7 @@
}
} else {
if (!(VD = Lookup.getAsSingle<VarDecl>())) {
- Diag(Id.getLoc(), diag::err_omp_expected_var_arg)
- << Id.getName();
+ Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
return ExprError();
}
@@ -455,12 +458,12 @@
// Variables must be file-scope, namespace-scope, or static block-scope.
if (!VD->hasGlobalStorage()) {
Diag(Id.getLoc(), diag::err_omp_global_var_arg)
- << getOpenMPDirectiveName(OMPD_threadprivate)
- << !VD->isStaticLocal();
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << !VD->isStaticLocal();
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD;
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
@@ -472,11 +475,12 @@
if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
!getCurLexicalContext()->isTranslationUnit()) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
// OpenMP [2.9.2, Restrictions, C/C++, p.3]
@@ -486,11 +490,12 @@
if (CanonicalVD->isStaticDataMember() &&
!CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
// OpenMP [2.9.2, Restrictions, C/C++, p.4]
@@ -501,11 +506,12 @@
(!getCurLexicalContext()->isFileContext() ||
!getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
// OpenMP [2.9.2, Restrictions, C/C++, p.6]
@@ -514,11 +520,12 @@
if (CanonicalVD->isStaticLocal() && CurScope &&
!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
@@ -527,7 +534,7 @@
// of the variables in its list.
if (VD->isUsed()) {
Diag(Id.getLoc(), diag::err_omp_var_used)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
return ExprError();
}
@@ -536,9 +543,9 @@
return DE;
}
-Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
- SourceLocation Loc,
- ArrayRef<Expr *> VarList) {
+Sema::DeclGroupPtrTy
+Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
+ ArrayRef<Expr *> VarList) {
if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
CurContext->addDecl(D);
return DeclGroupPtrTy::make(DeclGroupRef(D));
@@ -546,14 +553,11 @@
return DeclGroupPtrTy();
}
-OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
- SourceLocation Loc,
- ArrayRef<Expr *> VarList) {
+OMPThreadPrivateDecl *
+Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(),
- E = VarList.end();
- I != E; ++I) {
- DeclRefExpr *DE = cast<DeclRefExpr>(*I);
+ for (auto &RefExpr : VarList) {
+ DeclRefExpr *DE = cast<DeclRefExpr>(RefExpr);
VarDecl *VD = cast<VarDecl>(DE->getDecl());
SourceLocation ILoc = DE->getExprLoc();
@@ -568,29 +572,30 @@
// A threadprivate variable must not have a reference type.
if (VD->getType()->isReferenceType()) {
Diag(ILoc, diag::err_omp_ref_type_arg)
- << getOpenMPDirectiveName(OMPD_threadprivate)
- << VD->getType();
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
continue;
}
// Check if this is a TLS variable.
if (VD->getTLSKind()) {
Diag(ILoc, diag::err_omp_var_thread_local) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
continue;
}
- Vars.push_back(*I);
+ Vars.push_back(RefExpr);
DSAStack->addDSA(VD, DE, OMPC_threadprivate);
}
- OMPThreadPrivateDecl *D = 0;
+ OMPThreadPrivateDecl *D = nullptr;
if (!Vars.empty()) {
D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
Vars);
@@ -606,11 +611,13 @@
bool ErrorFound;
CapturedStmt *CS;
llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
+
public:
void VisitDeclRefExpr(DeclRefExpr *E) {
- if(VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
// Skip internally declared variables.
- if (VD->isLocalVarDecl() && !CS->capturesVariable(VD)) return;
+ if (VD->isLocalVarDecl() && !CS->capturesVariable(VD))
+ return;
SourceLocation ELoc = E->getExprLoc();
@@ -646,28 +653,55 @@
}
}
void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
- for (ArrayRef<OMPClause *>::iterator I = S->clauses().begin(),
- E = S->clauses().end();
- I != E; ++I)
- if (OMPClause *C = *I)
+ for (auto C : S->clauses())
+ if (C)
for (StmtRange R = C->children(); R; ++R)
if (Stmt *Child = *R)
Visit(Child);
}
void VisitStmt(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();
- I != E; ++I)
+ for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E;
+ ++I)
if (Stmt *Child = *I)
if (!isa<OMPExecutableDirective>(Child))
Visit(Child);
- }
+ }
bool isErrorFound() { return ErrorFound; }
ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; }
DSAAttrChecker(DSAStackTy *S, Sema &Actions, CapturedStmt *CS)
- : Stack(S), Actions(Actions), ErrorFound(false), CS(CS) { }
+ : Stack(S), Actions(Actions), ErrorFound(false), CS(CS) {}
};
+} // namespace
+
+void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,
+ Scope *CurScope) {
+ switch (DKind) {
+ case OMPD_parallel: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ Sema::CapturedParamNameType Params[3] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
+ break;
+ }
+ case OMPD_simd: {
+ Sema::CapturedParamNameType Params[1] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
+ break;
+ }
+ case OMPD_threadprivate:
+ case OMPD_task:
+ llvm_unreachable("OpenMP Directive is not allowed");
+ case OMPD_unknown:
+ llvm_unreachable("Unknown OpenMP directive");
+ }
}
StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
@@ -690,35 +724,34 @@
bool ErrorFound = false;
if (!DSAChecker.getImplicitFirstprivate().empty()) {
- if (OMPClause *Implicit =
- ActOnOpenMPFirstprivateClause(DSAChecker.getImplicitFirstprivate(),
- SourceLocation(), SourceLocation(),
- SourceLocation())) {
+ if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
+ DSAChecker.getImplicitFirstprivate(), SourceLocation(),
+ SourceLocation(), SourceLocation())) {
ClausesWithImplicit.push_back(Implicit);
ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
- DSAChecker.getImplicitFirstprivate().size();
+ DSAChecker.getImplicitFirstprivate().size();
} else
ErrorFound = true;
}
switch (Kind) {
case OMPD_parallel:
- Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt,
- StartLoc, EndLoc);
+ Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
break;
case OMPD_simd:
- Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt,
- StartLoc, EndLoc);
+ Res =
+ ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
break;
case OMPD_threadprivate:
case OMPD_task:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
- case NUM_OPENMP_DIRECTIVES:
llvm_unreachable("Unknown OpenMP directive");
}
- if (ErrorFound) return StmtError();
+ if (ErrorFound)
+ return StmtError();
return Res;
}
@@ -726,15 +759,23 @@
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 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.
+ CS->getCapturedDecl()->setNothrow();
+
getCurFunction()->setHasBranchProtectedScope();
- return Owned(OMPParallelDirective::Create(Context, StartLoc, EndLoc,
- Clauses, AStmt));
+ return Owned(
+ OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt));
}
StmtResult Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
+ Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
Stmt *CStmt = AStmt;
while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(CStmt))
@@ -744,23 +785,22 @@
ForStmt *For = dyn_cast<ForStmt>(CStmt);
if (!For) {
Diag(CStmt->getLocStart(), diag::err_omp_not_for)
- << getOpenMPDirectiveName(OMPD_simd);
+ << getOpenMPDirectiveName(OMPD_simd);
return StmtError();
}
// FIXME: Checking loop canonical form, collapsing etc.
getCurFunction()->setHasBranchProtectedScope();
- return Owned(OMPSimdDirective::Create(Context, StartLoc, EndLoc,
- Clauses, AStmt));
+ return Owned(
+ OMPSimdDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt));
}
-OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
- Expr *Expr,
+OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
- OMPClause *Res = 0;
+ OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_if:
Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc);
@@ -771,21 +811,24 @@
case OMPC_safelen:
Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_collapse:
+ Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_default:
+ case OMPC_proc_bind:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_linear:
case OMPC_copyin:
case OMPC_threadprivate:
case OMPC_unknown:
- case NUM_OPENMP_CLAUSES:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
-OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition,
- SourceLocation StartLoc,
+OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
Expr *ValExpr = Condition;
@@ -793,10 +836,9 @@
!Condition->isInstantiationDependent() &&
!Condition->containsUnexpandedParameterPack()) {
ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(),
- Condition->getExprLoc(),
- Condition);
+ Condition->getExprLoc(), Condition);
if (Val.isInvalid())
- return 0;
+ return nullptr;
ValExpr = Val.take();
}
@@ -812,36 +854,36 @@
class IntConvertDiagnoser : public ICEConvertDiagnoser {
public:
IntConvertDiagnoser()
- : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
- false, true) {}
+ : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
QualType T) override {
return S.Diag(Loc, diag::err_omp_not_integral) << T;
}
- SemaDiagnosticBuilder diagnoseIncomplete(
- Sema &S, SourceLocation Loc, QualType T) override {
+ SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
}
- SemaDiagnosticBuilder diagnoseExplicitConv(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
+ SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) override {
return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
}
- SemaDiagnosticBuilder noteExplicitConv(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
+ SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
+ QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
- << ConvTy->isEnumeralType() << ConvTy;
+ << ConvTy->isEnumeralType() << ConvTy;
}
- SemaDiagnosticBuilder diagnoseAmbiguous(
- Sema &S, SourceLocation Loc, QualType T) override {
+ SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
}
- SemaDiagnosticBuilder noteAmbiguous(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
+ SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
+ QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
- << ConvTy->isEnumeralType() << ConvTy;
+ << ConvTy->isEnumeralType() << ConvTy;
}
- SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
+ SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
+ QualType) override {
llvm_unreachable("conversion functions are permitted");
}
} ConvertDiagnoser;
@@ -860,23 +902,23 @@
ExprResult Val =
PerformImplicitIntegerConversion(NumThreadsLoc, NumThreads);
if (Val.isInvalid())
- return 0;
+ return nullptr;
ValExpr = Val.take();
// OpenMP [2.5, Restrictions]
// The num_threads expression must evaluate to a positive integer value.
llvm::APSInt Result;
- if (ValExpr->isIntegerConstantExpr(Result, Context) &&
- Result.isSigned() && !Result.isStrictlyPositive()) {
+ if (ValExpr->isIntegerConstantExpr(Result, Context) && Result.isSigned() &&
+ !Result.isStrictlyPositive()) {
Diag(NumThreadsLoc, diag::err_omp_negative_expression_in_clause)
<< "num_threads" << NumThreads->getSourceRange();
- return 0;
+ return nullptr;
}
}
- return new (Context) OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc,
- EndLoc);
+ return new (Context)
+ OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc, EndLoc);
}
ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
@@ -906,34 +948,51 @@
// positive integer expression.
ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
if (Safelen.isInvalid())
- return 0;
+ return nullptr;
return new (Context)
OMPSafelenClause(Safelen.take(), StartLoc, LParenLoc, EndLoc);
}
-OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
- unsigned Argument,
- SourceLocation ArgumentLoc,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- OMPClause *Res = 0;
+OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *Num, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ // OpenMP [2.8.1, simd construct, Description]
+ // The parameter of the collapse clause must be a constant
+ // positive integer expression.
+ ExprResult NumForLoops =
+ VerifyPositiveIntegerConstantInClause(Num, OMPC_collapse);
+ if (NumForLoops.isInvalid())
+ return nullptr;
+ return new (Context)
+ OMPCollapseClause(NumForLoops.take(), StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPSimpleClause(
+ OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
+ OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_default:
Res =
- ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
- ArgumentLoc, StartLoc, LParenLoc, EndLoc);
+ ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
+ ArgumentLoc, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_proc_bind:
+ Res = ActOnOpenMPProcBindClause(
+ static_cast<OpenMPProcBindClauseKind>(Argument), ArgumentLoc, StartLoc,
+ LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_linear:
case OMPC_copyin:
case OMPC_threadprivate:
case OMPC_unknown:
- case NUM_OPENMP_CLAUSES:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -946,19 +1005,18 @@
SourceLocation EndLoc) {
if (Kind == OMPC_DEFAULT_unknown) {
std::string Values;
- static_assert(NUM_OPENMP_DEFAULT_KINDS > 1,
- "NUM_OPENMP_DEFAULT_KINDS not greater than 1");
+ static_assert(OMPC_DEFAULT_unknown > 0,
+ "OMPC_DEFAULT_unknown not greater than 0");
std::string Sep(", ");
- for (unsigned i = OMPC_DEFAULT_unknown + 1;
- i < NUM_OPENMP_DEFAULT_KINDS; ++i) {
+ for (unsigned i = 0; i < OMPC_DEFAULT_unknown; ++i) {
Values += "'";
Values += getOpenMPSimpleClauseTypeName(OMPC_default, i);
Values += "'";
switch (i) {
- case NUM_OPENMP_DEFAULT_KINDS - 2:
+ case OMPC_DEFAULT_unknown - 2:
Values += " or ";
break;
- case NUM_OPENMP_DEFAULT_KINDS - 1:
+ case OMPC_DEFAULT_unknown - 1:
break;
default:
Values += Sep;
@@ -966,8 +1024,8 @@
}
}
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
- << Values << getOpenMPClauseName(OMPC_default);
- return 0;
+ << Values << getOpenMPClauseName(OMPC_default);
+ return nullptr;
}
switch (Kind) {
case OMPC_DEFAULT_none:
@@ -977,20 +1035,50 @@
DSAStack->setDefaultDSAShared();
break;
case OMPC_DEFAULT_unknown:
- case NUM_OPENMP_DEFAULT_KINDS:
llvm_unreachable("Clause kind is not allowed.");
break;
}
- return new (Context) OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc,
- EndLoc);
+ return new (Context)
+ OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
}
-OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
- ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- OMPClause *Res = 0;
+OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
+ SourceLocation KindKwLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ if (Kind == OMPC_PROC_BIND_unknown) {
+ std::string Values;
+ std::string Sep(", ");
+ for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) {
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i);
+ Values += "'";
+ switch (i) {
+ case OMPC_PROC_BIND_unknown - 2:
+ Values += " or ";
+ break;
+ case OMPC_PROC_BIND_unknown - 1:
+ break;
+ default:
+ Values += Sep;
+ break;
+ }
+ }
+ Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
+ << Values << getOpenMPClauseName(OMPC_proc_bind);
+ return nullptr;
+ }
+ return new (Context)
+ OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *
+Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> VarList,
+ Expr *TailExpr, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc) {
+ OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_private:
Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
@@ -1001,16 +1089,21 @@
case OMPC_shared:
Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_linear:
+ Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
+ ColonLoc, EndLoc);
+ break;
case OMPC_copyin:
Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_collapse:
case OMPC_default:
+ case OMPC_proc_bind:
case OMPC_threadprivate:
case OMPC_unknown:
- case NUM_OPENMP_CLAUSES:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -1021,25 +1114,23 @@
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
- I != E; ++I) {
- assert(*I && "NULL expr in OpenMP private clause.");
- if (isa<DependentScopeDeclRefExpr>(*I)) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP private clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
- Vars.push_back(*I);
+ Vars.push_back(RefExpr);
continue;
}
- SourceLocation ELoc = (*I)->getExprLoc();
+ SourceLocation ELoc = RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.9.3.3, Restrictions, p.1]
// A variable that is part of another variable (as an array or
// structure element) cannot appear in a private clause.
- DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
+ DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name)
- << (*I)->getSourceRange();
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
continue;
}
Decl *D = DE->getDecl();
@@ -1061,11 +1152,12 @@
}
if (Type->isReferenceType()) {
Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_private) << Type;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPClauseName(OMPC_private) << Type;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
continue;
}
@@ -1074,26 +1166,27 @@
// clause requires an accesible, unambiguous default constructor for the
// class type.
while (Type.getNonReferenceType()->isArrayType()) {
- Type = cast<ArrayType>(
- Type.getNonReferenceType().getTypePtr())->getElementType();
+ Type = cast<ArrayType>(Type.getNonReferenceType().getTypePtr())
+ ->getElementType();
}
- CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
- Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus
+ ? Type.getNonReferenceType()->getAsCXXRecordDecl()
+ : nullptr;
if (RD) {
CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (!CD ||
- CheckConstructorAccess(ELoc, CD,
- InitializedEntity::InitializeTemporary(Type),
- CD->getAccess(), PD) == AR_inaccessible ||
+ 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_private) << 0;
+ << getOpenMPClauseName(OMPC_private) << 0;
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -1105,11 +1198,12 @@
if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
DD->isDeleted()) {
Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_private) << 4;
+ << getOpenMPClauseName(OMPC_private) << 4;
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -1127,15 +1221,14 @@
// the variable's predetermined data-sharing attributes.
DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
- Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_private);
+ Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_private);
if (DVar.RefExpr) {
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
- << getOpenMPClauseName(DVar.CKind);
+ << getOpenMPClauseName(DVar.CKind);
} else {
Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
- << getOpenMPClauseName(DVar.CKind);
+ << getOpenMPClauseName(DVar.CKind);
}
continue;
}
@@ -1144,7 +1237,8 @@
Vars.push_back(DE);
}
- if (Vars.empty()) return 0;
+ if (Vars.empty())
+ return nullptr;
return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
@@ -1154,25 +1248,23 @@
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
- I != E; ++I) {
- assert(*I && "NULL expr in OpenMP firstprivate clause.");
- if (isa<DependentScopeDeclRefExpr>(*I)) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
- Vars.push_back(*I);
+ Vars.push_back(RefExpr);
continue;
}
- SourceLocation ELoc = (*I)->getExprLoc();
+ SourceLocation ELoc = RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.9.3.3, Restrictions, p.1]
// A variable that is part of another variable (as an array or
// structure element) cannot appear in a private clause.
- DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
+ DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name)
- << (*I)->getSourceRange();
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
continue;
}
Decl *D = DE->getDecl();
@@ -1194,11 +1286,12 @@
}
if (Type->isReferenceType()) {
Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_firstprivate) << Type;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPClauseName(OMPC_firstprivate) << Type;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
continue;
}
@@ -1207,23 +1300,24 @@
// clause requires an accesible, unambiguous copy constructor for the
// class type.
Type = Context.getBaseElementType(Type);
- CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
- Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus
+ ? Type.getNonReferenceType()->getAsCXXRecordDecl()
+ : nullptr;
if (RD) {
CXXConstructorDecl *CD = LookupCopyingConstructor(RD, 0);
PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (!CD ||
- CheckConstructorAccess(ELoc, CD,
- InitializedEntity::InitializeTemporary(Type),
- CD->getAccess(), PD) == AR_inaccessible ||
+ 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_firstprivate) << 1;
+ << getOpenMPClauseName(OMPC_firstprivate) << 1;
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -1235,11 +1329,12 @@
if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
DD->isDeleted()) {
Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_firstprivate) << 4;
+ << getOpenMPClauseName(OMPC_firstprivate) << 4;
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -1263,10 +1358,10 @@
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_firstprivate);
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_firstprivate);
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
- << getOpenMPClauseName(DVar.CKind);
+ << getOpenMPClauseName(DVar.CKind);
continue;
}
@@ -1284,10 +1379,10 @@
if (!(IsConstant || VD->isStaticDataMember()) && !DVar.RefExpr &&
DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_firstprivate);
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_firstprivate);
Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
- << getOpenMPClauseName(DVar.CKind);
+ << getOpenMPClauseName(DVar.CKind);
continue;
}
@@ -1314,7 +1409,8 @@
Vars.push_back(DE);
}
- if (Vars.empty()) return 0;
+ if (Vars.empty())
+ return nullptr;
return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
Vars);
@@ -1325,26 +1421,24 @@
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
- I != E; ++I) {
- assert(*I && "NULL expr in OpenMP shared clause.");
- if (isa<DependentScopeDeclRefExpr>(*I)) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
- Vars.push_back(*I);
+ Vars.push_back(RefExpr);
continue;
}
- SourceLocation ELoc = (*I)->getExprLoc();
+ SourceLocation ELoc = RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.14.3.2, Restrictions, p.1]
// A variable that is part of another variable (as an array or structure
// element) cannot appear in a shared unless it is a static data member
// of a C++ class.
- DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name)
- << (*I)->getSourceRange();
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
continue;
}
Decl *D = DE->getDecl();
@@ -1365,12 +1459,12 @@
// variable in a data-sharing attribute clause is allowed and overrides
// the variable's predetermined data-sharing attributes.
DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
- if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && DVar.RefExpr) {
- Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_shared);
+ if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
+ DVar.RefExpr) {
+ Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_shared);
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
- << getOpenMPClauseName(DVar.CKind);
+ << getOpenMPClauseName(DVar.CKind);
continue;
}
@@ -1378,34 +1472,161 @@
Vars.push_back(DE);
}
- if (Vars.empty()) return 0;
+ if (Vars.empty())
+ return nullptr;
return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
+OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP linear clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ // OpenMP [2.14.3.7, linear clause]
+ // A list item that appears in a linear clause is subject to the private
+ // clause semantics described in Section 2.14.3.3 on page 159 except as
+ // noted. In addition, the value of the new list item on each iteration
+ // of the associated loop(s) corresponds to the value of the original
+ // list item before entering the construct plus the logical number of
+ // the iteration times linear-step.
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable name.
+ // OpenMP [2.14.3.3, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or
+ // structure element) cannot appear in a private clause.
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+ continue;
+ }
+
+ VarDecl *VD = cast<VarDecl>(DE->getDecl());
+
+ // OpenMP [2.14.3.7, linear clause]
+ // A list-item cannot appear in more than one linear clause.
+ // A list-item that appears in a linear clause cannot appear in any
+ // other data-sharing attribute clause.
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ if (DVar.RefExpr) {
+ Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_linear);
+ Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
+ << getOpenMPClauseName(DVar.CKind);
+ continue;
+ }
+
+ QualType QType = VD->getType();
+ if (QType->isDependentType() || QType->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // A variable must not have an incomplete type or a reference type.
+ if (RequireCompleteType(ELoc, QType,
+ diag::err_omp_linear_incomplete_type)) {
+ continue;
+ }
+ if (QType->isReferenceType()) {
+ Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+ << getOpenMPClauseName(OMPC_linear) << QType;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ // A list item must not be const-qualified.
+ if (QType.isConstant(Context)) {
+ Diag(ELoc, diag::err_omp_const_variable)
+ << getOpenMPClauseName(OMPC_linear);
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ // A list item must be of integral or pointer type.
+ QType = QType.getUnqualifiedType().getCanonicalType();
+ const Type *Ty = QType.getTypePtrOrNull();
+ if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
+ !Ty->isPointerType())) {
+ Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_linear);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ Expr *StepExpr = Step;
+ if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
+ !Step->isInstantiationDependent() &&
+ !Step->containsUnexpandedParameterPack()) {
+ SourceLocation StepLoc = Step->getLocStart();
+ ExprResult Val = PerformImplicitIntegerConversion(StepLoc, Step);
+ if (Val.isInvalid())
+ return nullptr;
+ StepExpr = Val.take();
+
+ // Warn about zero linear step (it would be probably better specified as
+ // making corresponding variables 'const').
+ llvm::APSInt Result;
+ if (StepExpr->isIntegerConstantExpr(Result, Context) &&
+ !Result.isNegative() && !Result.isStrictlyPositive())
+ Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0]
+ << (Vars.size() > 1);
+ }
+
+ return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc,
+ Vars, StepExpr);
+}
+
OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
- I != E; ++I) {
- assert(*I && "NULL expr in OpenMP copyin clause.");
- if (isa<DependentScopeDeclRefExpr>(*I)) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP copyin clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
- Vars.push_back(*I);
+ Vars.push_back(RefExpr);
continue;
}
- SourceLocation ELoc = (*I)->getExprLoc();
+ SourceLocation ELoc = RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.14.4.1, Restrictions, p.1]
// A list item that appears in a copyin clause must be threadprivate.
- DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name)
- << (*I)->getSourceRange();
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
continue;
}
@@ -1423,8 +1644,8 @@
// A list item that appears in a copyin clause must be threadprivate.
if (!DSAStack->isThreadPrivate(VD)) {
Diag(ELoc, diag::err_omp_required_access)
- << getOpenMPClauseName(OMPC_copyin)
- << getOpenMPDirectiveName(OMPD_threadprivate);
+ << getOpenMPClauseName(OMPC_copyin)
+ << getOpenMPDirectiveName(OMPD_threadprivate);
continue;
}
@@ -1433,20 +1654,20 @@
// copyin clause requires an accesible, unambiguous copy assignment
// operator for the class type.
Type = Context.getBaseElementType(Type);
- CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
- Type->getAsCXXRecordDecl() : 0;
+ CXXRecordDecl *RD =
+ getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
if (RD) {
CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
- if (!MD ||
- CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
+ if (!MD || CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
MD->isDeleted()) {
Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_copyin) << 2;
+ << 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(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -1458,7 +1679,8 @@
Vars.push_back(DE);
}
- if (Vars.empty()) return 0;
+ if (Vars.empty())
+ return nullptr;
return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index ee1feb5..147325b 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -20,9 +20,9 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaInternal.h"
@@ -33,6 +33,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include <algorithm>
+#include <cstdlib>
namespace clang {
using namespace sema;
@@ -215,7 +216,7 @@
BindsToRvalue = false;
BindsImplicitObjectArgumentWithoutRefQualifier = false;
ObjCLifetimeConversionBinding = false;
- CopyConstructor = 0;
+ CopyConstructor = nullptr;
}
/// getRank - Retrieve the rank of this standard conversion sequence
@@ -573,7 +574,7 @@
DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
- Result.Data = 0;
+ Result.Data = nullptr;
switch (TDK) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
@@ -644,12 +645,12 @@
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
// FIXME: Destroy the data?
- Data = 0;
+ Data = nullptr;
break;
case Sema::TDK_SubstitutionFailure:
// FIXME: Destroy the template argument list?
- Data = 0;
+ Data = nullptr;
if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) {
Diag->~PartialDiagnosticAt();
HasDiagnostic = false;
@@ -665,7 +666,7 @@
PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() {
if (HasDiagnostic)
return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic));
- return 0;
+ return nullptr;
}
TemplateParameter DeductionFailureInfo::getTemplateParameter() {
@@ -709,7 +710,7 @@
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
- return 0;
+ return nullptr;
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
@@ -719,7 +720,7 @@
break;
}
- return 0;
+ return nullptr;
}
const TemplateArgument *DeductionFailureInfo::getFirstArg() {
@@ -733,7 +734,7 @@
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
- return 0;
+ return nullptr;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
@@ -745,7 +746,7 @@
break;
}
- return 0;
+ return nullptr;
}
const TemplateArgument *DeductionFailureInfo::getSecondArg() {
@@ -759,7 +760,7 @@
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
- return 0;
+ return nullptr;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
@@ -771,7 +772,7 @@
break;
}
- return 0;
+ return nullptr;
}
Expr *DeductionFailureInfo::getExpr() {
@@ -779,7 +780,7 @@
Sema::TDK_FailedOverloadResolution)
return static_cast<Expr*>(Data);
- return 0;
+ return nullptr;
}
void OverloadCandidateSet::destroyCandidates() {
@@ -829,8 +830,9 @@
/// without this, they will be immediately diagnosed as errors
///
/// Return true on unrecoverable error.
-static bool checkPlaceholderForOverload(Sema &S, Expr *&E,
- UnbridgedCastsSet *unbridgedCasts = 0) {
+static bool
+checkPlaceholderForOverload(Sema &S, Expr *&E,
+ UnbridgedCastsSet *unbridgedCasts = nullptr) {
if (const BuiltinType *placeholder = E->getType()->getAsPlaceholderType()) {
// We can't handle overloaded expressions here because overload
// resolution might reasonably tweak them.
@@ -982,7 +984,7 @@
// C++ [temp.fct]p2:
// A function template can be overloaded with other function templates
// and with normal (non-template) functions.
- if ((OldTemplate == 0) != (NewTemplate == 0))
+ if ((OldTemplate == nullptr) != (NewTemplate == nullptr))
return true;
// Is the function New an overload of the function Old?
@@ -1127,7 +1129,8 @@
}
// Attempt user-defined conversion.
- OverloadCandidateSet Conversions(From->getExprLoc());
+ OverloadCandidateSet Conversions(From->getExprLoc(),
+ OverloadCandidateSet::CSK_Normal);
OverloadingResult UserDefResult
= IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
AllowExplicit, AllowObjCConversionOnExplicit);
@@ -1254,7 +1257,7 @@
// copy/move constructor, since overloading just assumes that it
// exists. When we actually perform initialization, we'll find the
// appropriate constructor to copy the returned object, if needed.
- ICS.Standard.CopyConstructor = 0;
+ ICS.Standard.CopyConstructor = nullptr;
// Determine whether this is considered a derived-to-base conversion.
if (!S.Context.hasSameUnqualifiedType(FromType, ToType))
@@ -1436,7 +1439,7 @@
SCS.setAsIdentityConversion();
SCS.IncompatibleObjC = false;
SCS.setFromType(FromType);
- SCS.CopyConstructor = 0;
+ SCS.CopyConstructor = nullptr;
// There are no standard conversions for class types in C++, so
// abort early. When overloading in C, however, we do permit
@@ -1920,7 +1923,7 @@
return IsFloatingPointPromotion(FromComplex->getElementType(),
ToComplex->getElementType()) ||
- IsIntegralPromotion(0, FromComplex->getElementType(),
+ IsIntegralPromotion(nullptr, FromComplex->getElementType(),
ToComplex->getElementType());
}
@@ -2524,7 +2527,7 @@
if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) {
const MemberPointerType *FromMember = FromType->getAs<MemberPointerType>(),
*ToMember = ToType->getAs<MemberPointerType>();
- if (FromMember->getClass() != ToMember->getClass()) {
+ if (!Context.hasSameType(FromMember->getClass(), ToMember->getClass())) {
PDiag << ft_different_class << QualType(ToMember->getClass(), 0)
<< QualType(FromMember->getClass(), 0);
return;
@@ -2948,7 +2951,7 @@
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
@@ -2967,7 +2970,7 @@
isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType);
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
From, CandidateSet,
SuppressUserConversions);
else
@@ -3083,7 +3086,7 @@
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
@@ -3110,7 +3113,7 @@
}
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions);
else
@@ -3244,7 +3247,8 @@
bool
Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
- OverloadCandidateSet CandidateSet(From->getExprLoc());
+ OverloadCandidateSet CandidateSet(From->getExprLoc(),
+ OverloadCandidateSet::CSK_Normal);
OverloadingResult OvResult =
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
CandidateSet, false, false);
@@ -4071,7 +4075,7 @@
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
- OverloadCandidateSet CandidateSet(DeclLoc);
+ OverloadCandidateSet CandidateSet(DeclLoc, OverloadCandidateSet::CSK_Normal);
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator>
Conversions = T2RecordDecl->getVisibleConversionFunctions();
@@ -4262,7 +4266,7 @@
ICS.Standard.BindsToRvalue = false;
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
- ICS.Standard.CopyConstructor = 0;
+ ICS.Standard.CopyConstructor = nullptr;
ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
// Nothing more to do: the inaccessibility/ambiguity check for
@@ -4337,7 +4341,7 @@
ICS.Standard.BindsToRvalue = InitCategory.isRValue();
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
- ICS.Standard.CopyConstructor = 0;
+ ICS.Standard.CopyConstructor = nullptr;
ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
return ICS;
}
@@ -4563,7 +4567,7 @@
Result.UserDefined.After.setAsIdentityConversion();
Result.UserDefined.After.setFromType(ToType);
Result.UserDefined.After.setAllToTypes(ToType);
- Result.UserDefined.ConversionFunction = 0;
+ Result.UserDefined.ConversionFunction = nullptr;
}
return Result;
}
@@ -4992,7 +4996,7 @@
/*InOverloadResolution=*/false,
/*CStyle=*/false,
/*AllowObjcWritebackConversion=*/false);
- StandardConversionSequence *SCS = 0;
+ StandardConversionSequence *SCS = nullptr;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
if (!CheckConvertedConstantConversions(*this, ICS.Standard))
@@ -5185,7 +5189,7 @@
<< FixItHint::CreateInsertion(From->getLocStart(),
"static_cast<" + TypeStr + ">(")
<< FixItHint::CreateInsertion(
- SemaRef.PP.getLocForEndOfToken(From->getLocEnd()), ")");
+ SemaRef.getLocForEndOfToken(From->getLocEnd()), ")");
Converter.noteExplicitConv(SemaRef, Conversion, ConvTy);
// If we aren't in a SFINAE context, build a call to the
@@ -5193,15 +5197,15 @@
if (SemaRef.isSFINAEContext())
return true;
- SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+ SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, nullptr, Found);
ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion,
HadMultipleCandidates);
if (Result.isInvalid())
return true;
// Record usage of conversion in an implicit cast.
From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
- CK_UserDefinedConversion, Result.get(), 0,
- Result.get()->getValueKind());
+ CK_UserDefinedConversion, Result.get(),
+ nullptr, Result.get()->getValueKind());
}
return false;
}
@@ -5212,7 +5216,7 @@
DeclAccessPair &Found) {
CXXConversionDecl *Conversion =
cast<CXXConversionDecl>(Found->getUnderlyingDecl());
- SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+ SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, nullptr, Found);
QualType ToType = Conversion->getConversionType().getNonReferenceType();
if (!Converter.SuppressConversion) {
@@ -5229,8 +5233,8 @@
return true;
// Record usage of conversion in an implicit cast.
From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
- CK_UserDefinedConversion, Result.get(), 0,
- Result.get()->getValueKind());
+ CK_UserDefinedConversion, Result.get(),
+ nullptr, Result.get()->getValueKind());
return false;
}
@@ -5419,7 +5423,7 @@
// If one unique T is found:
// First, build a candidate set from the previously recorded
// potentially viable conversions.
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
collectViableConversionCandidates(*this, From, ToType, ViableConversions,
CandidateSet);
@@ -5476,6 +5480,45 @@
return finishContextualImplicitConversion(*this, Loc, From, Converter);
}
+/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
+/// an acceptable non-member overloaded operator for a call whose
+/// arguments have types T1 (and, if non-empty, T2). This routine
+/// implements the check in C++ [over.match.oper]p3b2 concerning
+/// enumeration types.
+static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context,
+ FunctionDecl *Fn,
+ ArrayRef<Expr *> Args) {
+ QualType T1 = Args[0]->getType();
+ QualType T2 = Args.size() > 1 ? Args[1]->getType() : QualType();
+
+ if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
+ return true;
+
+ if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
+ return true;
+
+ const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
+ if (Proto->getNumParams() < 1)
+ return false;
+
+ if (T1->isEnumeralType()) {
+ QualType ArgType = Proto->getParamType(0).getNonReferenceType();
+ if (Context.hasSameUnqualifiedType(T1, ArgType))
+ return true;
+ }
+
+ if (Proto->getNumParams() < 2)
+ return false;
+
+ if (!T2.isNull() && T2->isEnumeralType()) {
+ QualType ArgType = Proto->getParamType(1).getNonReferenceType();
+ if (Context.hasSameUnqualifiedType(T2, ArgType))
+ return true;
+ }
+
+ return false;
+}
+
/// AddOverloadCandidate - Adds the given function to the set of
/// candidate functions, using the given function call arguments. If
/// @p SuppressUserConversions, then don't allow user-defined
@@ -5519,6 +5562,17 @@
if (!CandidateSet.isNewCandidate(Function))
return;
+ // C++ [over.match.oper]p3:
+ // if no operand has a class type, only those non-member functions in the
+ // lookup set that have a first parameter of type T1 or "reference to
+ // (possibly cv-qualified) T1", when T1 is an enumeration type, or (if there
+ // is a right operand) a second parameter of type T2 or "reference to
+ // (possibly cv-qualified) T2", when T2 is an enumeration type, are
+ // candidate functions.
+ if (CandidateSet.getKind() == OverloadCandidateSet::CSK_Operator &&
+ !IsAcceptableNonMemberOperatorCandidate(Context, Function, Args))
+ return;
+
// C++11 [class.copy]p11: [DR1402]
// A defaulted move constructor that is defined as deleted is ignored by
// overload resolution.
@@ -5629,12 +5683,12 @@
// FIXME: specific_attr_iterator<EnableIfAttr> iterates in reverse order, but
// we need to find the first failing one.
if (!Function->hasAttrs())
- return 0;
+ return nullptr;
AttrVec Attrs = Function->getAttrs();
AttrVec::iterator E = std::remove_if(Attrs.begin(), Attrs.end(),
IsNotEnableIfAttr);
if (Attrs.begin() == E)
- return 0;
+ return nullptr;
std::reverse(Attrs.begin(), E);
SFINAETrap Trap(*this);
@@ -5648,7 +5702,7 @@
!isa<CXXConstructorDecl>(Function)) {
CXXMethodDecl *Method = cast<CXXMethodDecl>(Function);
ExprResult R =
- PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr,
Method, Method);
if (R.isInvalid()) {
InitializationFailed = true;
@@ -5684,7 +5738,7 @@
return EIA;
}
}
- return 0;
+ return nullptr;
}
/// \brief Add all of the function declarations in the given function set to
@@ -5742,7 +5796,7 @@
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
ObjectType, ObjectClassification,
Args, CandidateSet,
SuppressUserConversions);
@@ -5899,7 +5953,7 @@
// function template are combined with the set of non-template candidate
// functions.
TemplateDeductionInfo Info(CandidateSet.getLocation());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args,
Specialization, Info)) {
@@ -5949,7 +6003,7 @@
// function template are combined with the set of non-template candidate
// functions.
TemplateDeductionInfo Info(CandidateSet.getLocation());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args,
Specialization, Info)) {
@@ -6199,7 +6253,7 @@
return;
TemplateDeductionInfo Info(CandidateSet.getLocation());
- CXXConversionDecl *Specialization = 0;
+ CXXConversionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ToType,
Specialization, Info)) {
@@ -6243,7 +6297,7 @@
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
Candidate.FoundDecl = FoundDecl;
- Candidate.Function = 0;
+ Candidate.Function = nullptr;
Candidate.Surrogate = Conversion;
Candidate.Viable = true;
Candidate.IsSurrogate = true;
@@ -6403,8 +6457,8 @@
// Add this candidate
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
- Candidate.FoundDecl = DeclAccessPair::make(0, AS_none);
- Candidate.Function = 0;
+ Candidate.FoundDecl = DeclAccessPair::make(nullptr, AS_none);
+ Candidate.Function = nullptr;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.BuiltinTypes.ResultTy = ResultTy;
@@ -8084,7 +8138,7 @@
/// candidate set (C++ [basic.lookup.argdep]).
void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
- bool Operator, SourceLocation Loc,
+ SourceLocation Loc,
ArrayRef<Expr *> Args,
TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
@@ -8099,7 +8153,7 @@
// we supposed to consider on ADL candidates, anyway?
// FIXME: Pass in the explicit template arguments?
- ArgumentDependentLookup(Name, Operator, Loc, Args, Fns);
+ ArgumentDependentLookup(Name, Loc, Args, Fns);
// Erase all of the candidates we already knew about.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
@@ -8184,29 +8238,6 @@
if (HasBetterConversion)
return true;
- // - F1 is a non-template function and F2 is a function template
- // specialization, or, if not that,
- if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) &&
- Cand2.Function && Cand2.Function->getPrimaryTemplate())
- return true;
-
- // -- F1 and F2 are function template specializations, and the function
- // template for F1 is more specialized than the template for F2
- // according to the partial ordering rules described in 14.5.5.2, or,
- // if not that,
- if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
- Cand2.Function && Cand2.Function->getPrimaryTemplate()) {
- if (FunctionTemplateDecl *BetterTemplate
- = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
- Cand2.Function->getPrimaryTemplate(),
- Loc,
- isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
- : TPOC_Call,
- Cand1.ExplicitCallArguments,
- Cand2.ExplicitCallArguments))
- return BetterTemplate == Cand1.Function->getPrimaryTemplate();
- }
-
// -- the context is an initialization by user-defined conversion
// (see 8.5, 13.3.1.5) and the standard conversion sequence
// from the return type of F1 to the destination type (i.e.,
@@ -8220,26 +8251,44 @@
// other. This only distinguishes the results in non-standard, extension
// cases such as the conversion from a lambda closure type to a function
// pointer or block.
- ImplicitConversionSequence::CompareKind FuncResult
- = compareConversionFunctions(S, Cand1.Function, Cand2.Function);
- if (FuncResult != ImplicitConversionSequence::Indistinguishable)
- return FuncResult;
-
- switch (CompareStandardConversionSequences(S,
- Cand1.FinalConversion,
- Cand2.FinalConversion)) {
- case ImplicitConversionSequence::Better:
- // Cand1 has a better conversion sequence.
- return true;
+ ImplicitConversionSequence::CompareKind Result =
+ compareConversionFunctions(S, Cand1.Function, Cand2.Function);
+ if (Result == ImplicitConversionSequence::Indistinguishable)
+ Result = CompareStandardConversionSequences(S,
+ Cand1.FinalConversion,
+ Cand2.FinalConversion);
- case ImplicitConversionSequence::Worse:
- // Cand1 can't be better than Cand2.
- return false;
+ if (Result != ImplicitConversionSequence::Indistinguishable)
+ return Result == ImplicitConversionSequence::Better;
- case ImplicitConversionSequence::Indistinguishable:
- // Do nothing
- break;
- }
+ // FIXME: Compare kind of reference binding if conversion functions
+ // convert to a reference type used in direct reference binding, per
+ // C++14 [over.match.best]p1 section 2 bullet 3.
+ }
+
+ // -- F1 is a non-template function and F2 is a function template
+ // specialization, or, if not that,
+ bool Cand1IsSpecialization = Cand1.Function &&
+ Cand1.Function->getPrimaryTemplate();
+ bool Cand2IsSpecialization = Cand2.Function &&
+ Cand2.Function->getPrimaryTemplate();
+ if (Cand1IsSpecialization != Cand2IsSpecialization)
+ return Cand2IsSpecialization;
+
+ // -- F1 and F2 are function template specializations, and the function
+ // template for F1 is more specialized than the template for F2
+ // according to the partial ordering rules described in 14.5.5.2, or,
+ // if not that,
+ if (Cand1IsSpecialization && Cand2IsSpecialization) {
+ if (FunctionTemplateDecl *BetterTemplate
+ = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
+ Cand2.Function->getPrimaryTemplate(),
+ Loc,
+ isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
+ : TPOC_Call,
+ Cand1.ExplicitCallArguments,
+ Cand2.ExplicitCallArguments))
+ return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
// Check for enable_if value-based overload resolution.
@@ -8250,37 +8299,41 @@
// specific_attr_iterator<EnableIfAttr> but going in declaration order,
// instead of reverse order which is how they're stored in the AST.
AttrVec Cand1Attrs;
- AttrVec::iterator Cand1E = Cand1Attrs.end();
if (Cand1.Function->hasAttrs()) {
Cand1Attrs = Cand1.Function->getAttrs();
- Cand1E = std::remove_if(Cand1Attrs.begin(), Cand1Attrs.end(),
- IsNotEnableIfAttr);
- std::reverse(Cand1Attrs.begin(), Cand1E);
+ Cand1Attrs.erase(std::remove_if(Cand1Attrs.begin(), Cand1Attrs.end(),
+ IsNotEnableIfAttr),
+ Cand1Attrs.end());
+ std::reverse(Cand1Attrs.begin(), Cand1Attrs.end());
}
AttrVec Cand2Attrs;
- AttrVec::iterator Cand2E = Cand2Attrs.end();
if (Cand2.Function->hasAttrs()) {
Cand2Attrs = Cand2.Function->getAttrs();
- Cand2E = std::remove_if(Cand2Attrs.begin(), Cand2Attrs.end(),
- IsNotEnableIfAttr);
- std::reverse(Cand2Attrs.begin(), Cand2E);
+ Cand2Attrs.erase(std::remove_if(Cand2Attrs.begin(), Cand2Attrs.end(),
+ IsNotEnableIfAttr),
+ Cand2Attrs.end());
+ std::reverse(Cand2Attrs.begin(), Cand2Attrs.end());
}
- for (AttrVec::iterator
- Cand1I = Cand1Attrs.begin(), Cand2I = Cand2Attrs.begin();
- Cand1I != Cand1E || Cand2I != Cand2E; ++Cand1I, ++Cand2I) {
- if (Cand1I == Cand1E)
- return false;
- if (Cand2I == Cand2E)
- return true;
+
+ // Candidate 1 is better if it has strictly more attributes and
+ // the common sequence is identical.
+ if (Cand1Attrs.size() <= Cand2Attrs.size())
+ return false;
+
+ auto Cand1I = Cand1Attrs.begin();
+ for (auto &Cand2A : Cand2Attrs) {
+ auto &Cand1A = *Cand1I++;
llvm::FoldingSetNodeID Cand1ID, Cand2ID;
- cast<EnableIfAttr>(*Cand1I)->getCond()->Profile(Cand1ID,
- S.getASTContext(), true);
- cast<EnableIfAttr>(*Cand2I)->getCond()->Profile(Cand2ID,
- S.getASTContext(), true);
+ cast<EnableIfAttr>(Cand1A)->getCond()->Profile(Cand1ID,
+ S.getASTContext(), true);
+ cast<EnableIfAttr>(Cand2A)->getCond()->Profile(Cand2ID,
+ S.getASTContext(), true);
if (Cand1ID != Cand2ID)
return false;
}
+
+ return true;
}
return false;
@@ -8750,12 +8803,12 @@
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
- << Fn->getParamDecl(0) << NumFormalArgs;
+ << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
+ << mode << Fn->getParamDecl(0) << NumFormalArgs;
else
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
- << modeCount << NumFormalArgs;
+ << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
+ << mode << modeCount << NumFormalArgs;
MaybeEmitInheritedConstructorNote(S, Fn);
}
@@ -9177,7 +9230,10 @@
struct CompareOverloadCandidatesForDisplay {
Sema &S;
- CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {}
+ size_t NumArgs;
+
+ CompareOverloadCandidatesForDisplay(Sema &S, size_t nArgs)
+ : S(S), NumArgs(nArgs) {}
bool operator()(const OverloadCandidate *L,
const OverloadCandidate *R) {
@@ -9202,8 +9258,24 @@
if (!L->Viable) {
// 1. Arity mismatches come after other candidates.
if (L->FailureKind == ovl_fail_too_many_arguments ||
- L->FailureKind == ovl_fail_too_few_arguments)
+ L->FailureKind == ovl_fail_too_few_arguments) {
+ if (R->FailureKind == ovl_fail_too_many_arguments ||
+ R->FailureKind == ovl_fail_too_few_arguments) {
+ int LDist = std::abs((int)L->getNumParams() - (int)NumArgs);
+ int RDist = std::abs((int)R->getNumParams() - (int)NumArgs);
+ if (LDist == RDist) {
+ if (L->FailureKind == R->FailureKind)
+ // Sort non-surrogates before surrogates.
+ return !L->IsSurrogate && R->IsSurrogate;
+ // Sort candidates requiring fewer parameters than there were
+ // arguments given after candidates requiring more parameters
+ // than there were arguments given.
+ return L->FailureKind == ovl_fail_too_many_arguments;
+ }
+ return LDist < RDist;
+ }
return false;
+ }
if (R->FailureKind == ovl_fail_too_many_arguments ||
R->FailureKind == ovl_fail_too_few_arguments)
return true;
@@ -9390,7 +9462,7 @@
}
std::sort(Cands.begin(), Cands.end(),
- CompareOverloadCandidatesForDisplay(S));
+ CompareOverloadCandidatesForDisplay(S, Args.size()));
bool ReportedAmbiguousConversions = false;
@@ -9671,7 +9743,7 @@
// resulting template argument list is used to generate a single
// function template specialization, which is added to the set of
// overloaded functions considered.
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (Sema::TemplateDeductionResult Result
= S.DeduceTemplateArguments(FunctionTemplate,
@@ -9807,7 +9879,7 @@
// [...] any function template specializations in the set are
// eliminated if the set also contains a non-template function, [...]
for (unsigned I = 0, N = Matches.size(); I != N; ) {
- if (Matches[I].second->getPrimaryTemplate() == 0)
+ if (Matches[I].second->getPrimaryTemplate() == nullptr)
++I;
else {
Matches[I] = Matches[--N];
@@ -9879,12 +9951,12 @@
int getNumMatches() const { return Matches.size(); }
FunctionDecl* getMatchingFunctionDecl() const {
- if (Matches.size() != 1) return 0;
+ if (Matches.size() != 1) return nullptr;
return Matches[0].second;
}
const DeclAccessPair* getMatchingFunctionAccessPair() const {
- if (Matches.size() != 1) return 0;
+ if (Matches.size() != 1) return nullptr;
return &Matches[0].first;
}
};
@@ -9915,7 +9987,7 @@
AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType,
Complain);
int NumMatches = Resolver.getNumMatches();
- FunctionDecl* Fn = 0;
+ FunctionDecl *Fn = nullptr;
if (NumMatches == 0 && Complain) {
if (Resolver.IsInvalidFormOfPointerToMemberFunction())
Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
@@ -9964,7 +10036,7 @@
// If we didn't actually find any template-ids, we're done.
if (!ovl->hasExplicitTemplateArgs())
- return 0;
+ return nullptr;
TemplateArgumentListInfo ExplicitTemplateArgs;
ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
@@ -9972,7 +10044,7 @@
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
- FunctionDecl *Matched = 0;
+ FunctionDecl *Matched = nullptr;
for (UnresolvedSetIterator I = ovl->decls_begin(),
E = ovl->decls_end(); I != E; ++I) {
// C++0x [temp.arg.explicit]p3:
@@ -9990,7 +10062,7 @@
// resulting template argument list is used to generate a single
// function template specialization, which is added to the set of
// overloaded functions considered.
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
@@ -10013,7 +10085,7 @@
<< ovl->getName();
NoteAllOverloadCandidates(ovl);
}
- return 0;
+ return nullptr;
}
Matched = Specialization;
@@ -10023,7 +10095,7 @@
if (Matched && getLangOpts().CPlusPlus1y &&
Matched->getReturnType()->isUndeducedType() &&
DeduceReturnType(Matched, ovl->getExprLoc(), Complain))
- return 0;
+ return nullptr;
return Matched;
}
@@ -10184,7 +10256,7 @@
// It would be nice to avoid this copy.
TemplateArgumentListInfo TABuffer;
- TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TABuffer);
ExplicitTemplateArgs = &TABuffer;
@@ -10197,8 +10269,7 @@
/*KnownValid*/ true);
if (ULE->requiresADL())
- AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false,
- ULE->getExprLoc(),
+ AddArgumentDependentLookupCandidates(ULE->getName(), ULE->getExprLoc(),
Args, ExplicitTemplateArgs,
CandidateSet, PartialOverloading);
}
@@ -10225,6 +10296,7 @@
static bool
DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
const CXXScopeSpec &SS, LookupResult &R,
+ OverloadCandidateSet::CandidateSetKind CSK,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args) {
if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty())
@@ -10246,7 +10318,7 @@
return false;
}
- OverloadCandidateSet Candidates(FnLoc);
+ OverloadCandidateSet Candidates(FnLoc, CSK);
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
AddOverloadedCallCandidate(SemaRef, I.getPair(),
ExplicitTemplateArgs, Args,
@@ -10330,7 +10402,8 @@
SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName);
return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R,
- /*ExplicitTemplateArgs=*/0, Args);
+ OverloadCandidateSet::CSK_Operator,
+ /*ExplicitTemplateArgs=*/nullptr, Args);
}
namespace {
@@ -10374,7 +10447,7 @@
SourceLocation TemplateKWLoc = ULE->getTemplateKeywordLoc();
TemplateArgumentListInfo TABuffer;
- TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TABuffer);
ExplicitTemplateArgs = &TABuffer;
@@ -10383,12 +10456,14 @@
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
FunctionCallFilterCCC Validator(SemaRef, Args.size(),
- ExplicitTemplateArgs != 0, false);
+ ExplicitTemplateArgs != nullptr,
+ dyn_cast<MemberExpr>(Fn));
NoTypoCorrectionCCC RejectAll;
CorrectionCandidateCallback *CCC = AllowTypoCorrection ?
(CorrectionCandidateCallback*)&Validator :
(CorrectionCandidateCallback*)&RejectAll;
if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
+ OverloadCandidateSet::CSK_Normal,
ExplicitTemplateArgs, Args) &&
(!EmptyLookup ||
SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC,
@@ -10415,7 +10490,7 @@
// This shouldn't cause an infinite loop because we're giving it
// an expression with viable lookup results, which should never
// end up here.
- return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc,
+ return SemaRef.ActOnCallExpr(/*Scope*/ nullptr, NewFn.take(), LParenLoc,
MultiExprArg(Args.data(), Args.size()),
RParenLoc);
}
@@ -10567,7 +10642,8 @@
SourceLocation RParenLoc,
Expr *ExecConfig,
bool AllowTypoCorrection) {
- OverloadCandidateSet CandidateSet(Fn->getExprLoc());
+ OverloadCandidateSet CandidateSet(Fn->getExprLoc(),
+ OverloadCandidateSet::CSK_Normal);
ExprResult result;
if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet,
@@ -10620,7 +10696,7 @@
if (checkPlaceholderForOverload(*this, Input))
return ExprError();
- Expr *Args[2] = { Input, 0 };
+ Expr *Args[2] = { Input, nullptr };
unsigned NumArgs = 1;
// For post-increment and post-decrement, add the implicit '0' as
@@ -10643,7 +10719,7 @@
VK_RValue, OK_Ordinary,
OpLoc));
- CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, NamingClass,
NestedNameSpecifierLoc(), OpNameInfo,
@@ -10656,7 +10732,7 @@
}
// Build an empty overload set.
- OverloadCandidateSet CandidateSet(OpLoc);
+ OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator);
// Add the candidates from the given function set.
AddFunctionCandidates(Fns, ArgsArray, CandidateSet, false);
@@ -10665,8 +10741,8 @@
AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet);
// Add candidates from ADL.
- AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, OpLoc,
- ArgsArray, /*ExplicitTemplateArgs*/ 0,
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray,
+ /*ExplicitTemplateArgs*/nullptr,
CandidateSet);
// Add builtin operator candidates.
@@ -10687,10 +10763,10 @@
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
- CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(OpLoc, Args[0], nullptr, Best->FoundDecl);
ExprResult InputRes =
- PerformObjectArgumentInitialization(Input, /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Input, /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (InputRes.isInvalid())
return ExprError();
@@ -10803,7 +10879,7 @@
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS) {
Expr *Args[2] = { LHS, RHS };
- LHS=RHS=0; //Please use only Args instead of LHS/RHS couple
+ LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple
BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
@@ -10833,7 +10909,7 @@
}
// FIXME: save results of ADL from here?
- CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
// TODO: provide better source location info in DNLoc component.
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
UnresolvedLookupExpr *Fn
@@ -10871,7 +10947,7 @@
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
// Build an empty overload set.
- OverloadCandidateSet CandidateSet(OpLoc);
+ OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator);
// Add the candidates from the given function set.
AddFunctionCandidates(Fns, Args, CandidateSet, false);
@@ -10880,9 +10956,8 @@
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
// Add candidates from ADL.
- AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
- OpLoc, Args,
- /*ExplicitTemplateArgs*/ 0,
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
+ /*ExplicitTemplateArgs*/ nullptr,
CandidateSet);
// Add builtin operator candidates.
@@ -10915,7 +10990,7 @@
return ExprError();
ExprResult Arg0 =
- PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
@@ -11081,7 +11156,7 @@
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
- CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
// CHECKME: no 'operator' keyword?
DeclarationNameInfo OpNameInfo(OpName, LLoc);
OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
@@ -11107,7 +11182,7 @@
return ExprError();
// Build an empty overload set.
- OverloadCandidateSet CandidateSet(LLoc);
+ OverloadCandidateSet CandidateSet(LLoc, OverloadCandidateSet::CSK_Operator);
// Subscript can only be overloaded as a member function.
@@ -11135,7 +11210,7 @@
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
ExprResult Arg0 =
- PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
@@ -11294,10 +11369,10 @@
resultType, valueKind, RParenLoc);
if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getLocStart(),
- call, 0))
+ call, nullptr))
return ExprError();
- if (ConvertArgumentsForCall(call, op, 0, proto, Args, RParenLoc))
+ if (ConvertArgumentsForCall(call, op, nullptr, proto, Args, RParenLoc))
return ExprError();
if (CheckOtherCall(call, proto))
@@ -11311,9 +11386,9 @@
return ExprError();
MemberExpr *MemExpr;
- CXXMethodDecl *Method = 0;
- DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
- NestedNameSpecifier *Qualifier = 0;
+ CXXMethodDecl *Method = nullptr;
+ DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_public);
+ NestedNameSpecifier *Qualifier = nullptr;
if (isa<MemberExpr>(NakedMemExpr)) {
MemExpr = cast<MemberExpr>(NakedMemExpr);
Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
@@ -11330,10 +11405,11 @@
: UnresExpr->getBase()->Classify(Context);
// Add overload candidates
- OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc());
+ OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc(),
+ OverloadCandidateSet::CSK_Normal);
// FIXME: avoid copy.
- TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (UnresExpr->hasExplicitTemplateArgs()) {
UnresExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
@@ -11514,7 +11590,8 @@
// operators of T. The function call operators of T are obtained by
// ordinary lookup of the name operator() in the context of
// (E).operator().
- OverloadCandidateSet CandidateSet(LParenLoc);
+ OverloadCandidateSet CandidateSet(LParenLoc,
+ OverloadCandidateSet::CSK_Operator);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
if (RequireCompleteType(LParenLoc, Object.get()->getType(),
@@ -11627,14 +11704,15 @@
UnbridgedCasts.restore();
- if (Best->Function == 0) {
+ if (Best->Function == nullptr) {
// Since there is no function declaration, this is one of the
// surrogate candidates. Dig out the conversion function.
CXXConversionDecl *Conv
= cast<CXXConversionDecl>(
Best->Conversions[0].UserDefined.ConversionFunction);
- CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(LParenLoc, Object.get(), nullptr,
+ Best->FoundDecl);
if (DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc))
return ExprError();
assert(Conv == Best->FoundDecl.getDecl() &&
@@ -11652,12 +11730,12 @@
// Record usage of conversion in an implicit cast.
Call = Owned(ImplicitCastExpr::Create(Context, Call.get()->getType(),
CK_UserDefinedConversion,
- Call.get(), 0, VK_RValue));
+ Call.get(), nullptr, VK_RValue));
return ActOnCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc);
}
- CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(LParenLoc, Object.get(), nullptr, Best->FoundDecl);
// We found an overloaded operator(). Build a CXXOperatorCallExpr
// that calls this method, using Object for the implicit object
@@ -11713,7 +11791,7 @@
// Initialize the implicit object parameter.
ExprResult ObjRes =
- PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (ObjRes.isInvalid())
IsError = true;
@@ -11755,7 +11833,8 @@
if (Proto->isVariadic()) {
// Promote the arguments (C99 6.5.2.2p7).
for (unsigned i = NumParams, e = Args.size(); i < e; i++) {
- ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
+ ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
+ nullptr);
IsError |= Arg.isInvalid();
TheCall->setArg(i + 1, Arg.take());
}
@@ -11793,7 +11872,7 @@
// overload resolution mechanism (13.3).
DeclarationName OpName =
Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Operator);
const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
if (RequireCompleteType(Loc, Base->getType(),
@@ -11856,12 +11935,12 @@
return ExprError();
}
- CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(OpLoc, Base, nullptr, Best->FoundDecl);
// Convert the object parameter.
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
ExprResult BaseResult =
- PerformObjectArgumentInitialization(Base, /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Base, /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (BaseResult.isInvalid())
return ExprError();
@@ -11895,7 +11974,8 @@
TemplateArgumentListInfo *TemplateArgs) {
SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc();
- OverloadCandidateSet CandidateSet(UDSuffixLoc);
+ OverloadCandidateSet CandidateSet(UDSuffixLoc,
+ OverloadCandidateSet::CSK_Normal);
AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true,
TemplateArgs);
@@ -11953,7 +12033,7 @@
if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
- if (CheckFunctionCall(FD, UDL, NULL))
+ if (CheckFunctionCall(FD, UDL, nullptr))
return ExprError();
return MaybeBindToTemporary(UDL);
@@ -11980,16 +12060,16 @@
BuildMemberReferenceExpr(Range, Range->getType(), Loc,
/*IsPtr=*/false, CXXScopeSpec(),
/*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/0,
+ /*FirstQualifierInScope=*/nullptr,
MemberLookup,
- /*TemplateArgs=*/0);
+ /*TemplateArgs=*/nullptr);
if (MemberRef.isInvalid()) {
*CallExpr = ExprError();
Diag(Range->getLocStart(), diag::note_in_for_range)
<< RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
- *CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, None, Loc, 0);
+ *CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, None, Loc, nullptr);
if (CallExpr->isInvalid()) {
*CallExpr = ExprError();
Diag(Range->getLocStart(), diag::note_in_for_range)
@@ -11999,7 +12079,7 @@
} else {
UnresolvedSet<0> FoundNames;
UnresolvedLookupExpr *Fn =
- UnresolvedLookupExpr::Create(Context, /*NamingClass=*/0,
+ UnresolvedLookupExpr::Create(Context, /*NamingClass=*/nullptr,
NestedNameSpecifierLoc(), NameInfo,
/*NeedsADL=*/true, /*Overloaded=*/false,
FoundNames.begin(), FoundNames.end());
@@ -12019,7 +12099,7 @@
return FRS_NoViableFunction;
}
*CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, Range,
- Loc, 0, CandidateSet, &Best,
+ Loc, nullptr, CandidateSet, &Best,
OverloadResult,
/*AllowTypoCorrection=*/false);
if (CallExpr->isInvalid() || OverloadResult != OR_Success) {
@@ -12061,7 +12141,7 @@
return ImplicitCastExpr::Create(Context, ICE->getType(),
ICE->getCastKind(),
- SubExpr, 0,
+ SubExpr, nullptr,
ICE->getValueKind());
}
@@ -12112,7 +12192,7 @@
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
// FIXME: avoid copy.
- TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
@@ -12135,7 +12215,7 @@
if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
// FIXME: avoid copy.
- TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (MemExpr->hasExplicitTemplateArgs()) {
MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index de02fa9..94b1943 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -31,6 +31,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -267,7 +268,8 @@
public:
ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
- SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) {
+ SyntacticRefExpr(nullptr), InstanceReceiver(nullptr), Getter(nullptr),
+ Setter(nullptr) {
}
ExprResult buildRValueOperation(Expr *op);
@@ -306,9 +308,9 @@
ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
RefExpr(refExpr),
- InstanceBase(0), InstanceKey(0),
- AtIndexGetter(0), AtIndexSetter(0) { }
-
+ InstanceBase(nullptr), InstanceKey(nullptr),
+ AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
+
ExprResult buildRValueOperation(Expr *op);
ExprResult buildAssignmentOperation(Scope *Sc,
SourceLocation opLoc,
@@ -578,7 +580,7 @@
ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
- return (Getter != 0);
+ return (Getter != nullptr);
}
/// Try to find the most accurate setter declaration for the property
@@ -643,7 +645,7 @@
/// Capture the base object of an Objective-C property expression.
Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
- assert(InstanceReceiver == 0);
+ assert(InstanceReceiver == nullptr);
// If we have a base, capture it in an OVE and rebuild the syntactic
// form to use the OVE as its base.
@@ -681,7 +683,8 @@
// Build a message-send.
ExprResult msg;
- if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
+ if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
+ RefExpr->isObjectReceiver()) {
assert(InstanceReceiver || RefExpr->isSuperReceiver());
msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
GenericLoc, Getter->getSelector(),
@@ -750,7 +753,8 @@
// Build a message-send.
ExprResult msg;
- if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
+ if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
+ RefExpr->isObjectReceiver()) {
msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
GenericLoc, SetterSelector, Setter,
MultiExprArg(args, 1));
@@ -964,8 +968,8 @@
/// Capture the base object of an Objective-C Index'ed expression.
Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
- assert(InstanceBase == 0);
-
+ assert(InstanceBase == nullptr);
+
// Capture base expression in an OVE and rebuild the syntactic
// form to use the OVE as its base expression.
InstanceBase = capture(RefExpr->getBaseExpr());
@@ -1131,7 +1135,7 @@
AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
SourceLocation(), AtIndexGetterSelector,
S.Context.getObjCIdType() /*ReturnType*/,
- 0 /*TypeSourceInfo */,
+ nullptr /*TypeSourceInfo */,
S.Context.getTranslationUnitDecl(),
true /*Instance*/, false/*isVariadic*/,
/*isPropertyAccessor=*/false,
@@ -1144,9 +1148,9 @@
: &S.Context.Idents.get("key"),
arrayRef ? S.Context.UnsignedLongTy
: S.Context.getObjCIdType(),
- /*TInfo=*/0,
+ /*TInfo=*/nullptr,
SC_None,
- 0);
+ nullptr);
AtIndexGetter->setMethodParams(S.Context, Argument, None);
}
@@ -1240,7 +1244,7 @@
BaseT->isObjCQualifiedIdType());
if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
- TypeSourceInfo *ReturnTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = nullptr;
QualType ReturnType = S.Context.VoidTy;
AtIndexSetter = ObjCMethodDecl::Create(
S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,
@@ -1254,9 +1258,9 @@
SourceLocation(), SourceLocation(),
&S.Context.Idents.get("object"),
S.Context.getObjCIdType(),
- /*TInfo=*/0,
+ /*TInfo=*/nullptr,
SC_None,
- 0);
+ nullptr);
Params.push_back(object);
ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
SourceLocation(), SourceLocation(),
@@ -1264,9 +1268,9 @@
: &S.Context.Idents.get("key"),
arrayRef ? S.Context.UnsignedLongTy
: S.Context.getObjCIdType(),
- /*TInfo=*/0,
+ /*TInfo=*/nullptr,
SC_None,
- 0);
+ nullptr);
Params.push_back(key);
AtIndexSetter->setMethodParams(S.Context, Params, None);
}
@@ -1406,7 +1410,7 @@
ExprResult GetterExpr = S.ActOnMemberAccessExpr(
S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- GetterName, 0, true);
+ GetterName, nullptr, true);
if (GetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::error_cannot_find_suitable_accessor) << 0 /* getter */
@@ -1436,7 +1440,7 @@
ExprResult SetterExpr = S.ActOnMemberAccessExpr(
S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- SetterName, 0, true);
+ SetterName, nullptr, true);
if (SetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::error_cannot_find_suitable_accessor) << 1 /* setter */
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 2be5d5c..7d568ee 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -95,7 +95,7 @@
// foreach variables are never actually initialized in the way that
// the parser came up with.
- var->setInit(0);
+ var->setInit(nullptr);
// In ARC, we don't need to retain the iteration variable of a fast
// enumeration loop. Rather than actually trying to catch that
@@ -289,7 +289,7 @@
return;
}
- DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2);
+ DiagRuntimeBehavior(Loc, nullptr, PDiag(DiagID) << R1 << R2);
}
void Sema::ActOnStartOfCompoundStmt() {
@@ -351,7 +351,7 @@
Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
SourceLocation DotDotDotLoc, Expr *RHSVal,
SourceLocation ColonLoc) {
- assert((LHSVal != 0) && "missing expression in case statement");
+ assert(LHSVal && "missing expression in case statement");
if (getCurFunction()->SwitchStack.empty()) {
Diag(CaseLoc, diag::err_case_not_in_switch);
@@ -451,7 +451,7 @@
ExprResult CondResult(CondVal.release());
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
@@ -580,7 +580,7 @@
Decl *CondVar) {
ExprResult CondResult;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false);
@@ -702,6 +702,7 @@
assert(SS == getCurFunction()->SwitchStack.back() &&
"switch stack missing push/pop!");
+ if (!BodyStmt) return StmtError();
SS->setBody(BodyStmt, SwitchLoc);
getCurFunction()->SwitchStack.pop_back();
@@ -756,7 +757,7 @@
typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy;
CaseRangesTy CaseRanges;
- DefaultStmt *TheDefaultStmt = 0;
+ DefaultStmt *TheDefaultStmt = nullptr;
bool CaseListIsErroneous = false;
@@ -963,7 +964,7 @@
// Check to see whether the case range overlaps with any
// singleton cases.
- CaseStmt *OverlapStmt = 0;
+ CaseStmt *OverlapStmt = nullptr;
llvm::APSInt OverlapVal(32);
// Find the smallest value >= the lower bound. If I is in the
@@ -1141,8 +1142,9 @@
}
}
- DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt,
- diag::warn_empty_switch_body);
+ if (BodyStmt)
+ DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt,
+ diag::warn_empty_switch_body);
// FIXME: If the case list was broken is some way, we don't have a good system
// to patch it up. Instead, just return the whole substmt as broken.
@@ -1206,7 +1208,7 @@
Decl *CondVar, Stmt *Body) {
ExprResult CondResult(Cond.release());
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);
@@ -1597,8 +1599,8 @@
for (auto *DI : DS->decls()) {
VarDecl *VD = dyn_cast<VarDecl>(DI);
if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
- VD = 0;
- if (VD == 0) {
+ VD = nullptr;
+ if (!VD) {
Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
DI->setInvalidDecl();
}
@@ -1613,7 +1615,7 @@
CheckForRedundantIteration(*this, third.get(), Body);
ExprResult SecondResult(second.release());
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (secondVar) {
ConditionVar = cast<VarDecl>(secondVar);
SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);
@@ -1698,7 +1700,7 @@
};
Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);
- ObjCMethodDecl *method = 0;
+ ObjCMethodDecl *method = nullptr;
// If there's an interface, look in both the public and private APIs.
if (iface) {
@@ -1801,8 +1803,8 @@
return StmtError();
return Owned(new (Context) ObjCForCollectionStmt(First,
- CollectionExprResult.take(), 0,
- ForLoc, RParenLoc));
+ CollectionExprResult.take(),
+ nullptr, ForLoc, RParenLoc));
}
/// Finish building a variable declaration for a for-range statement.
@@ -1880,7 +1882,7 @@
static bool ObjCEnumerationCollection(Expr *Collection) {
return !Collection->isTypeDependent()
- && Collection->getType()->getAs<ObjCObjectPointerType>() != 0;
+ && Collection->getType()->getAs<ObjCObjectPointerType>() != nullptr;
}
/// ActOnCXXForRangeStmt - Check and build a C++11 for-range statement.
@@ -1948,8 +1950,8 @@
}
return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(),
- /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS,
- RParenLoc, Kind);
+ /*BeginEndDecl=*/nullptr, /*Cond=*/nullptr,
+ /*Inc=*/nullptr, DS, RParenLoc, Kind);
}
/// \brief Create the initialization, compare, and increment steps for
@@ -2194,7 +2196,8 @@
return StmtError();
}
} else {
- OverloadCandidateSet CandidateSet(RangeLoc);
+ OverloadCandidateSet CandidateSet(RangeLoc,
+ OverloadCandidateSet::CSK_Normal);
Sema::BeginEndFunction BEFFailure;
ForRangeStatus RangeStatus =
BuildNonArrayForRange(*this, S, BeginRangeRef.get(),
@@ -2332,8 +2335,8 @@
return Owned(new (Context) CXXForRangeStmt(RangeDS,
cast_or_null<DeclStmt>(BeginEndDecl.get()),
NotEqExpr.take(), IncrExpr.take(),
- LoopVarDS, /*Body=*/0, ForLoc,
- ColonLoc, RParenLoc));
+ LoopVarDS, /*Body=*/nullptr,
+ ForLoc, ColonLoc, RParenLoc));
}
/// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach
@@ -2442,52 +2445,62 @@
///
/// \returns The NRVO candidate variable, if the return statement may use the
/// NRVO, or NULL if there is no such candidate.
-const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType,
- Expr *E,
- bool AllowFunctionParameter) {
- QualType ExprType = E->getType();
+VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType,
+ Expr *E,
+ bool AllowFunctionParameter) {
+ if (!getLangOpts().CPlusPlus)
+ return nullptr;
+
+ // - in a return statement in a function [where] ...
+ // ... the expression is the name of a non-volatile automatic object ...
+ DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
+ if (!DR || DR->refersToEnclosingLocal())
+ return nullptr;
+ VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return nullptr;
+
+ if (isCopyElisionCandidate(ReturnType, VD, AllowFunctionParameter))
+ return VD;
+ return nullptr;
+}
+
+bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
+ bool AllowFunctionParameter) {
+ QualType VDType = VD->getType();
// - in a return statement in a function with ...
// ... a class return type ...
- if (!ReturnType.isNull()) {
+ if (!ReturnType.isNull() && !ReturnType->isDependentType()) {
if (!ReturnType->isRecordType())
- return 0;
+ return false;
// ... the same cv-unqualified type as the function return type ...
- if (!Context.hasSameUnqualifiedType(ReturnType, ExprType))
- return 0;
+ if (!VDType->isDependentType() &&
+ !Context.hasSameUnqualifiedType(ReturnType, VDType))
+ return false;
}
- // ... the expression is the name of a non-volatile automatic object
- // (other than a function or catch-clause parameter)) ...
- const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
- if (!DR || DR->refersToEnclosingLocal())
- return 0;
- const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
- if (!VD)
- return 0;
-
// ...object (other than a function or catch-clause parameter)...
if (VD->getKind() != Decl::Var &&
!(AllowFunctionParameter && VD->getKind() == Decl::ParmVar))
- return 0;
- if (VD->isExceptionVariable()) return 0;
+ return false;
+ if (VD->isExceptionVariable()) return false;
// ...automatic...
- if (!VD->hasLocalStorage()) return 0;
+ if (!VD->hasLocalStorage()) return false;
// ...non-volatile...
- if (VD->getType().isVolatileQualified()) return 0;
- if (VD->getType()->isReferenceType()) return 0;
+ if (VD->getType().isVolatileQualified()) return false;
// __block variables can't be allocated in a way that permits NRVO.
- if (VD->hasAttr<BlocksAttr>()) return 0;
+ if (VD->hasAttr<BlocksAttr>()) return false;
// Variables with higher required alignment than their type's ABI
// alignment cannot use NRVO.
- if (VD->hasAttr<AlignedAttr>() &&
+ if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() &&
Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType()))
- return 0;
+ return false;
- return VD;
+ return true;
}
/// \brief Perform the initialization of a potentially-movable value, which
@@ -2547,7 +2560,7 @@
// Promote "AsRvalue" to the heap, since we now need this
// expression node to persist.
Value = ImplicitCastExpr::Create(Context, Value->getType(),
- CK_NoOp, Value, 0, VK_XValue);
+ CK_NoOp, Value, nullptr, VK_XValue);
// Complete type-checking the initialization of the return type
// using the constructor we found.
@@ -2653,7 +2666,7 @@
// Otherwise, verify that this result type matches the previous one. We are
// pickier with blocks than for normal functions because we don't have GCC
// compatibility to worry about here.
- const VarDecl *NRVOCandidate = 0;
+ const VarDecl *NRVOCandidate = nullptr;
if (FnRetType->isDependentType()) {
// Delay processing for now. TODO: there are lots of dependent
// types we can conclusively prove aren't void.
@@ -2667,7 +2680,7 @@
Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2;
else {
Diag(ReturnLoc, diag::err_return_block_has_expr);
- RetValExp = 0;
+ RetValExp = nullptr;
}
}
} else if (!RetValExp) {
@@ -2684,7 +2697,7 @@
NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
- NRVOCandidate != 0);
+ NRVOCandidate != nullptr);
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
FnRetType, RetValExp);
if (Res.isInvalid()) {
@@ -2693,6 +2706,8 @@
}
RetValExp = Res.take();
CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc);
+ } else {
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
}
if (RetValExp) {
@@ -2707,9 +2722,7 @@
// If we need to check for the named return value optimization,
// or if we need to infer the return type,
// save the return statement in our scope for later processing.
- if (CurCap->HasImplicitReturnType ||
- (getLangOpts().CPlusPlus && FnRetType->isRecordType() &&
- !CurContext->isDependentContext()))
+ if (CurCap->HasImplicitReturnType || NRVOCandidate)
FunctionScopes.back()->Returns.push_back(Result);
return Owned(Result);
@@ -2806,7 +2819,24 @@
}
StmtResult
-Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
+ Scope *CurScope) {
+ StmtResult R = BuildReturnStmt(ReturnLoc, RetValExp);
+ if (R.isInvalid()) {
+ return R;
+ }
+
+ if (VarDecl *VD =
+ const_cast<VarDecl*>(cast<ReturnStmt>(R.get())->getNRVOCandidate())) {
+ CurScope->addNRVOCandidate(VD);
+ } else {
+ CurScope->setNoNRVO();
+ }
+
+ return R;
+}
+
+StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// Check for unexpanded parameter packs.
if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
return StmtError();
@@ -2816,7 +2846,7 @@
QualType FnRetType;
QualType RelatedRetType;
- const AttrVec *Attrs = 0;
+ const AttrVec *Attrs = nullptr;
bool isObjCMethod = false;
if (const FunctionDecl *FD = getCurFunctionDecl()) {
@@ -2857,7 +2887,7 @@
bool HasDependentReturnType = FnRetType->isDependentType();
- ReturnStmt *Result = 0;
+ ReturnStmt *Result = nullptr;
if (FnRetType->isVoidType()) {
if (RetValExp) {
if (isa<InitListExpr>(RetValExp)) {
@@ -2878,7 +2908,7 @@
<< RetValExp->getSourceRange();
// Drop the expression.
- RetValExp = 0;
+ RetValExp = nullptr;
} else if (!RetValExp->isTypeDependent()) {
// C99 6.8.6.4p1 (ext_ since GCC warns)
unsigned D = diag::ext_return_has_expr;
@@ -2933,7 +2963,7 @@
}
}
- Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);
+ Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr);
} else if (!RetValExp && !HasDependentReturnType) {
unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4
// C99 6.8.6.4p1 (ext_ since GCC warns)
@@ -2946,22 +2976,23 @@
Result = new (Context) ReturnStmt(ReturnLoc);
} else {
assert(RetValExp || HasDependentReturnType);
- const VarDecl *NRVOCandidate = 0;
+ const VarDecl *NRVOCandidate = nullptr;
+
+ QualType RetType = RelatedRetType.isNull() ? FnRetType : RelatedRetType;
+
+ // C99 6.8.6.4p3(136): The return statement is not an assignment. The
+ // overlap restriction of subclause 6.5.16.1 does not apply to the case of
+ // function return.
+
+ // In C++ the return statement is handled via a copy initialization,
+ // the C version of which boils down to CheckSingleAssignmentConstraints.
+ if (RetValExp)
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {
// we have a non-void function with an expression, continue checking
-
- QualType RetType = (RelatedRetType.isNull() ? FnRetType : RelatedRetType);
-
- // C99 6.8.6.4p3(136): The return statement is not an assignment. The
- // overlap restriction of subclause 6.5.16.1 does not apply to the case of
- // function return.
-
- // In C++ the return statement is handled via a copy initialization,
- // the C version of which boils down to CheckSingleAssignmentConstraints.
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
RetType,
- NRVOCandidate != 0);
+ NRVOCandidate != nullptr);
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
RetType, RetValExp);
if (Res.isInvalid()) {
@@ -3000,8 +3031,7 @@
// If we need to check for the named return value optimization, save the
// return statement in our scope for later processing.
- if (getLangOpts().CPlusPlus && FnRetType->isRecordType() &&
- !CurContext->isDependentContext())
+ if (Result->getNRVOCandidate())
FunctionScopes.back()->Returns.push_back(Result);
return Owned(Result);
@@ -3284,30 +3314,20 @@
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
- RecordDecl *RD = 0;
+ RecordDecl *RD = nullptr;
if (getLangOpts().CPlusPlus)
- RD = CXXRecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/0);
+ RD = CXXRecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc,
+ /*Id=*/nullptr);
else
- RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/0);
+ RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr);
DC->addDecl(RD);
RD->setImplicit();
RD->startDefinition();
+ assert(NumParams > 0 && "CapturedStmt requires context parameter");
CD = CapturedDecl::Create(Context, CurContext, NumParams);
DC->addDecl(CD);
-
- // Build the context parameter
- assert(NumParams > 0 && "CapturedStmt requires context parameter");
- DC = CapturedDecl::castToDeclContext(CD);
- IdentifierInfo *VarName = &Context.Idents.get("__context");
- QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
- ImplicitParamDecl *Param
- = ImplicitParamDecl::Create(Context, DC, Loc, VarName, ParamType);
- DC->addDecl(Param);
-
- CD->setContextParam(Param);
-
return RD;
}
@@ -3339,9 +3359,71 @@
void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
CapturedRegionKind Kind,
unsigned NumParams) {
- CapturedDecl *CD = 0;
+ CapturedDecl *CD = nullptr;
RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc, NumParams);
+ // Build the context parameter
+ DeclContext *DC = CapturedDecl::castToDeclContext(CD);
+ IdentifierInfo *ParamName = &Context.Idents.get("__context");
+ QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ ImplicitParamDecl *Param
+ = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
+ DC->addDecl(Param);
+
+ CD->setContextParam(0, Param);
+
+ // Enter the capturing scope for this captured region.
+ PushCapturedRegionScope(CurScope, CD, RD, Kind);
+
+ if (CurScope)
+ PushDeclContext(CurScope, CD);
+ else
+ CurContext = CD;
+
+ PushExpressionEvaluationContext(PotentiallyEvaluated);
+}
+
+void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+ CapturedRegionKind Kind,
+ ArrayRef<CapturedParamNameType> Params) {
+ CapturedDecl *CD = nullptr;
+ RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc, Params.size());
+
+ // Build the context parameter
+ DeclContext *DC = CapturedDecl::castToDeclContext(CD);
+ bool ContextIsFound = false;
+ unsigned ParamNum = 0;
+ for (ArrayRef<CapturedParamNameType>::iterator I = Params.begin(),
+ E = Params.end();
+ I != E; ++I, ++ParamNum) {
+ if (I->second.isNull()) {
+ assert(!ContextIsFound &&
+ "null type has been found already for '__context' parameter");
+ IdentifierInfo *ParamName = &Context.Idents.get("__context");
+ QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ ImplicitParamDecl *Param
+ = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
+ DC->addDecl(Param);
+ CD->setContextParam(ParamNum, Param);
+ ContextIsFound = true;
+ } else {
+ IdentifierInfo *ParamName = &Context.Idents.get(I->first);
+ ImplicitParamDecl *Param
+ = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second);
+ DC->addDecl(Param);
+ CD->setParam(ParamNum, Param);
+ }
+ }
+ assert(ContextIsFound && "no null type for '__context' parameter");
+ if (!ContextIsFound) {
+ // Add __context implicitly if it is not specified.
+ IdentifierInfo *ParamName = &Context.Idents.get("__context");
+ QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ ImplicitParamDecl *Param =
+ ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
+ DC->addDecl(Param);
+ CD->setContextParam(ParamNum, Param);
+ }
// Enter the capturing scope for this captured region.
PushCapturedRegionScope(CurScope, CD, RD, Kind);
@@ -3362,8 +3444,8 @@
Record->setInvalidDecl();
SmallVector<Decl*, 4> Fields(Record->fields());
- ActOnFields(/*Scope=*/0, Record->getLocation(), Record, Fields,
- SourceLocation(), SourceLocation(), /*AttributeList=*/0);
+ ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields,
+ SourceLocation(), SourceLocation(), /*AttributeList=*/nullptr);
PopDeclContext();
PopFunctionScopeInfo();
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 9169032..6502548 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -15,7 +15,6 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
@@ -382,7 +381,7 @@
ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
/*trailing lparen*/ false,
/*is & operand*/ false,
- /*CorrectionCandidateCallback=*/0,
+ /*CorrectionCandidateCallback=*/nullptr,
/*IsInlineAsmIdentifier=*/ true);
if (IsUnevaluatedContext)
@@ -438,12 +437,14 @@
if (!BaseResult.isSingleResult())
return true;
- const RecordType *RT = 0;
+ const RecordType *RT = nullptr;
NamedDecl *FoundDecl = BaseResult.getFoundDecl();
if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
RT = VD->getType()->getAs<RecordType>();
- else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl))
+ else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl))
RT = TD->getUnderlyingType()->getAs<RecordType>();
+ else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
+ RT = TD->getTypeForDecl()->getAs<RecordType>();
if (!RT)
return true;
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 9bb191d..3bc620b 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -14,7 +14,6 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
@@ -29,16 +28,15 @@
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
<< St->getLocStart();
if (isa<SwitchCase>(St)) {
- SourceLocation L = Lexer::getLocForEndOfToken(Range.getEnd(), 0,
- S.getSourceManager(), S.getLangOpts());
+ SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
<< FixItHint::CreateInsertion(L, ";");
}
- return 0;
+ return nullptr;
}
if (S.getCurFunction()->SwitchStack.empty()) {
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
- return 0;
+ return nullptr;
}
return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
A.getAttributeSpellingListIndex());
@@ -52,7 +50,7 @@
S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
diag::warn_unhandled_ms_attribute_ignored :
diag::warn_unknown_attribute_ignored) << A.getName();
- return 0;
+ return nullptr;
case AttributeList::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
default:
@@ -60,7 +58,7 @@
// it as a statement attribute => it is declaration attribute
S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
<< A.getName() << St->getLocStart();
- return 0;
+ return nullptr;
}
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 9be7189..272c811 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -52,8 +52,8 @@
if (isa<TemplateDecl>(D)) {
if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D))
- return 0;
-
+ return nullptr;
+
return Orig;
}
@@ -79,10 +79,10 @@
return Spec->getSpecializedTemplate();
}
- return 0;
+ return nullptr;
}
- return 0;
+ return nullptr;
}
void Sema::FilterAcceptableTemplateNames(LookupResult &R,
@@ -250,7 +250,7 @@
bool &MemberOfUnknownSpecialization) {
// Determine where to perform name lookup
MemberOfUnknownSpecialization = false;
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
bool isDependent = false;
if (!ObjectType.isNull()) {
// This nested-name-specifier occurs in a member access expression, e.g.,
@@ -325,7 +325,8 @@
FilterCCC.WantCXXNamedCasts = true;
if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),
Found.getLookupKind(), S, &SS,
- FilterCCC, LookupCtx)) {
+ FilterCCC, CTK_ErrorRecovery,
+ LookupCtx)) {
Found.setLookupName(Corrected.getCorrection());
if (Corrected.getCorrectionDecl())
Found.addDecl(Corrected.getCorrectionDecl());
@@ -418,10 +419,10 @@
// Since the 'this' expression is synthesized, we don't need to
// perform the double-lookup check.
- NamedDecl *FirstQualifierInScope = 0;
+ NamedDecl *FirstQualifierInScope = nullptr;
return Owned(CXXDependentScopeMemberExpr::Create(Context,
- /*This*/ 0, ThisType,
+ /*This*/ nullptr, ThisType,
/*IsArrow*/ true,
/*Op*/ SourceLocation(),
SS.getWithLocInContext(Context),
@@ -474,7 +475,7 @@
D = Temp->getTemplatedDecl();
return Temp;
}
- return 0;
+ return nullptr;
}
ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion(
@@ -715,7 +716,7 @@
// template-parameter that is not a template parameter pack.
if (Default && IsParameterPack) {
Diag(EqualLoc, diag::err_template_param_pack_default_arg);
- Default = 0;
+ Default = nullptr;
}
// Check the well-formedness of the default template argument, if provided.
@@ -906,7 +907,7 @@
if (Previous.isAmbiguous())
return true;
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
if (Previous.begin() != Previous.end())
PrevDecl = (*Previous.begin())->getUnderlyingDecl();
@@ -949,7 +950,7 @@
// Declarations in outer scopes don't matter. However, the outermost
// context we computed is the semantic context for our new
// declaration.
- PrevDecl = PrevClassTemplate = 0;
+ PrevDecl = PrevClassTemplate = nullptr;
SemanticContext = OutermostContext;
// Check that the chosen semantic context doesn't already contain a
@@ -970,7 +971,7 @@
}
} else if (PrevDecl &&
!isDeclInScope(PrevDecl, SemanticContext, S, SS.isValid()))
- PrevDecl = PrevClassTemplate = 0;
+ PrevDecl = PrevClassTemplate = nullptr;
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible. Skip this check
@@ -1012,7 +1013,7 @@
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
} else if (PrevDecl) {
// C++ [temp]p5:
// A class template shall not have the same name as any other
@@ -1031,7 +1032,8 @@
if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
CheckTemplateParameterList(
TemplateParams,
- PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() : 0,
+ PrevClassTemplate ? PrevClassTemplate->getTemplateParameters()
+ : nullptr,
(SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
SemanticContext->isDependentContext())
? TPC_ClassTemplateMember
@@ -1053,7 +1055,7 @@
CXXRecordDecl *NewClass =
CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
PrevClassTemplate?
- PrevClassTemplate->getTemplatedDecl() : 0,
+ PrevClassTemplate->getTemplatedDecl() : nullptr,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(NewClass, SS);
if (NumOuterTemplateParamLists > 0)
@@ -1300,7 +1302,7 @@
// Merge default arguments for template type parameters.
TemplateTypeParmDecl *OldTypeParm
- = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0;
+ = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr;
if (NewTypeParm->isParameterPack()) {
assert(!NewTypeParm->hasDefaultArgument() &&
@@ -1345,7 +1347,7 @@
// Merge default arguments for non-type template parameters
NonTypeTemplateParmDecl *OldNonTypeParm
- = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0;
+ = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : nullptr;
if (NewNonTypeParm->isParameterPack()) {
assert(!NewNonTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
@@ -1392,7 +1394,7 @@
// Merge default arguments for template template parameters
TemplateTemplateParmDecl *OldTemplateParm
- = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
+ = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : nullptr;
if (NewTemplateParm->isParameterPack()) {
assert(!NewTemplateParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
@@ -1593,6 +1595,9 @@
/// parameter lists. This scope specifier precedes a qualified name that is
/// being declared.
///
+/// \param TemplateId The template-id following the scope specifier, if there
+/// is one. Used to check for a missing 'template<>'.
+///
/// \param ParamLists the template parameter lists, from the outermost to the
/// innermost template parameter lists.
///
@@ -1611,6 +1616,7 @@
/// itself a template).
TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TemplateId,
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
bool &IsExplicitSpecialization, bool &Invalid) {
IsExplicitSpecialization = false;
@@ -1717,6 +1723,37 @@
// template<> for each enclosing class template that is
// explicitly specialized.
bool SawNonEmptyTemplateParameterList = false;
+
+ auto CheckExplicitSpecialization = [&](SourceRange Range, bool Recovery) {
+ if (SawNonEmptyTemplateParameterList) {
+ Diag(DeclLoc, diag::err_specialize_member_of_template)
+ << !Recovery << Range;
+ Invalid = true;
+ IsExplicitSpecialization = false;
+ return true;
+ }
+
+ return false;
+ };
+
+ auto DiagnoseMissingExplicitSpecialization = [&] (SourceRange Range) {
+ // Check that we can have an explicit specialization here.
+ if (CheckExplicitSpecialization(Range, true))
+ return true;
+
+ // We don't have a template header, but we should.
+ SourceLocation ExpectedTemplateLoc;
+ if (!ParamLists.empty())
+ ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
+ else
+ ExpectedTemplateLoc = DeclStartLoc;
+
+ Diag(DeclLoc, diag::err_template_spec_needs_header)
+ << Range
+ << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
+ return false;
+ };
+
unsigned ParamIdx = 0;
for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
++TypeIdx) {
@@ -1730,7 +1767,7 @@
// For a dependent type, the set of template parameters that we
// expect to see.
- TemplateParameterList *ExpectedTemplateParams = 0;
+ TemplateParameterList *ExpectedTemplateParams = nullptr;
// C++0x [temp.expl.spec]p15:
// A member or a member template may be nested within many enclosing
@@ -1787,13 +1824,9 @@
// are not explicitly specialized as well.
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() == 0) {
- if (SawNonEmptyTemplateParameterList) {
- Diag(DeclLoc, diag::err_specialize_member_of_template)
- << ParamLists[ParamIdx]->getSourceRange();
- Invalid = true;
- IsExplicitSpecialization = false;
- return 0;
- }
+ if (CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
+ false))
+ return nullptr;
} else
SawNonEmptyTemplateParameterList = true;
}
@@ -1814,30 +1847,22 @@
ParamLists[ParamIdx]->getRAngleLoc())
<< getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
Invalid = true;
- return 0;
+ return nullptr;
}
-
+
// Consume this template header.
++ParamIdx;
continue;
- }
-
- if (!IsFriend) {
- // We don't have a template header, but we should.
- SourceLocation ExpectedTemplateLoc;
- if (!ParamLists.empty())
- ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
- else
- ExpectedTemplateLoc = DeclStartLoc;
-
- Diag(DeclLoc, diag::err_template_spec_needs_header)
- << getRangeOfTypeInNestedNameSpecifier(Context, T, SS)
- << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
}
-
+
+ if (!IsFriend)
+ if (DiagnoseMissingExplicitSpecialization(
+ getRangeOfTypeInNestedNameSpecifier(Context, T, SS)))
+ return nullptr;
+
continue;
}
-
+
if (NeedNonemptyTemplateHeader) {
// In friend declarations we can have template-ids which don't
// depend on the corresponding template parameter lists. But
@@ -1846,7 +1871,7 @@
if (IsFriend && T->isDependentType()) {
if (ParamIdx < ParamLists.size() &&
DependsOnTemplateParameters(T, ParamLists[ParamIdx]))
- ExpectedTemplateParams = 0;
+ ExpectedTemplateParams = nullptr;
else
continue;
}
@@ -1858,9 +1883,9 @@
ExpectedTemplateParams,
true, TPL_TemplateMatch))
Invalid = true;
-
+
if (!Invalid &&
- CheckTemplateParameterList(ParamLists[ParamIdx], 0,
+ CheckTemplateParameterList(ParamLists[ParamIdx], nullptr,
TPC_ClassTemplateMember))
Invalid = true;
@@ -1875,12 +1900,26 @@
continue;
}
}
-
+
// If there were at least as many template-ids as there were template
// parameter lists, then there are no template parameter lists remaining for
// the declaration itself.
- if (ParamIdx >= ParamLists.size())
- return 0;
+ if (ParamIdx >= ParamLists.size()) {
+ if (TemplateId && !IsFriend) {
+ // We don't have a template header for the declaration itself, but we
+ // should.
+ IsExplicitSpecialization = true;
+ DiagnoseMissingExplicitSpecialization(SourceRange(TemplateId->LAngleLoc,
+ TemplateId->RAngleLoc));
+
+ // Fabricate an empty template parameter list for the invented header.
+ return TemplateParameterList::Create(Context, SourceLocation(),
+ SourceLocation(), nullptr, 0,
+ SourceLocation());
+ }
+
+ return nullptr;
+ }
// If there were too many template parameter lists, complain about that now.
if (ParamIdx < ParamLists.size() - 1) {
@@ -1921,14 +1960,11 @@
// unspecialized, except that the declaration shall not explicitly
// specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
- if (ParamLists.back()->size() == 0 && SawNonEmptyTemplateParameterList) {
- Diag(DeclLoc, diag::err_specialize_member_of_template)
- << ParamLists[ParamIdx]->getSourceRange();
- Invalid = true;
- IsExplicitSpecialization = false;
- return 0;
- }
-
+ if (ParamLists.back()->size() == 0 &&
+ CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
+ false))
+ return nullptr;
+
// Return the last template parameter list, which corresponds to the
// entity being declared.
return ParamLists.back();
@@ -2087,7 +2123,7 @@
= dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *Decl
= ClassTemplate->findSpecialization(Converted.data(), Converted.size(),
InsertPos);
@@ -2102,7 +2138,7 @@
ClassTemplate->getLocation(),
ClassTemplate,
Converted.data(),
- Converted.size(), 0);
+ Converted.size(), nullptr);
ClassTemplate->AddSpecialization(Decl, InsertPos);
if (ClassTemplate->isOutOfLine())
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
@@ -2355,6 +2391,17 @@
return true;
}
+/// Convert the parser's template argument list representation into our form.
+static TemplateArgumentListInfo
+makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
+ TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,
+ TemplateId.RAngleLoc);
+ ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),
+ TemplateId.NumArgs);
+ S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ return TemplateArgs;
+}
+
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
TemplateParameterList *TemplateParams, VarDecl::StorageClass SC,
@@ -2364,21 +2411,29 @@
"Variable template specialization is declared with a template it.");
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+ TemplateArgumentListInfo TemplateArgs =
+ makeTemplateArgumentListInfo(*this, *TemplateId);
SourceLocation TemplateNameLoc = D.getIdentifierLoc();
SourceLocation LAngleLoc = TemplateId->LAngleLoc;
SourceLocation RAngleLoc = TemplateId->RAngleLoc;
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+
TemplateName Name = TemplateId->Template.get();
// The template-id must name a variable template.
VarTemplateDecl *VarTemplate =
- dyn_cast<VarTemplateDecl>(Name.getAsTemplateDecl());
- if (!VarTemplate)
+ dyn_cast_or_null<VarTemplateDecl>(Name.getAsTemplateDecl());
+ if (!VarTemplate) {
+ NamedDecl *FnTemplate;
+ if (auto *OTS = Name.getAsOverloadedTemplate())
+ FnTemplate = *OTS->begin();
+ else
+ FnTemplate = dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl());
+ if (FnTemplate)
+ return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template_but_method)
+ << FnTemplate->getDeclName();
return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template)
<< IsPartialSpecialization;
+ }
// Check for unexpanded parameter packs in any of the template arguments.
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -2446,8 +2501,8 @@
}
}
- void *InsertPos = 0;
- VarTemplateSpecializationDecl *PrevDecl = 0;
+ void *InsertPos = nullptr;
+ VarTemplateSpecializationDecl *PrevDecl = nullptr;
if (IsPartialSpecialization)
// FIXME: Template parameter list matters too
@@ -2457,7 +2512,7 @@
PrevDecl = VarTemplate->findSpecialization(Converted.data(),
Converted.size(), InsertPos);
- VarTemplateSpecializationDecl *Specialization = 0;
+ VarTemplateSpecializationDecl *Specialization = nullptr;
// Check whether we can declare a variable template specialization in
// the current scope.
@@ -2473,7 +2528,7 @@
// the list of outer template parameters to reflect our new declaration.
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
- PrevDecl = 0;
+ PrevDecl = nullptr;
} else if (IsPartialSpecialization) {
// Create a new class template partial specialization declaration node.
VarTemplatePartialSpecializationDecl *PrevPartial =
@@ -2618,7 +2673,7 @@
// Find the variable template specialization declaration that
// corresponds to these arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(
Converted.data(), Converted.size(), InsertPos))
// If we already have a variable template specialization, return it.
@@ -2771,7 +2826,7 @@
// Build an ordinary singleton decl ref.
return BuildDeclarationNameExpr(SS, NameInfo, Var,
- /*FoundD=*/0, TemplateArgs);
+ /*FoundD=*/nullptr, TemplateArgs);
}
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
@@ -2833,7 +2888,7 @@
bool MemberOfUnknownSpecialization;
LookupResult R(*this, NameInfo, LookupOrdinaryName);
- LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false,
+ LookupTemplateName(R, (Scope*)nullptr, SS, QualType(), /*Entering*/ false,
MemberOfUnknownSpecialization);
if (R.isAmbiguous())
@@ -2877,7 +2932,7 @@
diag::ext_template_outside_of_template)
<< FixItHint::CreateRemoval(TemplateKWLoc);
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
if (SS.isSet())
LookupCtx = computeDeclContext(SS, EnteringContext);
if (!LookupCtx && ObjectType)
@@ -3079,7 +3134,7 @@
Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
- return 0;
+ return nullptr;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted.data(), Converted.size());
@@ -3400,7 +3455,8 @@
ExprResult E = Owned(DependentScopeDeclRefExpr::Create(Context,
SS.getWithLocInContext(Context),
TemplateKWLoc,
- NameInfo, 0));
+ NameInfo,
+ nullptr));
// If we parsed the template argument as a pack expansion, create a
// pack expansion expression.
@@ -4170,10 +4226,9 @@
if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) {
std::string Code = "static_cast<" + ParamType.getAsString() + ">(";
S.Diag(Arg->getExprLoc(), diag::err_template_arg_untyped_null_constant)
- << ParamType
- << FixItHint::CreateInsertion(Arg->getLocStart(), Code)
- << FixItHint::CreateInsertion(S.PP.getLocForEndOfToken(Arg->getLocEnd()),
- ")");
+ << ParamType << FixItHint::CreateInsertion(Arg->getLocStart(), Code)
+ << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getLocEnd()),
+ ")");
S.Diag(Param->getLocation(), diag::note_template_param_here);
return NPV_NullPointer;
}
@@ -4577,7 +4632,7 @@
// template-parameter shall be one of: [...]
//
// -- a pointer to member expressed as described in 5.3.1.
- DeclRefExpr *DRE = 0;
+ DeclRefExpr *DRE = nullptr;
// In C++98/03 mode, give an extension warning on any extra parentheses.
// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
@@ -4604,7 +4659,7 @@
if (UnOp->getOpcode() == UO_AddrOf) {
DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
if (DRE && !DRE->getQualifier())
- DRE = 0;
+ DRE = nullptr;
}
}
// A constant of pointer-to-member type.
@@ -4623,7 +4678,7 @@
}
}
- DRE = 0;
+ DRE = nullptr;
}
if (!DRE)
@@ -5108,7 +5163,7 @@
QualType ClassType
= Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
NestedNameSpecifier *Qualifier
- = NestedNameSpecifier::Create(Context, 0, false,
+ = NestedNameSpecifier::Create(Context, nullptr, false,
ClassType.getTypePtr());
CXXScopeSpec SS;
SS.MakeTrivial(Context, Qualifier, Loc);
@@ -5234,7 +5289,8 @@
if (OrigT->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
- E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E, 0,
+ E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E,
+ nullptr,
Context.getTrivialTypeSourceInfo(OrigT, Loc),
Loc, Loc);
}
@@ -5840,23 +5896,23 @@
TagUseKind TUK,
SourceLocation KWLoc,
SourceLocation ModulePrivateLoc,
- CXXScopeSpec &SS,
- TemplateTy TemplateD,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation RAngleLoc,
+ TemplateIdAnnotation &TemplateId,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
assert(TUK != TUK_Reference && "References are not specializations");
+ CXXScopeSpec &SS = TemplateId.SS;
+
// NOTE: KWLoc is the location of the tag keyword. This will instead
// store the location of the outermost template keyword in the declaration.
SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
- ? TemplateParameterLists[0]->getTemplateLoc() : SourceLocation();
+ ? TemplateParameterLists[0]->getTemplateLoc() : KWLoc;
+ SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;
+ SourceLocation LAngleLoc = TemplateId.LAngleLoc;
+ SourceLocation RAngleLoc = TemplateId.RAngleLoc;
// Find the class template we're specializing
- TemplateName Name = TemplateD.get();
+ TemplateName Name = TemplateId.Template.get();
ClassTemplateDecl *ClassTemplate
= dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
@@ -5877,8 +5933,9 @@
bool Invalid = false;
TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
- TemplateNameLoc, TemplateNameLoc, SS, TemplateParameterLists,
- TUK == TUK_Friend, isExplicitSpecialization, Invalid);
+ KWLoc, TemplateNameLoc, SS, &TemplateId,
+ TemplateParameterLists, TUK == TUK_Friend, isExplicitSpecialization,
+ Invalid);
if (Invalid)
return true;
@@ -5929,11 +5986,8 @@
<< SourceRange(LAngleLoc, RAngleLoc);
else
isExplicitSpecialization = true;
- } else if (TUK != TUK_Friend) {
- Diag(KWLoc, diag::err_template_spec_needs_header)
- << FixItHint::CreateInsertion(KWLoc, "template<> ");
- TemplateKWLoc = KWLoc;
- isExplicitSpecialization = true;
+ } else {
+ assert(TUK == TUK_Friend && "should have a 'template<>' for this decl");
}
// Check that the specialization uses the same tag kind as the
@@ -5953,10 +6007,8 @@
}
// Translate the parser's template argument list in our AST format.
- TemplateArgumentListInfo TemplateArgs;
- TemplateArgs.setLAngleLoc(LAngleLoc);
- TemplateArgs.setRAngleLoc(RAngleLoc);
- translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+ TemplateArgumentListInfo TemplateArgs =
+ makeTemplateArgumentListInfo(*this, TemplateId);
// Check for unexpanded parameter packs in any of the template arguments.
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -5991,8 +6043,8 @@
}
}
- void *InsertPos = 0;
- ClassTemplateSpecializationDecl *PrevDecl = 0;
+ void *InsertPos = nullptr;
+ ClassTemplateSpecializationDecl *PrevDecl = nullptr;
if (isPartialSpecialization)
// FIXME: Template parameter list matters, too
@@ -6005,7 +6057,7 @@
= ClassTemplate->findSpecialization(Converted.data(),
Converted.size(), InsertPos);
- ClassTemplateSpecializationDecl *Specialization = 0;
+ ClassTemplateSpecializationDecl *Specialization = nullptr;
// Check whether we can declare a class template specialization in
// the current scope.
@@ -6017,24 +6069,7 @@
// The canonical type
QualType CanonType;
- if (PrevDecl &&
- (PrevDecl->getSpecializationKind() == TSK_Undeclared ||
- TUK == TUK_Friend)) {
- // Since the only prior class template specialization with these
- // arguments was referenced but not declared, or we're only
- // referencing this specialization as a friend, reuse that
- // declaration node as our own, updating its source location and
- // the list of outer template parameters to reflect our new declaration.
- Specialization = PrevDecl;
- Specialization->setLocation(TemplateNameLoc);
- if (TemplateParameterLists.size() > 0) {
- Specialization->setTemplateParameterListsInfo(Context,
- TemplateParameterLists.size(),
- TemplateParameterLists.data());
- }
- PrevDecl = 0;
- CanonType = Context.getTypeDeclType(Specialization);
- } else if (isPartialSpecialization) {
+ if (isPartialSpecialization) {
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
@@ -6259,7 +6294,7 @@
Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D) {
- assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+ assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
if (FTI.hasPrototype) {
@@ -6477,8 +6512,12 @@
// For a given template and a given set of template-arguments,
// - an explicit instantiation definition shall appear at most once
// in a program,
- Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
- << PrevDecl;
+
+ // MSVCCompat: MSVC silently ignores duplicate explicit instantiations.
+ Diag(NewLoc, (getLangOpts().MSVCCompat)
+ ? diag::warn_explicit_instantiation_duplicate
+ : diag::err_explicit_instantiation_duplicate)
+ << PrevDecl;
Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
diag::note_previous_explicit_instantiation);
HasNoEffect = true;
@@ -6592,7 +6631,7 @@
// specializing this template.
// FIXME: It is somewhat wasteful to build
TemplateDeductionInfo Info(FailedCandidates.getLocation());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK = DeduceTemplateArguments(
cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()),
ExplicitTemplateArgs, FT, Specialization, Info)) {
@@ -6616,7 +6655,7 @@
FD->getLocation(),
PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
PDiag(diag::err_function_template_spec_ambiguous)
- << FD->getDeclName() << (ExplicitTemplateArgs != 0),
+ << FD->getDeclName() << (ExplicitTemplateArgs != nullptr),
PDiag(diag::note_function_template_spec_matched));
if (Result == Candidates.end())
@@ -6685,7 +6724,7 @@
const TemplateArgumentList* TemplArgs = new (Context)
TemplateArgumentList(Specialization->getTemplateSpecializationArgs());
FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(),
- TemplArgs, /*InsertPos=*/0,
+ TemplArgs, /*InsertPos=*/nullptr,
SpecInfo->getTemplateSpecializationKind(),
ExplicitTemplateArgs);
@@ -6715,9 +6754,9 @@
assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
// Try to find the member we are instantiating.
- NamedDecl *Instantiation = 0;
- NamedDecl *InstantiatedFrom = 0;
- MemberSpecializationInfo *MSInfo = 0;
+ NamedDecl *Instantiation = nullptr;
+ NamedDecl *InstantiatedFrom = nullptr;
+ MemberSpecializationInfo *MSInfo = nullptr;
if (Previous.empty()) {
// Nowhere to look anyway.
@@ -7024,7 +7063,7 @@
// Find the class template specialization declaration that
// corresponds to these arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->findSpecialization(Converted.data(),
Converted.size(), InsertPos);
@@ -7041,7 +7080,7 @@
SS.isSet()))
return true;
- ClassTemplateSpecializationDecl *Specialization = 0;
+ ClassTemplateSpecializationDecl *Specialization = nullptr;
bool HasNoEffect = false;
if (PrevDecl) {
@@ -7063,7 +7102,7 @@
// (Other source locations will be updated later.)
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
}
@@ -7147,6 +7186,7 @@
// TSK_ExplicitInstantiationDefinition
if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
TSK == TSK_ExplicitInstantiationDefinition)
+ // FIXME: Need to notify the ASTMutationListener that we did this.
Def->setTemplateSpecializationKind(TSK);
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
@@ -7416,13 +7456,8 @@
}
// Translate the parser's template argument list into our AST format.
- TemplateArgumentListInfo TemplateArgs;
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
- TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
- TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ TemplateArgumentListInfo TemplateArgs =
+ makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
D.getIdentifierLoc(), TemplateArgs);
@@ -7484,7 +7519,7 @@
}
// FIXME: Create an ExplicitInstantiation node?
- return (Decl*) 0;
+ return (Decl*) nullptr;
}
// If the declarator is a template-id, translate the parser's template
@@ -7492,12 +7527,7 @@
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo TemplateArgs;
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
- TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
- TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
HasExplicitTemplateArgs = true;
}
@@ -7529,10 +7559,11 @@
continue;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK
= DeduceTemplateArguments(FunTmpl,
- (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+ (HasExplicitTemplateArgs ? &TemplateArgs
+ : nullptr),
R, Specialization, Info)) {
// Keep track of almost-matches.
FailedCandidates.addCandidate()
@@ -7585,7 +7616,7 @@
// FIXME: We may still want to build some representation of this
// explicit specialization.
if (HasNoEffect)
- return (Decl*) 0;
+ return (Decl*) nullptr;
}
Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
@@ -7593,7 +7624,11 @@
if (Attr)
ProcessDeclAttributeList(S, Specialization, Attr);
- if (TSK == TSK_ExplicitInstantiationDefinition)
+ if (Specialization->isDefined()) {
+ // Let the ASTConsumer know that this function has been explicitly
+ // instantiated now, and its linkage might have changed.
+ Consumer.HandleTopLevelDecl(DeclGroupRef(Specialization));
+ } else if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);
// C++0x [temp.explicit]p2:
@@ -7618,7 +7653,7 @@
D.getCXXScopeSpec().isSet());
// FIXME: Create some kind of ExplicitInstantiationDecl here.
- return (Decl*) 0;
+ return (Decl*) nullptr;
}
TypeResult
@@ -7830,7 +7865,7 @@
LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
LookupQualifiedName(Result, Ctx);
unsigned DiagID = 0;
- Decl *Referenced = 0;
+ Decl *Referenced = nullptr;
switch (Result.getResultKind()) {
case LookupResult::NotFound: {
// If we're looking up 'type' within a template named 'enable_if', produce
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 8a0589a..246107e 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -126,7 +126,7 @@
unsigned TDF,
bool PartialOrdering = false,
SmallVectorImpl<RefParamPartialOrderingComparison> *
- RefParamComparisons = 0);
+ RefParamComparisons = nullptr);
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
@@ -155,7 +155,7 @@
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
- return 0;
+ return nullptr;
}
/// \brief Determine whether two declaration pointers refer to the same
@@ -382,7 +382,7 @@
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
- D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : 0;
+ D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
TemplateArgument New(D, NTTP->getType()->isReferenceType());
DeducedTemplateArgument NewDeduced(New);
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
@@ -715,7 +715,7 @@
unsigned TDF,
bool PartialOrdering = false,
SmallVectorImpl<RefParamPartialOrderingComparison> *
- RefParamComparisons = 0) {
+ RefParamComparisons = nullptr) {
// Fast-path check to see if we have too many/too few arguments.
if (NumParams != NumArgs &&
!(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
@@ -2461,7 +2461,7 @@
static bool isSimpleTemplateIdType(QualType T) {
if (const TemplateSpecializationType *Spec
= T->getAs<TemplateSpecializationType>())
- return Spec->getTemplateName().getAsTemplateDecl() != 0;
+ return Spec->getTemplateName().getAsTemplateDecl() != nullptr;
return false;
}
@@ -2600,7 +2600,7 @@
// and the end of the function-definition, member-declarator, or
// declarator.
unsigned ThisTypeQuals = 0;
- CXXRecordDecl *ThisContext = 0;
+ CXXRecordDecl *ThisContext = nullptr;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
ThisContext = Method->getParent();
ThisTypeQuals = Method->getTypeQualifiers();
@@ -3052,7 +3052,7 @@
return QualType();
// Otherwise, see if we can resolve a function type
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(Ovl->getNameLoc());
if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs,
Specialization, Info))
@@ -3144,7 +3144,7 @@
if (ArgType == S.Context.OverloadTy) {
ArgType = ResolveOverloadForDeduction(S, TemplateParams,
Arg, ParamType,
- ParamRefType != 0);
+ ParamRefType != nullptr);
if (ArgType.isNull())
return true;
}
@@ -3313,7 +3313,7 @@
*ExplicitTemplateArgs,
Deduced,
ParamTypes,
- 0,
+ nullptr,
Info);
if (Result)
return Result;
@@ -3679,7 +3679,7 @@
FunctionTemplateDecl *CallOpTemplate =
CallOpGeneric->getDescribedFunctionTemplate();
- FunctionDecl *CallOpSpecialized = 0;
+ FunctionDecl *CallOpSpecialized = nullptr;
// Use the deduced arguments of the conversion function, to specialize our
// generic lambda's call operator.
if (Sema::TemplateDeductionResult Result
@@ -3705,7 +3705,7 @@
// specialized our corresponding call operator, we are ready to
// specialize the static invoker with the deduced arguments of our
// ptr-to-function.
- FunctionDecl *InvokerSpecialized = 0;
+ FunctionDecl *InvokerSpecialized = nullptr;
FunctionTemplateDecl *InvokerTemplate = LambdaClass->
getLambdaStaticInvoker()->getDescribedFunctionTemplate();
@@ -3848,7 +3848,7 @@
// Create an Instantiation Scope for finalizing the operator.
LocalInstantiationScope InstScope(*this);
// Finish template argument deduction.
- FunctionDecl *ConversionSpecialized = 0;
+ FunctionDecl *ConversionSpecialized = nullptr;
TemplateDeductionResult Result
= FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
ConversionSpecialized, Info);
@@ -4017,8 +4017,8 @@
// Build template<class TemplParam> void Func(FuncParam);
TemplateTypeParmDecl *TemplParam =
- TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0,
- false, false);
+ TemplateTypeParmDecl::Create(Context, nullptr, SourceLocation(), Loc, 0, 0,
+ nullptr, false, false);
QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
NamedDecl *TemplParamPtr = TemplParam;
FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
@@ -4363,7 +4363,7 @@
unsigned NumCallArguments2) {
SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
- NumCallArguments1, 0);
+ NumCallArguments1, nullptr);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
NumCallArguments2,
&RefParamComparisons);
@@ -4372,7 +4372,7 @@
return Better1? FT1 : FT2;
if (!Better1 && !Better2) // Neither is better than the other
- return 0;
+ return nullptr;
// C++0x [temp.deduct.partial]p10:
// If for each type being considered a given template is at least as
@@ -4398,13 +4398,13 @@
RefParamComparisons[I].ParamIsRvalueRef) {
Better2 = true;
if (Better1)
- return 0;
+ return nullptr;
continue;
} else if (!RefParamComparisons[I].ParamIsRvalueRef &&
RefParamComparisons[I].ArgIsRvalueRef) {
Better1 = true;
if (Better2)
- return 0;
+ return nullptr;
continue;
}
@@ -4419,13 +4419,13 @@
case ParamMoreQualified:
Better1 = true;
if (Better2)
- return 0;
+ return nullptr;
continue;
case ArgMoreQualified:
Better2 = true;
if (Better1)
- return 0;
+ return nullptr;
continue;
}
@@ -4446,7 +4446,7 @@
if (Variadic1 != Variadic2)
return Variadic1? FT2 : FT1;
- return 0;
+ return nullptr;
}
/// \brief Determine if the two templates are equivalent.
@@ -4611,7 +4611,7 @@
PS2->getTemplateParameters(),
PT2, PT1, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*RefParamComparisons=*/0);
+ /*RefParamComparisons=*/nullptr);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
@@ -4625,7 +4625,7 @@
bool Better2 = !DeduceTemplateArgumentsByTypeMatch(
*this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*RefParamComparisons=*/0);
+ /*RefParamComparisons=*/nullptr);
if (Better2) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
Deduced.end());
@@ -4635,7 +4635,7 @@
}
if (Better1 == Better2)
- return 0;
+ return nullptr;
return Better1 ? PS1 : PS2;
}
@@ -4669,7 +4669,7 @@
bool Better1 = !DeduceTemplateArgumentsByTypeMatch(
*this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*RefParamComparisons=*/0);
+ /*RefParamComparisons=*/nullptr);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
Deduced.end());
@@ -4686,7 +4686,7 @@
PS1->getTemplateParameters(),
PT1, PT2, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*RefParamComparisons=*/0);
+ /*RefParamComparisons=*/nullptr);
if (Better2) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
@@ -4696,7 +4696,7 @@
}
if (Better1 == Better2)
- return 0;
+ return nullptr;
return Better1? PS1 : PS2;
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 1ee3e4b..fae1222 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -532,8 +532,8 @@
std::string Name;
if (!Parm->getName().empty())
Name = std::string(" '") + Parm->getName().str() + "'";
-
- TemplateParameterList *TemplateParams = 0;
+
+ TemplateParameterList *TemplateParams = nullptr;
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
TemplateParams = Template->getTemplateParameters();
else
@@ -552,7 +552,7 @@
}
case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
- TemplateParameterList *TemplateParams = 0;
+ TemplateParameterList *TemplateParams = nullptr;
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
TemplateParams = Template->getTemplateParameters();
else
@@ -581,7 +581,7 @@
Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
if (InNonInstantiationSFINAEContext)
- return Optional<TemplateDeductionInfo *>(0);
+ return Optional<TemplateDeductionInfo *>(nullptr);
for (SmallVectorImpl<ActiveTemplateInstantiation>::const_reverse_iterator
Active = ActiveTemplateInstantiations.rbegin(),
@@ -761,11 +761,11 @@
NestedNameSpecifierLoc QualifierLoc,
QualType T);
- TemplateName TransformTemplateName(CXXScopeSpec &SS,
- TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = 0);
+ TemplateName
+ TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
+ SourceLocation NameLoc,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = nullptr);
ExprResult TransformPredefinedExpr(PredefinedExpr *E);
ExprResult TransformDeclRefExpr(DeclRefExpr *E);
@@ -885,7 +885,7 @@
Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (!D)
- return 0;
+ return nullptr;
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
@@ -921,7 +921,7 @@
Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
if (!Inst)
- return 0;
+ return nullptr;
getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst);
return Inst;
@@ -945,8 +945,8 @@
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1)
- return 0;
-
+ return nullptr;
+
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
@@ -959,7 +959,7 @@
// The resulting type is not a tag; complain.
getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
- return 0;
+ return nullptr;
}
}
@@ -1155,7 +1155,7 @@
return ExprError();
} else {
// Propagate NULL template argument.
- VD = 0;
+ VD = nullptr;
}
// Derive the type we want the substituted decl to have. This had
@@ -1393,7 +1393,7 @@
// the template parameter list of a member template inside the
// template we are instantiating). Create a new template type
// parameter with the template "level" reduced by one.
- TemplateTypeParmDecl *NewTTPDecl = 0;
+ TemplateTypeParmDecl *NewTTPDecl = nullptr;
if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
TransformDecl(TL.getNameLoc(), OldTTPDecl));
@@ -1486,7 +1486,7 @@
"instantiation stack");
if (TL.getType().isNull())
- return 0;
+ return nullptr;
if (!TL.getType()->isInstantiationDependentType() &&
!TL.getType()->isVariablyModifiedType()) {
@@ -1502,7 +1502,7 @@
TLB.reserve(TL.getFullDataSize());
QualType Result = Instantiator.TransformType(TLB, TL);
if (Result.isNull())
- return 0;
+ return nullptr;
return TLB.getTypeSourceInfo(Context, Result);
}
@@ -1588,7 +1588,7 @@
Result = Instantiator.TransformType(TLB, TL);
}
if (Result.isNull())
- return 0;
+ return nullptr;
return TLB.getTypeSourceInfo(Context, Result);
}
@@ -1599,8 +1599,8 @@
Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
- TypeSourceInfo *NewDI = 0;
-
+ TypeSourceInfo *NewDI = nullptr;
+
TypeLoc OldTL = OldDI->getTypeLoc();
if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) {
@@ -1609,8 +1609,8 @@
NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
OldParm->getLocation(), OldParm->getDeclName());
if (!NewDI)
- return 0;
-
+ return nullptr;
+
if (NewDI->getType()->containsUnexpandedParameterPack()) {
// We still have unexpanded parameter packs, which means that
// our function parameter is still a function parameter pack.
@@ -1625,7 +1625,7 @@
Diag(OldParm->getLocation(),
diag::err_function_parameter_pack_without_parameter_packs)
<< NewDI->getType();
- return 0;
+ return nullptr;
}
} else {
NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
@@ -1633,11 +1633,11 @@
}
if (!NewDI)
- return 0;
+ return nullptr;
if (NewDI->getType()->isVoidType()) {
Diag(OldParm->getLocation(), diag::err_param_with_void_type);
- return 0;
+ return nullptr;
}
ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
@@ -1647,8 +1647,8 @@
NewDI->getType(), NewDI,
OldParm->getStorageClass());
if (!NewParm)
- return 0;
-
+ return nullptr;
+
// Mark the (new) default argument as uninstantiated (if any).
if (OldParm->hasUninstantiatedDefaultArg()) {
Expr *Arg = OldParm->getUninstantiatedDefaultArg();
@@ -1698,8 +1698,9 @@
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
DeclarationName());
- return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams, 0,
- ParamTypes, OutParams);
+ return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams,
+ nullptr, ParamTypes,
+ OutParams);
}
/// \brief Perform substitution on the base class specifiers of the
@@ -2012,8 +2013,8 @@
}
// Finish checking fields.
- ActOnFields(0, Instantiation->getLocation(), Instantiation, Fields,
- SourceLocation(), SourceLocation(), 0);
+ ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields,
+ SourceLocation(), SourceLocation(), nullptr);
CheckCompletedCXXClass(Instantiation);
// Attach any in-class member initializers now the class is complete.
@@ -2228,7 +2229,7 @@
return true;
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
- CXXRecordDecl *Pattern = 0;
+ CXXRecordDecl *Pattern = nullptr;
// C++ [temp.class.spec.match]p1:
// When a class template is used in a context that requires an
@@ -2369,6 +2370,9 @@
CXXRecordDecl *Instantiation,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateSpecializationKind TSK) {
+ // FIXME: We need to notify the ASTMutationListener that we did all of these
+ // things, in case we have an explicit instantiation definition in a PCM, a
+ // module, or preamble, and the declaration is in an imported AST.
assert(
(TSK == TSK_ExplicitInstantiationDefinition ||
TSK == TSK_ExplicitInstantiationDeclaration ||
@@ -2393,28 +2397,27 @@
SuppressNew) ||
SuppressNew)
continue;
-
- if (Function->isDefined())
+
+ // C++11 [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (TSK == TSK_ExplicitInstantiationDefinition && !Pattern->isDefined())
continue;
- if (TSK == TSK_ExplicitInstantiationDefinition) {
- // C++0x [temp.explicit]p8:
- // An explicit instantiation definition that names a class template
- // specialization explicitly instantiates the class template
- // specialization and is only an explicit instantiation definition
- // of members whose definition is visible at the point of
- // instantiation.
- if (!Pattern->isDefined())
- continue;
-
- Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
-
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+
+ if (Function->isDefined()) {
+ // Let the ASTConsumer know that this function has been explicitly
+ // instantiated now, and its linkage might have changed.
+ Consumer.HandleTopLevelDecl(DeclGroupRef(Function));
+ } else if (TSK == TSK_ExplicitInstantiationDefinition) {
InstantiateFunctionDefinition(PointOfInstantiation, Function);
- } else {
- Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
- if (TSK == TSK_ImplicitInstantiation)
- PendingLocalImplicitInstantiations.push_back(
- std::make_pair(Function, PointOfInstantiation));
+ } else if (TSK == TSK_ImplicitInstantiation) {
+ PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
}
}
} else if (auto *Var = dyn_cast<VarDecl>(D)) {
@@ -2682,7 +2685,7 @@
if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
CheckD = Tag->getPreviousDecl();
else
- CheckD = 0;
+ CheckD = nullptr;
} while (CheckD);
// If we aren't combined with our outer scope, we're done.
@@ -2694,13 +2697,13 @@
// deduction, we may not have values for template parameters yet.
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
isa<TemplateTemplateParmDecl>(D))
- return 0;
+ return nullptr;
// If we didn't find the decl, then we either have a sema bug, or we have a
// forward reference to a label declaration. Return null to indicate that
// we have an uninstantiated label.
assert(isa<LabelDecl>(D) && "declaration not instantiated in this scope");
- return 0;
+ return nullptr;
}
void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
@@ -2747,7 +2750,7 @@
const TemplateArgument **ExplicitArgs,
unsigned *NumExplicitArgs) const {
if (ExplicitArgs)
- *ExplicitArgs = 0;
+ *ExplicitArgs = nullptr;
if (NumExplicitArgs)
*NumExplicitArgs = 0;
@@ -2765,6 +2768,6 @@
if (!Current->CombineWithOuterScope)
break;
}
-
- return 0;
+
+ return nullptr;
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 316b574..be2db41 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -19,7 +19,6 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
@@ -133,7 +132,7 @@
static void instantiateDependentEnableIfAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const EnableIfAttr *A, const Decl *Tmpl, Decl *New) {
- Expr *Cond = 0;
+ Expr *Cond = nullptr;
{
EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
ExprResult Result = S.SubstExpr(A->getCond(), TemplateArgs);
@@ -188,7 +187,7 @@
if (TmplAttr->isLateParsed() && LateAttrs) {
// Late parsed attributes must be instantiated and attached after the
// enclosing class has been instantiated. See Sema::InstantiateClass.
- LocalInstantiationScope *Saved = 0;
+ LocalInstantiationScope *Saved = nullptr;
if (CurrentInstantiationScope)
Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
@@ -298,7 +297,7 @@
NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,
TemplateArgs);
if (!InstPrev)
- return 0;
+ return nullptr;
TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev);
@@ -336,11 +335,11 @@
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
TypeAliasDecl *Pattern = D->getTemplatedDecl();
- TypeAliasTemplateDecl *PrevAliasTemplate = 0;
+ TypeAliasTemplateDecl *PrevAliasTemplate = nullptr;
if (Pattern->getPreviousDecl()) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
if (!Found.empty()) {
@@ -351,7 +350,7 @@
TypeAliasDecl *AliasInst = cast_or_null<TypeAliasDecl>(
InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true));
if (!AliasInst)
- return 0;
+ return nullptr;
TypeAliasTemplateDecl *Inst
= TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
@@ -381,7 +380,7 @@
if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
if (RecordTy->getDecl()->isAnonymousStructOrUnion())
if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
- return 0;
+ return nullptr;
// Do substitution on the type of the declaration
TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
@@ -389,12 +388,12 @@
D->getTypeSpecStartLoc(),
D->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
if (DI->getType()->isFunctionType()) {
SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
<< D->isStaticDataMember() << DI->getType();
- return 0;
+ return nullptr;
}
DeclContext *DC = Owner;
@@ -413,10 +412,19 @@
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Var))
- return 0;
+ return nullptr;
SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner,
StartingScope, InstantiatingVarTemplate);
+
+ if (D->isNRVOVariable()) {
+ QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType();
+ if (SemaRef.isCopyElisionCandidate(ReturnType, Var, false))
+ Var->setNRVOVariable(true);
+ }
+
+ Var->setImplicit(D->isImplicit());
+
return Var;
}
@@ -455,7 +463,7 @@
Expr *BitWidth = D->getBitWidth();
if (Invalid)
- BitWidth = 0;
+ BitWidth = nullptr;
else if (BitWidth) {
// The bit-width expression is a constant expression.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
@@ -465,7 +473,7 @@
= SemaRef.SubstExpr(BitWidth, TemplateArgs);
if (InstantiatedBitWidth.isInvalid()) {
Invalid = true;
- BitWidth = 0;
+ BitWidth = nullptr;
} else
BitWidth = InstantiatedBitWidth.takeAs<Expr>();
}
@@ -479,10 +487,10 @@
D->getInClassInitStyle(),
D->getInnerLocStart(),
D->getAccess(),
- 0);
+ nullptr);
if (!Field) {
cast<Decl>(Owner)->setInvalidDecl();
- return 0;
+ return nullptr;
}
SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope);
@@ -564,7 +572,7 @@
NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), PI,
TemplateArgs);
if (!Next)
- return 0;
+ return nullptr;
NamedChain[i++] = Next;
}
@@ -598,12 +606,12 @@
D->getLocation(), DeclarationName());
}
if (!InstTy)
- return 0;
+ return nullptr;
FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocStart(),
D->getFriendLoc(), InstTy);
if (!FD)
- return 0;
+ return nullptr;
FD->setAccess(AS_public);
FD->setUnsupportedFriend(D->isUnsupportedFriend());
@@ -619,7 +627,7 @@
// objects, with the most important detail being that the target
// decl should almost certainly not be placed in Owner.
Decl *NewND = Visit(ND);
- if (!NewND) return 0;
+ if (!NewND) return nullptr;
FriendDecl *FD =
FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(),
@@ -640,7 +648,7 @@
ExprResult InstantiatedAssertExpr
= SemaRef.SubstExpr(AssertExpr, TemplateArgs);
if (InstantiatedAssertExpr.isInvalid())
- return 0;
+ return nullptr;
return SemaRef.BuildStaticAssertDeclaration(D->getLocation(),
InstantiatedAssertExpr.get(),
@@ -650,12 +658,12 @@
}
Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
- EnumDecl *PrevDecl = 0;
+ EnumDecl *PrevDecl = nullptr;
if (D->getPreviousDecl()) {
NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
D->getPreviousDecl(),
TemplateArgs);
- if (!Prev) return 0;
+ if (!Prev) return nullptr;
PrevDecl = cast<EnumDecl>(Prev);
}
@@ -688,7 +696,7 @@
Enum->setAccess(D->getAccess());
// Forward the mangling number from the template to the instantiated decl.
SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D));
- if (SubstQualifier(D, Enum)) return 0;
+ if (SubstQualifier(D, Enum)) return nullptr;
Owner->addDecl(Enum);
EnumDecl *Def = D->getDefinition();
@@ -730,10 +738,10 @@
SmallVector<Decl*, 4> Enumerators;
- EnumConstantDecl *LastEnumConst = 0;
+ EnumConstantDecl *LastEnumConst = nullptr;
for (auto *EC : Pattern->enumerators()) {
// The specified value for the enumerator.
- ExprResult Value = SemaRef.Owned((Expr *)0);
+ ExprResult Value = SemaRef.Owned((Expr *)nullptr);
if (Expr *UninstValue = EC->getInitExpr()) {
// The enumerator's value expression is a constant expression.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
@@ -745,7 +753,7 @@
// Drop the initial value and continue.
bool isInvalid = false;
if (Value.isInvalid()) {
- Value = SemaRef.Owned((Expr *)0);
+ Value = SemaRef.Owned((Expr *)nullptr);
isInvalid = true;
}
@@ -781,7 +789,7 @@
SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(),
Enum->getRBraceLoc(), Enum,
Enumerators,
- 0, 0);
+ nullptr, nullptr);
}
Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
@@ -797,7 +805,7 @@
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return NULL;
+ return nullptr;
CXXRecordDecl *Pattern = D->getTemplatedDecl();
@@ -809,11 +817,11 @@
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
}
- CXXRecordDecl *PrevDecl = 0;
- ClassTemplateDecl *PrevClassTemplate = 0;
+ CXXRecordDecl *PrevDecl = nullptr;
+ ClassTemplateDecl *PrevClassTemplate = nullptr;
if (!isFriend && Pattern->getPreviousDecl()) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
@@ -834,7 +842,7 @@
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
- if (!DC) return 0;
+ if (!DC) return nullptr;
} else {
DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(),
Pattern->getDeclContext(),
@@ -857,7 +865,7 @@
SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
<< D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
<< QualifierLoc.getSourceRange();
- return 0;
+ return nullptr;
}
bool AdoptedPreviousTemplateParams = false;
@@ -879,11 +887,7 @@
if (DCParent->isNamespace() &&
cast<NamespaceDecl>(DCParent)->getIdentifier() &&
cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) {
- DeclContext *DCParent2 = DCParent->getParent();
- if (DCParent2->isNamespace() &&
- cast<NamespaceDecl>(DCParent2)->getIdentifier() &&
- cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") &&
- DCParent2->getParent()->isTranslationUnit())
+ if (cast<Decl>(DCParent)->isInStdNamespace())
Complain = false;
}
}
@@ -896,7 +900,7 @@
Complain,
Sema::TPL_TemplateMatch)) {
if (Complain)
- return 0;
+ return nullptr;
AdoptedPreviousTemplateParams = true;
InstParams = PrevParams;
@@ -907,7 +911,7 @@
if (!AdoptedPreviousTemplateParams &&
SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
Sema::TPC_ClassTemplate))
- return 0;
+ return nullptr;
}
}
@@ -984,12 +988,12 @@
DeclContext::lookup_result Found
= Owner->lookup(ClassTemplate->getDeclName());
if (Found.empty())
- return 0;
+ return nullptr;
ClassTemplateDecl *InstClassTemplate
= dyn_cast<ClassTemplateDecl>(Found.front());
if (!InstClassTemplate)
- return 0;
+ return nullptr;
if (ClassTemplatePartialSpecializationDecl *Result
= InstClassTemplate->findPartialSpecInstantiatedFromMember(D))
@@ -1008,10 +1012,10 @@
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return NULL;
+ return nullptr;
VarDecl *Pattern = D->getTemplatedDecl();
- VarTemplateDecl *PrevVarTemplate = 0;
+ VarTemplateDecl *PrevVarTemplate = nullptr;
if (Pattern->getPreviousDecl()) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
@@ -1089,9 +1093,9 @@
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return NULL;
+ return nullptr;
- FunctionDecl *Instantiated = 0;
+ FunctionDecl *Instantiated = nullptr;
if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl()))
Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod,
InstParams));
@@ -1101,7 +1105,7 @@
InstParams));
if (!Instantiated)
- return 0;
+ return nullptr;
// Link the instantiated function template declaration to the function
// template from which it was instantiated.
@@ -1131,14 +1135,14 @@
}
Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
- CXXRecordDecl *PrevDecl = 0;
+ CXXRecordDecl *PrevDecl = nullptr;
if (D->isInjectedClassName())
PrevDecl = cast<CXXRecordDecl>(Owner);
else if (D->getPreviousDecl()) {
NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
D->getPreviousDecl(),
TemplateArgs);
- if (!Prev) return 0;
+ if (!Prev) return nullptr;
PrevDecl = cast<CXXRecordDecl>(Prev);
}
@@ -1149,7 +1153,7 @@
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Record))
- return 0;
+ return nullptr;
Record->setImplicit(D->isImplicit());
// FIXME: Check against AS_none is an ugly hack to work around the issue that
@@ -1224,7 +1228,7 @@
if (FunctionTemplate && !TemplateParams) {
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *SpecFunc
= FunctionTemplate->findSpecialization(Innermost.begin(), Innermost.size(),
InsertPos);
@@ -1240,7 +1244,7 @@
else
isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
- bool MergeWithParentScope = (TemplateParams != 0) ||
+ bool MergeWithParentScope = (TemplateParams != nullptr) ||
Owner->isFunctionOrMethod() ||
!(isa<Decl>(Owner) &&
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
@@ -1249,7 +1253,7 @@
SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
if (!TInfo)
- return 0;
+ return nullptr;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
@@ -1257,7 +1261,7 @@
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
}
// If we're instantiating a local function declaration, put the result
@@ -1271,7 +1275,7 @@
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
- if (!DC) return 0;
+ if (!DC) return nullptr;
} else {
DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(),
TemplateArgs);
@@ -1345,7 +1349,7 @@
TemplateArgumentList::CreateCopy(SemaRef.Context,
Innermost.begin(),
Innermost.size()),
- /*InsertPos=*/0);
+ /*InsertPos=*/nullptr);
} else if (isFriend) {
// Note, we need this connection even if the friend doesn't have a body.
// Its body may exist but not have been attached yet due to deferred
@@ -1379,14 +1383,14 @@
Info->getRAngleLoc());
if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
ExplicitArgs, TemplateArgs))
- return 0;
+ return nullptr;
// Map the candidate templates to their instantiations.
for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
Info->getTemplate(I),
TemplateArgs);
- if (!Temp) return 0;
+ if (!Temp) return nullptr;
Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
}
@@ -1412,7 +1416,7 @@
Previous.clear();
}
- SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous,
+ SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous,
isExplicitSpecialization);
NamedDecl *PrincipalDecl = (TemplateParams
@@ -1435,7 +1439,7 @@
// to these implicit definitions.
if (D->isThisDeclarationADefinition()) {
// Check for a function body.
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
if (Function->isDefined(Definition) &&
Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
@@ -1502,7 +1506,7 @@
// specialization for this particular set of template arguments.
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *SpecFunc
= FunctionTemplate->findSpecialization(Innermost.begin(),
Innermost.size(),
@@ -1519,7 +1523,7 @@
else
isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
- bool MergeWithParentScope = (TemplateParams != 0) ||
+ bool MergeWithParentScope = (TemplateParams != nullptr) ||
!(isa<Decl>(Owner) &&
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
@@ -1533,7 +1537,7 @@
TemplateParameterList *TempParams = D->getTemplateParameterList(I);
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return NULL;
+ return nullptr;
TempParamLists[I] = InstParams;
}
}
@@ -1541,7 +1545,7 @@
SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
if (!TInfo)
- return 0;
+ return nullptr;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
@@ -1549,7 +1553,7 @@
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
}
DeclContext *DC = Owner;
@@ -1560,18 +1564,18 @@
DC = SemaRef.computeDeclContext(SS);
if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
- return 0;
+ return nullptr;
} else {
DC = SemaRef.FindInstantiatedContext(D->getLocation(),
D->getDeclContext(),
TemplateArgs);
}
- if (!DC) return 0;
+ if (!DC) return nullptr;
}
// Build the instantiated method declaration.
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
- CXXMethodDecl *Method = 0;
+ CXXMethodDecl *Method = nullptr;
SourceLocation StartLoc = D->getInnerLocStart();
DeclarationNameInfo NameInfo
@@ -1597,7 +1601,7 @@
Sema::InstantiatingTemplate Inst(SemaRef, Constructor->getLocation(),
Inh);
if (Inst.isInvalid())
- return 0;
+ return nullptr;
Sema::ContextRAII SavedContext(SemaRef, Inh->getDeclContext());
LocalInstantiationScope LocalScope(SemaRef);
@@ -1608,7 +1612,7 @@
Inh = cast_or_null<CXXConstructorDecl>(
SemaRef.SubstDecl(Inh, Inh->getDeclContext(), InheritedArgs));
if (!Inh)
- return 0;
+ return nullptr;
}
cast<CXXConstructorDecl>(Method)->setInheritedConstructor(Inh);
}
@@ -1669,7 +1673,7 @@
TemplateArgumentList::CreateCopy(SemaRef.Context,
Innermost.begin(),
Innermost.size()),
- /*InsertPos=*/0);
+ /*InsertPos=*/nullptr);
} else if (!isFriend) {
// Record that this is an instantiation of a member function.
Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
@@ -1712,7 +1716,7 @@
}
if (!IsClassScopeSpecialization)
- SemaRef.CheckFunctionDeclaration(0, Method, Previous, false);
+ SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, false);
if (D->isPure())
SemaRef.CheckPureMethod(Method, SourceRange());
@@ -1830,13 +1834,13 @@
D->getLocation(),
D->getDeclName());
if (!NewDI)
- return 0;
+ return nullptr;
ExpandedParameterPackTypesAsWritten.push_back(NewDI);
QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(),
D->getLocation());
if (NewT.isNull())
- return 0;
+ return nullptr;
ExpandedParameterPackTypes.push_back(NewT);
}
@@ -1865,7 +1869,7 @@
TemplateArgs,
Expand, RetainExpansion,
NumExpansions))
- return 0;
+ return nullptr;
if (Expand) {
for (unsigned I = 0; I != *NumExpansions; ++I) {
@@ -1874,14 +1878,14 @@
D->getLocation(),
D->getDeclName());
if (!NewDI)
- return 0;
+ return nullptr;
ExpandedParameterPackTypesAsWritten.push_back(NewDI);
QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(
NewDI->getType(),
D->getLocation());
if (NewT.isNull())
- return 0;
+ return nullptr;
ExpandedParameterPackTypes.push_back(NewT);
}
@@ -1899,12 +1903,12 @@
D->getLocation(),
D->getDeclName());
if (!NewPattern)
- return 0;
+ return nullptr;
DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(),
NumExpansions);
if (!DI)
- return 0;
+ return nullptr;
T = DI->getType();
}
@@ -1913,7 +1917,7 @@
DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
D->getLocation(), D->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
// Check that this type is acceptable for a non-type template parameter.
T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
@@ -1999,7 +2003,7 @@
TemplateParameterList *Expansion =
SubstTemplateParams(D->getExpansionTemplateParameters(I));
if (!Expansion)
- return 0;
+ return nullptr;
ExpandedParams.push_back(Expansion);
}
@@ -2024,7 +2028,7 @@
TemplateArgs,
Expand, RetainExpansion,
NumExpansions))
- return 0;
+ return nullptr;
if (Expand) {
for (unsigned I = 0; I != *NumExpansions; ++I) {
@@ -2032,7 +2036,7 @@
LocalInstantiationScope Scope(SemaRef);
TemplateParameterList *Expansion = SubstTemplateParams(TempParams);
if (!Expansion)
- return 0;
+ return nullptr;
ExpandedParams.push_back(Expansion);
}
@@ -2049,7 +2053,7 @@
LocalInstantiationScope Scope(SemaRef);
InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
}
} else {
// Perform the actual substitution of template parameters within a new,
@@ -2057,7 +2061,7 @@
LocalInstantiationScope Scope(SemaRef);
InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
}
// Build the template template parameter.
@@ -2134,7 +2138,7 @@
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
// The name info is non-dependent, so no transformation
// is required.
@@ -2182,8 +2186,7 @@
return NewUD;
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
- if (SemaRef.CheckInheritingConstructorUsingDecl(NewUD))
- NewUD->setInvalidDecl();
+ SemaRef.CheckInheritingConstructorUsingDecl(NewUD);
return NewUD;
}
@@ -2195,9 +2198,9 @@
cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
Shadow->getLocation(), Shadow->getTargetDecl(), TemplateArgs));
if (!InstTarget)
- return 0;
+ return nullptr;
- UsingShadowDecl *PrevDecl = 0;
+ UsingShadowDecl *PrevDecl = nullptr;
if (CheckRedeclaration) {
if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl))
continue;
@@ -2207,7 +2210,8 @@
}
UsingShadowDecl *InstShadow =
- SemaRef.BuildUsingShadowDecl(/*Scope*/0, NewUD, InstTarget, PrevDecl);
+ SemaRef.BuildUsingShadowDecl(/*Scope*/nullptr, NewUD, InstTarget,
+ PrevDecl);
SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
if (isFunctionScope)
@@ -2219,7 +2223,7 @@
Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
// Ignore these; we handle them in bulk when processing the UsingDecl.
- return 0;
+ return nullptr;
}
Decl * TemplateDeclInstantiator
@@ -2228,7 +2232,7 @@
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
@@ -2237,8 +2241,8 @@
// Hence, no transformation is required for it.
DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
NamedDecl *UD =
- SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
- D->getUsingLoc(), SS, NameInfo, 0,
+ SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(),
+ D->getUsingLoc(), SS, NameInfo, nullptr,
/*instantiation*/ true,
/*typename*/ true, D->getTypenameLoc());
if (UD)
@@ -2252,7 +2256,7 @@
NestedNameSpecifierLoc QualifierLoc
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
@@ -2261,8 +2265,8 @@
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
NamedDecl *UD =
- SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
- D->getUsingLoc(), SS, NameInfo, 0,
+ SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(),
+ D->getUsingLoc(), SS, NameInfo, nullptr,
/*instantiation*/ true,
/*typename*/ false, SourceLocation());
if (UD)
@@ -2276,13 +2280,13 @@
ClassScopeFunctionSpecializationDecl *Decl) {
CXXMethodDecl *OldFD = Decl->getSpecialization();
CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD,
- 0, true));
+ nullptr, true));
LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
Sema::ForRedeclaration);
TemplateArgumentListInfo TemplateArgs;
- TemplateArgumentListInfo* TemplateArgsPtr = 0;
+ TemplateArgumentListInfo *TemplateArgsPtr = nullptr;
if (Decl->hasExplicitTemplateArgs()) {
TemplateArgs = Decl->templateArgs();
TemplateArgsPtr = &TemplateArgs;
@@ -2322,11 +2326,11 @@
}
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
- return VisitFunctionDecl(D, 0);
+ return VisitFunctionDecl(D, nullptr);
}
Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
- return VisitCXXMethodDecl(D, 0);
+ return VisitCXXMethodDecl(D, nullptr);
}
Decl *TemplateDeclInstantiator::VisitRecordDecl(RecordDecl *D) {
@@ -2349,11 +2353,11 @@
DeclContext::lookup_result Found
= Owner->lookup(ClassTemplate->getDeclName());
if (Found.empty())
- return 0;
+ return nullptr;
ClassTemplateDecl *InstClassTemplate
= dyn_cast<ClassTemplateDecl>(Found.front());
if (!InstClassTemplate)
- return 0;
+ return nullptr;
// Substitute into the template arguments of the class template explicit
// specialization.
@@ -2366,7 +2370,7 @@
ArgLocs.push_back(Loc.getArgLoc(I));
if (SemaRef.Subst(ArgLocs.data(), ArgLocs.size(),
InstTemplateArgs, TemplateArgs))
- return 0;
+ return nullptr;
// Check that the template argument list is well-formed for this
// class template.
@@ -2376,11 +2380,11 @@
InstTemplateArgs,
false,
Converted))
- return 0;
+ return nullptr;
// Figure out where to insert this class template explicit specialization
// in the member template's set of class template explicit specializations.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl =
InstClassTemplate->findSpecialization(Converted.data(), Converted.size(),
InsertPos);
@@ -2395,7 +2399,7 @@
PrevDecl->getSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
Ignored))
- return 0;
+ return nullptr;
// If PrevDecl was a definition and D is also a definition, diagnose.
// This happens in cases like:
@@ -2414,7 +2418,7 @@
SemaRef.Diag(D->getLocation(), diag::err_redefinition) << PrevDecl;
SemaRef.Diag(PrevDecl->getDefinition()->getLocation(),
diag::note_previous_definition);
- return 0;
+ return nullptr;
}
// Create the class template partial specialization declaration.
@@ -2436,7 +2440,7 @@
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, InstD))
- return 0;
+ return nullptr;
// Build the canonical type that describes the converted template
// arguments of the class template explicit specialization.
@@ -2471,7 +2475,7 @@
SemaRef.InstantiateClass(D->getLocation(), InstD, D, TemplateArgs,
TSK_ImplicitInstantiation,
/*Complain=*/true))
- return 0;
+ return nullptr;
return InstD;
}
@@ -2491,7 +2495,7 @@
if (SemaRef.Subst(TemplateArgsInfo.getArgumentArray(),
TemplateArgsInfo.size(), VarTemplateArgsInfo, TemplateArgs))
- return 0;
+ return nullptr;
// Check that the template argument list is well-formed for this template.
SmallVector<TemplateArgument, 4> Converted;
@@ -2499,11 +2503,11 @@
VarTemplate, VarTemplate->getLocStart(),
const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false,
Converted))
- return 0;
+ return nullptr;
// Find the variable template specialization declaration that
// corresponds to these arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (VarTemplateSpecializationDecl *VarSpec = VarTemplate->findSpecialization(
Converted.data(), Converted.size(), InsertPos))
// If we already have a variable template specialization, return it.
@@ -2523,19 +2527,19 @@
if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
if (RecordTy->getDecl()->isAnonymousStructOrUnion())
if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
- return 0;
+ return nullptr;
// Do substitution on the type of the declaration
TypeSourceInfo *DI =
SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
D->getTypeSpecStartLoc(), D->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
if (DI->getType()->isFunctionType()) {
SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
<< D->isStaticDataMember() << DI->getType();
- return 0;
+ return nullptr;
}
// Build the instantiated declaration
@@ -2549,7 +2553,7 @@
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Var))
- return 0;
+ return nullptr;
SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs,
Owner, StartingScope);
@@ -2569,7 +2573,7 @@
SemaRef.Diag(D->getLocation(), DiagID)
<< D->getDeclKindName();
- return 0;
+ return nullptr;
}
Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) {
@@ -2580,7 +2584,7 @@
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
if (D->isInvalidDecl())
- return 0;
+ return nullptr;
return Instantiator.Visit(D);
}
@@ -2609,7 +2613,7 @@
// Clean up if we had an error.
if (Invalid)
- return NULL;
+ return nullptr;
TemplateParameterList *InstL
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
@@ -2643,7 +2647,7 @@
TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
// Substitute into the template arguments of the class template partial
// specialization.
@@ -2654,7 +2658,7 @@
if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
TemplArgInfo->NumTemplateArgs,
InstTemplateArgs, TemplateArgs))
- return 0;
+ return nullptr;
// Check that the template argument list is well-formed for this
// class template.
@@ -2664,11 +2668,11 @@
InstTemplateArgs,
false,
Converted))
- return 0;
+ return nullptr;
// Figure out where to insert this class template partial specialization
// in the member template's set of class template partial specializations.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->findPartialSpecialization(Converted.data(),
Converted.size(), InsertPos);
@@ -2714,7 +2718,7 @@
<< WrittenTy->getType();
SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
<< SemaRef.Context.getTypeDeclType(PrevDecl);
- return 0;
+ return nullptr;
}
@@ -2731,17 +2735,18 @@
Converted.size(),
InstTemplateArgs,
CanonType,
- 0);
+ nullptr);
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
- return 0;
+ return nullptr;
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
InstPartialSpec->setTypeAsWritten(WrittenTy);
// Add this partial specialization to the set of class template partial
// specializations.
- ClassTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+ ClassTemplate->AddPartialSpecialization(InstPartialSpec,
+ /*InsertPos=*/nullptr);
return InstPartialSpec;
}
@@ -2770,7 +2775,7 @@
TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
// Substitute into the template arguments of the variable template partial
// specialization.
@@ -2781,18 +2786,18 @@
if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
TemplArgInfo->NumTemplateArgs,
InstTemplateArgs, TemplateArgs))
- return 0;
+ return nullptr;
// Check that the template argument list is well-formed for this
// class template.
SmallVector<TemplateArgument, 4> Converted;
if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(),
InstTemplateArgs, false, Converted))
- return 0;
+ return nullptr;
// Figure out where to insert this variable template partial specialization
// in the member template's set of variable template partial specializations.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
VarTemplateSpecializationDecl *PrevDecl =
VarTemplate->findPartialSpecialization(Converted.data(), Converted.size(),
InsertPos);
@@ -2834,7 +2839,7 @@
<< WrittenTy->getType();
SemaRef.Diag(PrevDecl->getLocation(),
diag::note_var_prev_partial_spec_here);
- return 0;
+ return nullptr;
}
// Do substitution on the type of the declaration
@@ -2842,13 +2847,13 @@
PartialSpec->getTypeSourceInfo(), TemplateArgs,
PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
if (DI->getType()->isFunctionType()) {
SemaRef.Diag(PartialSpec->getLocation(),
diag::err_variable_instantiates_to_function)
<< PartialSpec->isStaticDataMember() << DI->getType();
- return 0;
+ return nullptr;
}
// Create the variable template partial specialization declaration.
@@ -2861,14 +2866,14 @@
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
- return 0;
+ return nullptr;
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
InstPartialSpec->setTypeAsWritten(WrittenTy);
// Add this partial specialization to the set of variable template partial
// specializations. The instantiation of the initializer is not necessary.
- VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+ VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/nullptr);
SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs,
LateAttrs, Owner, StartingScope);
@@ -2882,8 +2887,8 @@
TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
assert(OldTInfo && "substituting function without type source info");
assert(Params.empty() && "parameter vector is non-empty at start");
-
- CXXRecordDecl *ThisContext = 0;
+
+ CXXRecordDecl *ThisContext = nullptr;
unsigned ThisTypeQuals = 0;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
ThisContext = cast<CXXRecordDecl>(Owner);
@@ -2896,7 +2901,7 @@
D->getDeclName(),
ThisContext, ThisTypeQuals);
if (!NewTInfo)
- return 0;
+ return nullptr;
TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
if (FunctionProtoTypeLoc OldProtoLoc = OldTL.getAs<FunctionProtoTypeLoc>()) {
@@ -2949,7 +2954,7 @@
ParmVarDecl *Parm =
cast_or_null<ParmVarDecl>(VisitParmVarDecl(OldParam));
if (!Parm)
- return 0;
+ return nullptr;
Params.push_back(Parm);
}
}
@@ -2968,7 +2973,7 @@
if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(),
D->getNumParams(), TemplateArgs, ParamTypes,
&Params))
- return 0;
+ return nullptr;
}
return NewTInfo;
@@ -3031,7 +3036,7 @@
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
// and the end of the function-definition, member-declarator, or
// declarator.
- CXXRecordDecl *ThisContext = 0;
+ CXXRecordDecl *ThisContext = nullptr;
unsigned ThisTypeQuals = 0;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
ThisContext = Method->getParent();
@@ -3113,7 +3118,7 @@
Exceptions.push_back(T);
}
- Expr *NoexceptExpr = 0;
+ Expr *NoexceptExpr = nullptr;
if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
EnterExpressionEvaluationContext Unevaluated(SemaRef,
Sema::ConstantEvaluated);
@@ -3127,7 +3132,7 @@
!NoexceptExpr->isValueDependent())
NoexceptExpr
= SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
- 0, diag::err_noexcept_needs_constant_expression,
+ nullptr, diag::err_noexcept_needs_constant_expression,
/*AllowFold*/ false).take();
}
}
@@ -3164,7 +3169,7 @@
LocalInstantiationScope Scope(*this);
MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(Decl, 0, /*RelativeToPrimary*/true);
+ getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
FunctionDecl *Template = Proto->getExceptionSpecTemplate();
addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
@@ -3410,14 +3415,14 @@
if (PatternDecl->isDefaulted())
SetDeclDefaulted(Function, PatternDecl->getLocation());
else {
- ActOnStartOfFunctionDef(0, Function);
+ ActOnStartOfFunctionDef(nullptr, Function);
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
Sema::ContextRAII savedContext(*this, Function);
MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
+ getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
TemplateArgs);
@@ -3483,11 +3488,11 @@
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *StartingScope) {
if (FromVar->isInvalidDecl())
- return 0;
+ return nullptr;
InstantiatingTemplate Inst(*this, PointOfInstantiation, FromVar);
if (Inst.isInvalid())
- return 0;
+ return nullptr;
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(&TemplateArgList);
@@ -3532,7 +3537,7 @@
SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs,
PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
// Update the type of this variable template specialization.
VarSpec->setType(DI->getType());
@@ -3720,7 +3725,7 @@
VarTemplateSpecializationDecl *VarSpec =
dyn_cast<VarTemplateSpecializationDecl>(Var);
- VarDecl *PatternDecl = 0, *Def = 0;
+ VarDecl *PatternDecl = nullptr, *Def = nullptr;
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Var);
@@ -3930,7 +3935,7 @@
TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(),
TemplateArgs);
Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl(
- VarSpec->getSpecializedTemplate(), Def, 0,
+ VarSpec->getSpecializedTemplate(), Def, nullptr,
VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray()));
if (Var) {
llvm::PointerUnion<VarTemplateDecl *,
@@ -4330,7 +4335,7 @@
if (isInstantiationOf(Ctx, D, *first))
return cast<NamedDecl>(*first);
- return 0;
+ return nullptr;
}
/// \brief Finds the instantiation of the given declaration context
@@ -4420,7 +4425,7 @@
return D;
if (D->isInvalidDecl())
- return 0;
+ return nullptr;
// If we didn't find the decl, then we must have a label decl that hasn't
// been found yet. Lazily instantiate it and return it now.
@@ -4504,7 +4509,7 @@
ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs);
if (!ParentDC)
- return 0;
+ return nullptr;
if (ParentDC != D->getDeclContext()) {
// We performed some kind of instantiation in the parent context,
@@ -4523,13 +4528,13 @@
IsBeingInstantiated = true;
if (!Tag->isBeingDefined() &&
RequireCompleteType(Loc, T, diag::err_incomplete_type))
- return 0;
+ return nullptr;
ParentDC = Tag->getDecl();
}
}
- NamedDecl *Result = 0;
+ NamedDecl *Result = nullptr;
if (D->getDeclName()) {
DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index de850e3..9480c11 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -223,7 +223,7 @@
llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
if (const TemplateTypeParmType *TTP
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
Name = TTP->getIdentifier();
@@ -463,7 +463,7 @@
Pattern->getTypeLoc().getSourceRange(),
EllipsisLoc, NumExpansions);
if (Result.isNull())
- return 0;
+ return nullptr;
TypeLocBuilder TLB;
TLB.pushFullCopy(Pattern->getTypeLoc());
@@ -798,8 +798,8 @@
// The identifier in a sizeof... expression shall name a parameter pack.
LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName);
LookupName(R, S);
-
- NamedDecl *ParameterPack = 0;
+
+ NamedDecl *ParameterPack = nullptr;
ParameterPackValidatorCCC Validator;
switch (R.getResultKind()) {
case LookupResult::Found:
@@ -809,8 +809,8 @@
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), S, 0,
- Validator)) {
+ R.getLookupKind(), S, nullptr,
+ Validator, CTK_ErrorRecovery)) {
diagnoseTypo(Corrected,
PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name,
PDiag(diag::note_parameter_pack_here));
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index e273cb6..dec2b17 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -24,7 +24,6 @@
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
@@ -80,7 +79,8 @@
StringRef name = attr.getName()->getName();
// The GC attributes are usually written with macros; special-case them.
- IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident : 0;
+ IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident
+ : nullptr;
if (useExpansionLoc && loc.isMacroID() && II) {
if (II->isStr("strong")) {
if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
@@ -224,14 +224,14 @@
assert(hasSavedAttrs);
if (savedAttrs.empty()) {
- getMutableDeclSpec().getAttributes().set(0);
+ getMutableDeclSpec().getAttributes().set(nullptr);
return;
}
getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
savedAttrs[i]->setNext(savedAttrs[i+1]);
- savedAttrs.back()->setNext(0);
+ savedAttrs.back()->setNext(nullptr);
}
};
}
@@ -311,7 +311,7 @@
unsigned i) {
assert(i <= declarator.getNumTypeObjects());
- DeclaratorChunk *result = 0;
+ DeclaratorChunk *result = nullptr;
// First, look inwards past parens for a function declarator.
for (; i != 0; --i) {
@@ -379,7 +379,7 @@
case DeclaratorChunk::BlockPointer: {
// But don't move an ARC ownership attribute to the return type
// of a block.
- DeclaratorChunk *destChunk = 0;
+ DeclaratorChunk *destChunk = nullptr;
if (state.isProcessingDeclSpec() &&
attr.getKind() == AttributeList::AT_ObjCOwnership)
destChunk = maybeMovePastReturnType(declarator, i - 1);
@@ -663,7 +663,7 @@
/*HasProto=*/true,
/*IsAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
- /*ArgInfo=*/0,
+ /*ArgInfo=*/nullptr,
/*NumArgs=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
@@ -675,10 +675,10 @@
/*MutableLoc=*/NoLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
- /*Exceptions=*/0,
- /*ExceptionRanges=*/0,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
- /*NoexceptExpr=*/0,
+ /*NoexceptExpr=*/nullptr,
loc, loc, declarator));
// For consistency, make sure the state still has us as processing
@@ -852,7 +852,7 @@
break;
}
case DeclSpec::TST_int128:
- if (!S.PP.getTargetInfo().hasInt128Type())
+ if (!S.Context.getTargetInfo().hasInt128Type())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported);
if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
Result = Context.UnsignedInt128Ty;
@@ -1312,6 +1312,59 @@
return S.Context.getQualifiedType(type, qs);
}
+static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
+ std::string Quals =
+ Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
+
+ switch (FnTy->getRefQualifier()) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ if (!Quals.empty())
+ Quals += ' ';
+ Quals += '&';
+ break;
+
+ case RQ_RValue:
+ if (!Quals.empty())
+ Quals += ' ';
+ Quals += "&&";
+ break;
+ }
+
+ return Quals;
+}
+
+namespace {
+/// Kinds of declarator that cannot contain a qualified function type.
+///
+/// C++98 [dcl.fct]p4 / C++11 [dcl.fct]p6:
+/// a function type with a cv-qualifier or a ref-qualifier can only appear
+/// at the topmost level of a type.
+///
+/// Parens and member pointers are permitted. We don't diagnose array and
+/// function declarators, because they don't allow function types at all.
+///
+/// The values of this enum are used in diagnostics.
+enum QualifiedFunctionKind { QFK_BlockPointer, QFK_Pointer, QFK_Reference };
+}
+
+/// Check whether the type T is a qualified function type, and if it is,
+/// diagnose that it cannot be contained within the given kind of declarator.
+static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc,
+ QualifiedFunctionKind QFK) {
+ // Does T refer to a function type with a cv-qualifier or a ref-qualifier?
+ const FunctionProtoType *FPT = T->getAs<FunctionProtoType>();
+ if (!FPT || (FPT->getTypeQuals() == 0 && FPT->getRefQualifier() == RQ_None))
+ return false;
+
+ S.Diag(Loc, diag::err_compound_qualified_function_type)
+ << QFK << isa<FunctionType>(T.IgnoreParens()) << T
+ << getFunctionQualifiersAsString(FPT);
+ return true;
+}
+
/// \brief Build a pointer type.
///
/// \param T The type to which we'll be building a pointer.
@@ -1334,6 +1387,9 @@
return QualType();
}
+ if (checkQualifiedFunction(*this, T, Loc, QFK_Pointer))
+ return QualType();
+
assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
// In ARC, it is forbidden to build pointers to unqualified pointers.
@@ -1393,6 +1449,9 @@
return QualType();
}
+ if (checkQualifiedFunction(*this, T, Loc, QFK_Reference))
+ return QualType();
+
// In ARC, it is forbidden to build references to unqualified pointers.
if (getLangOpts().ObjCAutoRefCount)
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
@@ -1532,7 +1591,7 @@
llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
if (!ArraySize) {
if (ASM == ArrayType::Star)
- T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
+ T = Context.getVariableArrayType(T, nullptr, ASM, Quals, Brackets);
else
T = Context.getIncompleteArrayType(T, ASM, Quals);
} else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
@@ -1804,17 +1863,20 @@
return QualType();
}
+ if (checkQualifiedFunction(*this, T, Loc, QFK_BlockPointer))
+ return QualType();
+
return Context.getBlockPointerType(T);
}
QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
QualType QT = Ty.get();
if (QT.isNull()) {
- if (TInfo) *TInfo = 0;
+ if (TInfo) *TInfo = nullptr;
return QualType();
}
- TypeSourceInfo *DI = 0;
+ TypeSourceInfo *DI = nullptr;
if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
QT = LIT->getType();
DI = LIT->getTypeSourceInfo();
@@ -2046,10 +2108,10 @@
Sema &SemaRef = state.getSema();
Declarator &D = state.getDeclarator();
QualType T;
- ReturnTypeInfo = 0;
+ ReturnTypeInfo = nullptr;
// The TagDecl owned by the DeclSpec.
- TagDecl *OwnedTagDecl = 0;
+ TagDecl *OwnedTagDecl = nullptr;
bool ContainsPlaceholderType = false;
@@ -2271,67 +2333,7 @@
return T;
}
-static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
- std::string Quals =
- Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
-
- switch (FnTy->getRefQualifier()) {
- case RQ_None:
- break;
-
- case RQ_LValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += '&';
- break;
-
- case RQ_RValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += "&&";
- break;
- }
-
- return Quals;
-}
-
-/// Check that the function type T, which has a cv-qualifier or a ref-qualifier,
-/// can be contained within the declarator chunk DeclType, and produce an
-/// appropriate diagnostic if not.
-static void checkQualifiedFunction(Sema &S, QualType T,
- DeclaratorChunk &DeclType) {
- // C++98 [dcl.fct]p4 / C++11 [dcl.fct]p6: a function type with a
- // cv-qualifier or a ref-qualifier can only appear at the topmost level
- // of a type.
- int DiagKind = -1;
- switch (DeclType.Kind) {
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::MemberPointer:
- // These cases are permitted.
- return;
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Function:
- // These cases don't allow function types at all; no need to diagnose the
- // qualifiers separately.
- return;
- case DeclaratorChunk::BlockPointer:
- DiagKind = 0;
- break;
- case DeclaratorChunk::Pointer:
- DiagKind = 1;
- break;
- case DeclaratorChunk::Reference:
- DiagKind = 2;
- break;
- }
-
- assert(DiagKind != -1);
- S.Diag(DeclType.Loc, diag::err_compound_qualified_function_type)
- << DiagKind << isa<FunctionType>(T.IgnoreParens()) << T
- << getFunctionQualifiersAsString(T->castAs<FunctionProtoType>());
-}
-
-/// Produce an approprioate diagnostic for an ambiguity between a function
+/// Produce an appropriate diagnostic for an ambiguity between a function
/// declarator and a C++ direct-initializer.
static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
DeclaratorChunk &DeclType, QualType RT) {
@@ -2396,7 +2398,7 @@
// declaration.
SourceRange Range = FTI.Params[0].Param->getSourceRange();
SourceLocation B = Range.getBegin();
- SourceLocation E = S.PP.getLocForEndOfToken(Range.getEnd());
+ SourceLocation E = S.getLocForEndOfToken(Range.getEnd());
// FIXME: Maybe we should suggest adding braces instead of parens
// in C++11 for classes that don't have an initializer_list constructor.
S.Diag(B, diag::note_additional_parens_for_variable_declaration)
@@ -2547,10 +2549,7 @@
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
- if (IsQualifiedFunction) {
- checkQualifiedFunction(S, T, DeclType);
- IsQualifiedFunction = DeclType.Kind == DeclaratorChunk::Paren;
- }
+ IsQualifiedFunction &= DeclType.Kind == DeclaratorChunk::Paren;
switch (DeclType.Kind) {
case DeclaratorChunk::Paren:
T = S.BuildParenType(T);
@@ -2763,10 +2762,10 @@
SourceLocation DiagLoc, FixitLoc;
if (TInfo) {
DiagLoc = TInfo->getTypeLoc().getLocStart();
- FixitLoc = S.PP.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd());
+ FixitLoc = S.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd());
} else {
DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
- FixitLoc = S.PP.getLocForEndOfToken(D.getDeclSpec().getLocEnd());
+ FixitLoc = S.getLocForEndOfToken(D.getDeclSpec().getLocEnd());
}
S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value)
<< 0 << T
@@ -2869,10 +2868,10 @@
}
if (!Overloadable)
- S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
+ S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param);
}
- if (FTI.NumParams && FTI.Params[0].Param == 0) {
+ if (FTI.NumParams && FTI.Params[0].Param == nullptr) {
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
// definition.
S.Diag(FTI.Params[0].IdentLoc,
@@ -2892,10 +2891,10 @@
: FTI.RefQualifierIsLValueRef? RQ_LValue
: RQ_RValue;
- // Otherwise, we have a function with an argument list that is
+ // Otherwise, we have a function with a parameter list that is
// potentially variadic.
- SmallVector<QualType, 16> ArgTys;
- ArgTys.reserve(FTI.NumParams);
+ SmallVector<QualType, 16> ParamTys;
+ ParamTys.reserve(FTI.NumParams);
SmallVector<bool, 16> ConsumedParameters;
ConsumedParameters.reserve(FTI.NumParams);
@@ -2903,40 +2902,40 @@
for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
- QualType ArgTy = Param->getType();
- assert(!ArgTy.isNull() && "Couldn't parse type?");
+ QualType ParamTy = Param->getType();
+ assert(!ParamTy.isNull() && "Couldn't parse type?");
- // Look for 'void'. void is allowed only as a single argument to a
+ // Look for 'void'. void is allowed only as a single parameter to a
// function with no other parameters (C99 6.7.5.3p10). We record
- // int(void) as a FunctionProtoType with an empty argument list.
- if (ArgTy->isVoidType()) {
+ // int(void) as a FunctionProtoType with an empty parameter list.
+ if (ParamTy->isVoidType()) {
// If this is something like 'float(int, void)', reject it. 'void'
// is an incomplete type (C99 6.2.5p19) and function decls cannot
- // have arguments of incomplete type.
+ // have parameters of incomplete type.
if (FTI.NumParams != 1 || FTI.isVariadic) {
S.Diag(DeclType.Loc, diag::err_void_only_param);
- ArgTy = Context.IntTy;
- Param->setType(ArgTy);
+ ParamTy = Context.IntTy;
+ Param->setType(ParamTy);
} else if (FTI.Params[i].Ident) {
// Reject, but continue to parse 'int(void abc)'.
S.Diag(FTI.Params[i].IdentLoc, diag::err_param_with_void_type);
- ArgTy = Context.IntTy;
- Param->setType(ArgTy);
+ ParamTy = Context.IntTy;
+ Param->setType(ParamTy);
} else {
// Reject, but continue to parse 'float(const void)'.
- if (ArgTy.hasQualifiers())
+ if (ParamTy.hasQualifiers())
S.Diag(DeclType.Loc, diag::err_void_param_qualified);
- // Do not add 'void' to the ArgTys list.
+ // Do not add 'void' to the list.
break;
}
- } else if (ArgTy->isHalfType()) {
- // Disallow half FP arguments.
+ } else if (ParamTy->isHalfType()) {
+ // Disallow half FP parameters.
// FIXME: This really should be in BuildFunctionType.
if (S.getLangOpts().OpenCL) {
if (!S.getOpenCLOptions().cl_khr_fp16) {
S.Diag(Param->getLocation(),
- diag::err_opencl_half_argument) << ArgTy;
+ diag::err_opencl_half_param) << ParamTy;
D.setInvalidType();
Param->setInvalidDecl();
}
@@ -2946,12 +2945,12 @@
D.setInvalidType();
}
} else if (!FTI.hasPrototype) {
- if (ArgTy->isPromotableIntegerType()) {
- ArgTy = Context.getPromotedIntegerType(ArgTy);
+ if (ParamTy->isPromotableIntegerType()) {
+ ParamTy = Context.getPromotedIntegerType(ParamTy);
Param->setKNRPromoted(true);
- } else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) {
+ } else if (const BuiltinType* BTy = ParamTy->getAs<BuiltinType>()) {
if (BTy->getKind() == BuiltinType::Float) {
- ArgTy = Context.DoubleTy;
+ ParamTy = Context.DoubleTy;
Param->setKNRPromoted(true);
}
}
@@ -2963,7 +2962,7 @@
HasAnyConsumedParameters |= Consumed;
}
- ArgTys.push_back(ArgTy);
+ ParamTys.push_back(ParamTy);
}
if (HasAnyConsumedParameters)
@@ -2972,7 +2971,7 @@
SmallVector<QualType, 4> Exceptions;
SmallVector<ParsedType, 2> DynamicExceptions;
SmallVector<SourceRange, 2> DynamicExceptionRanges;
- Expr *NoexceptExpr = 0;
+ Expr *NoexceptExpr = nullptr;
if (FTI.getExceptionSpecType() == EST_Dynamic) {
// FIXME: It's rather inefficient to have to split into two vectors
@@ -2995,7 +2994,7 @@
Exceptions,
EPI);
- T = Context.getFunctionType(T, ArgTys, EPI);
+ T = Context.getFunctionType(T, ParamTys, EPI);
}
break;
@@ -3094,6 +3093,13 @@
// alias-declaration,
// - the type-id in the default argument of a type-parameter, or
// - the type-id of a template-argument for a type-parameter
+ //
+ // FIXME: Checking this here is insufficient. We accept-invalid on:
+ //
+ // template<typename T> struct S { void f(T); };
+ // S<int() const> s;
+ //
+ // ... for instance.
if (IsQualifiedFunction &&
!(!FreeFunction &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
@@ -3251,7 +3257,7 @@
TypeProcessingState state(*this, D);
- TypeSourceInfo *ReturnTypeInfo = 0;
+ TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
if (T.isNull())
return Context.getNullTypeSourceInfo();
@@ -3286,7 +3292,7 @@
if (attr->getKind() == AttributeList::AT_ObjCOwnership)
return;
- const char *attrStr = 0;
+ const char *attrStr = nullptr;
switch (ownership) {
case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break;
@@ -3305,7 +3311,7 @@
// so that we don't make an AttributedType for it).
AttributeList *attr = D.getAttributePool()
.create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
- /*scope*/ 0, SourceLocation(),
+ /*scope*/ nullptr, SourceLocation(),
/*args*/ &Args, 1, AttributeList::AS_GNU);
spliceAttrIntoList(*attr, chunk.getAttrListRef());
@@ -3366,7 +3372,7 @@
TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
TypeProcessingState state(*this, D);
- TypeSourceInfo *ReturnTypeInfo = 0;
+ TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
if (declSpecTy.isNull())
return Context.getNullTypeSourceInfo();
@@ -3516,7 +3522,7 @@
Visit(TL.getPointeeLoc());
}
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
// If we got no declarator info from previous Sema routines,
@@ -3548,7 +3554,7 @@
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
@@ -3558,7 +3564,7 @@
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
@@ -3581,7 +3587,7 @@
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (DS.getTypeSpecType() == TST_typename) {
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>());
@@ -3597,7 +3603,7 @@
}
void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.copy(TInfo->getTypeLoc().castAs<DependentNameTypeLoc>());
@@ -3605,7 +3611,7 @@
void VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.copy(
@@ -3621,7 +3627,7 @@
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
@@ -3859,7 +3865,8 @@
TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// C99 6.7.6: Type names have no identifier. This is already validated by
// the parser.
- assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
+ assert(D.getIdentifier() == nullptr &&
+ "Type name should have no identifier!");
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
@@ -4264,7 +4271,7 @@
} else {
const Type *DTy = Ty->getUnqualifiedDesugaredType();
if (Ty == DTy) {
- Fn = 0;
+ Fn = nullptr;
return;
}
@@ -4274,7 +4281,7 @@
}
}
- bool isFunctionType() const { return (Fn != 0); }
+ bool isFunctionType() const { return (Fn != nullptr); }
const FunctionType *get() const { return Fn; }
QualType wrap(Sema &S, const FunctionType *New) {
@@ -4731,7 +4738,8 @@
// now.
bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 ||
Triple.getArch() == llvm::Triple::aarch64_be ||
- Triple.getArch() == llvm::Triple::arm64;
+ Triple.getArch() == llvm::Triple::arm64 ||
+ Triple.getArch() == llvm::Triple::arm64_be;
if (VecKind == VectorType::NeonPolyVector) {
if (IsPolyUnsigned) {
// AArch64 polynomial vectors are unsigned and support poly64.
@@ -4750,7 +4758,8 @@
// float64_t on AArch64.
bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 ||
Triple.getArch() == llvm::Triple::aarch64_be ||
- Triple.getArch() == llvm::Triple::arm64;
+ Triple.getArch() == llvm::Triple::arm64 ||
+ Triple.getArch() == llvm::Triple::arm64_be;
if (Is64Bit && BTy->getKind() == BuiltinType::Double)
return true;
@@ -5075,6 +5084,69 @@
return false;
}
+/// \brief Determine whether there is any declaration of \p D that was ever a
+/// definition (perhaps before module merging) and is currently visible.
+/// \param D The definition of the entity.
+/// \param Suggested Filled in with the declaration that should be made visible
+/// in order to provide a definition of this entity.
+static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) {
+ // Easy case: if we don't have modules, all declarations are visible.
+ if (!S.getLangOpts().Modules)
+ return true;
+
+ // If this definition was instantiated from a template, map back to the
+ // pattern from which it was instantiated.
+ //
+ // FIXME: There must be a better place for this to live.
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ auto From = TD->getInstantiatedFrom();
+ if (auto *CTD = From.dyn_cast<ClassTemplateDecl*>()) {
+ while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
+ if (NewCTD->isMemberSpecialization())
+ break;
+ CTD = NewCTD;
+ }
+ RD = CTD->getTemplatedDecl();
+ } else if (auto *CTPSD = From.dyn_cast<
+ ClassTemplatePartialSpecializationDecl *>()) {
+ while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
+ if (NewCTPSD->isMemberSpecialization())
+ break;
+ CTPSD = NewCTPSD;
+ }
+ RD = CTPSD;
+ }
+ } else if (isTemplateInstantiation(RD->getTemplateSpecializationKind())) {
+ while (auto *NewRD = RD->getInstantiatedFromMemberClass())
+ RD = NewRD;
+ }
+ D = RD->getDefinition();
+ } else if (auto *ED = dyn_cast<EnumDecl>(D)) {
+ while (auto *NewED = ED->getInstantiatedFromMemberEnum())
+ ED = NewED;
+ if (ED->isFixed()) {
+ // If the enum has a fixed underlying type, any declaration of it will do.
+ *Suggested = 0;
+ for (auto *Redecl : ED->redecls()) {
+ if (LookupResult::isVisible(S, Redecl))
+ return true;
+ if (Redecl->isThisDeclarationADefinition() ||
+ (Redecl->isCanonicalDecl() && !*Suggested))
+ *Suggested = Redecl;
+ }
+ return false;
+ }
+ D = ED->getDefinition();
+ }
+ assert(D && "missing definition for pattern of instantiated definition");
+
+ // FIXME: If we merged any other decl into D, and that declaration is visible,
+ // then we should consider a definition to be visible.
+ *Suggested = D;
+ return LookupResult::isVisible(S, D);
+}
+
/// \brief The implementation of RequireCompleteType
bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
@@ -5087,24 +5159,24 @@
// "Can't ask whether a dependent type is complete");
// If we have a complete type, we're done.
- NamedDecl *Def = 0;
+ NamedDecl *Def = nullptr;
if (!T->isIncompleteType(&Def)) {
// If we know about the definition but it is not visible, complain.
- if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(*this, Def)) {
+ NamedDecl *SuggestedDef = 0;
+ if (!Diagnoser.Suppressed && Def &&
+ !hasVisibleDefinition(*this, Def, &SuggestedDef)) {
// Suppress this error outside of a SFINAE context if we've already
// emitted the error once for this type. There's no usefulness in
// repeating the diagnostic.
// FIXME: Add a Fix-It that imports the corresponding module or includes
// the header.
- Module *Owner = Def->getOwningModule();
+ Module *Owner = SuggestedDef->getOwningModule();
Diag(Loc, diag::err_module_private_definition)
<< T << Owner->getFullModuleName();
- Diag(Def->getLocation(), diag::note_previous_definition);
+ Diag(SuggestedDef->getLocation(), diag::note_previous_definition);
- if (!isSFINAEContext()) {
- // Recover by implicitly importing this module.
- createImplicitModuleImport(Loc, Owner);
- }
+ // Try to recover by implicitly importing this module.
+ createImplicitModuleImportForErrorRecovery(Loc, Owner);
}
// We lock in the inheritance model once somebody has asked us to ensure
@@ -5150,39 +5222,36 @@
return false;
}
- // FIXME: If there's an unimported definition of this type in a module (for
+ const TagType *Tag = T->getAs<TagType>();
+ const ObjCInterfaceType *IFace = T->getAs<ObjCInterfaceType>();
+
+ // If there's an unimported definition of this type in a module (for
// instance, because we forward declared it, then imported the definition),
// import that definition now.
+ //
// FIXME: What about other cases where an import extends a redeclaration
// chain for a declaration that can be accessed through a mechanism other
// than name lookup (eg, referenced in a template, or a variable whose type
// could be completed by the module)?
+ if (Tag || IFace) {
+ NamedDecl *D =
+ Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl();
- const TagType *Tag = T->getAs<TagType>();
- const ObjCInterfaceType *IFace = 0;
-
- if (Tag) {
// Avoid diagnosing invalid decls as incomplete.
- if (Tag->getDecl()->isInvalidDecl())
+ if (D->isInvalidDecl())
return true;
// Give the external AST source a chance to complete the type.
- if (Tag->getDecl()->hasExternalLexicalStorage()) {
- Context.getExternalSource()->CompleteType(Tag->getDecl());
- if (!Tag->isIncompleteType())
- return false;
- }
- }
- else if ((IFace = T->getAs<ObjCInterfaceType>())) {
- // Avoid diagnosing invalid decls as incomplete.
- if (IFace->getDecl()->isInvalidDecl())
- return true;
+ if (auto *Source = Context.getExternalSource()) {
+ if (Tag)
+ Source->CompleteType(Tag->getDecl());
+ else
+ Source->CompleteType(IFace->getDecl());
- // Give the external AST source a chance to complete the type.
- if (IFace->getDecl()->hasExternalLexicalStorage()) {
- Context.getExternalSource()->CompleteType(IFace->getDecl());
- if (!IFace->isIncompleteType())
- return false;
+ // If the external source completed the type, go through the motions
+ // again to ensure we're allowed to use the completed type.
+ if (!T->isIncompleteType())
+ return RequireCompleteTypeImpl(Loc, T, Diagnoser);
}
}
@@ -5384,7 +5453,7 @@
else {
if (Keyword == ETK_None)
return T;
- NNS = 0;
+ NNS = nullptr;
}
return Context.getElaboratedType(Keyword, NNS, T);
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index f78fca7..3386b5b 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -25,7 +25,6 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Ownership.h"
@@ -372,7 +371,7 @@
/// \returns true if an error occurred, false otherwise.
bool TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall,
SmallVectorImpl<Expr *> &Outputs,
- bool *ArgChanged = 0);
+ bool *ArgChanged = nullptr);
/// \brief Transform the given declaration, which is referenced from a type
/// or expression.
@@ -434,10 +433,10 @@
/// By default, transforms all of the types and declarations within the
/// nested-name-specifier. Subclasses may override this function to provide
/// alternate behavior.
- NestedNameSpecifierLoc TransformNestedNameSpecifierLoc(
- NestedNameSpecifierLoc NNS,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = 0);
+ NestedNameSpecifierLoc
+ TransformNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = nullptr);
/// \brief Transform the given declaration name.
///
@@ -468,11 +467,11 @@
/// By default, transforms the template name by transforming the declarations
/// and nested-name-specifiers that occur within the template name.
/// Subclasses may override this function to provide alternate behavior.
- TemplateName TransformTemplateName(CXXScopeSpec &SS,
- TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = 0);
+ TemplateName
+ TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
+ SourceLocation NameLoc,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = nullptr);
/// \brief Transform the given template argument.
///
@@ -849,7 +848,8 @@
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
TemplateName InstName
- = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(), 0);
+ = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(),
+ nullptr);
if (InstName.isNull())
return QualType();
@@ -867,7 +867,7 @@
getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
if (T.isNull()) return QualType();
- if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == 0)
+ if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == nullptr)
return T;
return SemaRef.Context.getElaboratedType(Keyword,
@@ -913,7 +913,7 @@
if (SemaRef.RequireCompleteDeclContext(SS, DC))
return QualType();
- TagDecl *Tag = 0;
+ TagDecl *Tag = nullptr;
SemaRef.LookupQualifiedName(Result, DC);
switch (Result.getResultKind()) {
case LookupResult::NotFound:
@@ -1080,7 +1080,7 @@
SourceLocation ColonLoc,
Stmt *SubStmt) {
return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt,
- /*CurScope=*/0);
+ /*CurScope=*/nullptr);
}
/// \brief Build a new label statement.
@@ -1187,7 +1187,7 @@
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildReturnStmt(SourceLocation ReturnLoc, Expr *Result) {
- return getSema().ActOnReturnStmt(ReturnLoc, Result);
+ return getSema().BuildReturnStmt(ReturnLoc, Result);
}
/// \brief Build a new declaration statement.
@@ -1333,6 +1333,17 @@
return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
}
+ /// \brief Build a new OpenMP 'collapse' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPCollapseClause(Expr *Num, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPCollapseClause(Num, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// \brief Build a new OpenMP 'default' clause.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1346,6 +1357,19 @@
StartLoc, LParenLoc, EndLoc);
}
+ /// \brief Build a new OpenMP 'proc_bind' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPProcBindClause(OpenMPProcBindClauseKind Kind,
+ SourceLocation KindKwLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPProcBindClause(Kind, KindKwLoc,
+ StartLoc, LParenLoc, EndLoc);
+ }
+
/// \brief Build a new OpenMP 'private' clause.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1382,6 +1406,19 @@
EndLoc);
}
+ /// \brief Build a new OpenMP 'linear' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPLinearClause(VarList, Step, StartLoc, LParenLoc,
+ ColonLoc, EndLoc);
+ }
+
/// \brief Build a new OpenMP 'copyin' clause.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1449,7 +1486,7 @@
SourceLocation StartLoc,
SourceLocation IdLoc,
IdentifierInfo *Id) {
- VarDecl *Var = getSema().BuildExceptionDeclaration(0, Declarator,
+ VarDecl *Var = getSema().BuildExceptionDeclaration(nullptr, Declarator,
StartLoc, IdLoc, Id);
if (Var)
getSema().CurContext->addDecl(Var);
@@ -1599,7 +1636,7 @@
ExprResult RebuildUnaryOperator(SourceLocation OpLoc,
UnaryOperatorKind Opc,
Expr *SubExpr) {
- return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, SubExpr);
+ return getSema().BuildUnaryOp(/*Scope=*/nullptr, OpLoc, Opc, SubExpr);
}
/// \brief Build a new builtin offsetof expression.
@@ -1651,7 +1688,7 @@
SourceLocation LBracketLoc,
Expr *RHS,
SourceLocation RBracketLoc) {
- return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, LHS,
+ return getSema().ActOnArraySubscriptExpr(/*Scope=*/nullptr, LHS,
LBracketLoc, RHS,
RBracketLoc);
}
@@ -1663,8 +1700,8 @@
ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc,
- Expr *ExecConfig = 0) {
- return getSema().ActOnCallExpr(/*Scope=*/0, Callee, LParenLoc,
+ Expr *ExecConfig = nullptr) {
+ return getSema().ActOnCallExpr(/*Scope=*/nullptr, Callee, LParenLoc,
Args, RParenLoc, ExecConfig);
}
@@ -1732,7 +1769,7 @@
ExprResult RebuildBinaryOperator(SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHS, Expr *RHS) {
- return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc, LHS, RHS);
+ return getSema().BuildBinOp(/*Scope=*/nullptr, OpLoc, Opc, LHS, RHS);
}
/// \brief Build a new conditional operator expression.
@@ -1786,9 +1823,9 @@
return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
OpLoc, /*IsArrow*/ false,
SS, SourceLocation(),
- /*FirstQualifierInScope*/ 0,
+ /*FirstQualifierInScope*/ nullptr,
NameInfo,
- /* TemplateArgs */ 0);
+ /* TemplateArgs */ nullptr);
}
/// \brief Build a new initializer list expression.
@@ -2470,7 +2507,7 @@
Sema::LookupMemberName);
ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/IvarLoc,
- SS, 0,
+ SS, nullptr,
false);
if (Result.isInvalid() || Base.isInvalid())
return ExprError();
@@ -2481,9 +2518,9 @@
return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
/*FIXME:*/IvarLoc, IsArrow,
SS, SourceLocation(),
- /*FirstQualifierInScope=*/0,
+ /*FirstQualifierInScope=*/nullptr,
R,
- /*TemplateArgs=*/0);
+ /*TemplateArgs=*/nullptr);
}
/// \brief Build a new Objective-C property reference expression.
@@ -2500,7 +2537,7 @@
bool IsArrow = false;
ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/PropertyLoc,
- SS, 0, false);
+ SS, nullptr, false);
if (Result.isInvalid() || Base.isInvalid())
return ExprError();
@@ -2510,9 +2547,8 @@
return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
/*FIXME:*/PropertyLoc, IsArrow,
SS, SourceLocation(),
- /*FirstQualifierInScope=*/0,
- R,
- /*TemplateArgs=*/0);
+ /*FirstQualifierInScope=*/nullptr,
+ R, /*TemplateArgs=*/nullptr);
}
/// \brief Build a new Objective-C property reference expression.
@@ -2544,7 +2580,7 @@
Sema::LookupMemberName);
ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
OpLoc,
- SS, 0, false);
+ SS, nullptr, false);
if (Result.isInvalid() || Base.isInvalid())
return ExprError();
@@ -2554,9 +2590,9 @@
return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
OpLoc, IsArrow,
SS, SourceLocation(),
- /*FirstQualifierInScope=*/0,
+ /*FirstQualifierInScope=*/nullptr,
R,
- /*TemplateArgs=*/0);
+ /*TemplateArgs=*/nullptr);
}
/// \brief Build a new shuffle vector expression.
@@ -2936,7 +2972,7 @@
switch (QNNS->getKind()) {
case NestedNameSpecifier::Identifier:
- if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0,
+ if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr,
*QNNS->getAsIdentifier(),
Q.getLocalBeginLoc(),
Q.getLocalEndLoc(),
@@ -3004,7 +3040,7 @@
}
// The qualifier-in-scope and object type only apply to the leftmost entity.
- FirstQualifierInScope = 0;
+ FirstQualifierInScope = nullptr;
ObjectType = QualType();
}
@@ -3053,7 +3089,7 @@
NewCanTy = SemaRef.Context.getCanonicalType(NewTInfo->getType());
}
else {
- NewTInfo = 0;
+ NewTInfo = nullptr;
TemporaryBase Rebase(*this, NameInfo.getLoc(), Name);
QualType NewT = getDerived().TransformType(Name.getCXXNameType());
if (NewT.isNull())
@@ -3104,7 +3140,7 @@
if (SS.getScopeRep()) {
// These apply to the scope specifier, not the template.
ObjectType = QualType();
- FirstQualifierInScope = 0;
+ FirstQualifierInScope = nullptr;
}
if (!getDerived().AlwaysRebuild() &&
@@ -3223,7 +3259,7 @@
case TemplateArgument::Type: {
TypeSourceInfo *DI = Input.getTypeSourceInfo();
- if (DI == NULL)
+ if (!DI)
DI = InventTypeSourceInfo(Input.getArgument().getAsType());
DI = getDerived().TransformType(DI);
@@ -3493,7 +3529,7 @@
QualType Result = getDerived().TransformType(TLB, TL);
if (Result.isNull())
- return 0;
+ return nullptr;
return TLB.getTypeSourceInfo(SemaRef.Context, Result);
}
@@ -3637,7 +3673,7 @@
SpecTL.getTemplateNameLoc(),
ObjectType, UnqualLookup);
if (Template.isNull())
- return 0;
+ return nullptr;
Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
Template);
@@ -3651,7 +3687,7 @@
SpecTL.getTemplateNameLoc(),
ObjectType, UnqualLookup);
if (Template.isNull())
- return 0;
+ return nullptr;
Result = getDerived().TransformDependentTemplateSpecializationType(TLB,
SpecTL,
@@ -3663,7 +3699,7 @@
}
if (Result.isNull())
- return 0;
+ return nullptr;
return TLB.getTypeSourceInfo(SemaRef.Context, Result);
}
@@ -3839,7 +3875,7 @@
return QualType();
TypeSourceInfo* OldClsTInfo = TL.getClassTInfo();
- TypeSourceInfo* NewClsTInfo = 0;
+ TypeSourceInfo *NewClsTInfo = nullptr;
if (OldClsTInfo) {
NewClsTInfo = getDerived().TransformType(OldClsTInfo);
if (!NewClsTInfo)
@@ -3946,7 +3982,7 @@
IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result);
NewTL.setLBracketLoc(TL.getLBracketLoc());
NewTL.setRBracketLoc(TL.getRBracketLoc());
- NewTL.setSizeExpr(0);
+ NewTL.setSizeExpr(nullptr);
return Result;
}
@@ -4134,7 +4170,7 @@
ParmVarDecl *OldParm, int indexAdjustment, Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
- TypeSourceInfo *NewDI = 0;
+ TypeSourceInfo *NewDI = nullptr;
if (NumExpansions && isa<PackExpansionType>(OldDI->getType())) {
// If we're substituting into a pack expansion type and we know the
@@ -4149,14 +4185,14 @@
QualType Result = getDerived().TransformType(TLB,
OldExpansionTL.getPatternLoc());
if (Result.isNull())
- return 0;
+ return nullptr;
Result = RebuildPackExpansionType(Result,
OldExpansionTL.getPatternLoc().getSourceRange(),
OldExpansionTL.getEllipsisLoc(),
NumExpansions);
if (Result.isNull())
- return 0;
+ return nullptr;
PackExpansionTypeLoc NewExpansionTL
= TLB.push<PackExpansionTypeLoc>(Result);
@@ -4165,7 +4201,7 @@
} else
NewDI = getDerived().TransformType(OldDI);
if (!NewDI)
- return 0;
+ return nullptr;
if (NewDI == OldDI && indexAdjustment == 0)
return OldParm;
@@ -4178,7 +4214,7 @@
NewDI->getType(),
NewDI,
OldParm->getStorageClass(),
- /* DefArg */ NULL);
+ /* DefArg */ nullptr);
newParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
OldParm->getFunctionScopeIndex() + indexAdjustment);
return newParm;
@@ -4198,7 +4234,7 @@
assert(OldParm->getFunctionScopeIndex() == i);
Optional<unsigned> NumExpansions;
- ParmVarDecl *NewParm = 0;
+ ParmVarDecl *NewParm = nullptr;
if (OldParm->isParameterPack()) {
// We have a function parameter pack that may need to be expanded.
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
@@ -4327,7 +4363,7 @@
OutParamTypes.push_back(NewType);
if (PVars)
- PVars->push_back(0);
+ PVars->push_back(nullptr);
}
// We're done with the pack expansion.
@@ -4344,7 +4380,7 @@
OutParamTypes.push_back(NewType);
if (PVars)
- PVars->push_back(0);
+ PVars->push_back(nullptr);
}
// We'll substitute the parameter now without expanding the pack
@@ -4366,7 +4402,7 @@
OutParamTypes.push_back(NewType);
if (PVars)
- PVars->push_back(0);
+ PVars->push_back(nullptr);
}
#ifndef NDEBUG
@@ -4384,7 +4420,7 @@
QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL) {
- return getDerived().TransformFunctionProtoType(TLB, TL, 0, 0);
+ return getDerived().TransformFunctionProtoType(TLB, TL, nullptr, 0);
}
template<typename Derived>
@@ -4592,8 +4628,8 @@
const DecltypeType *T = TL.getTypePtr();
// decltype expressions are not potentially evaluated contexts
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, 0,
- /*IsDecltype=*/ true);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated,
+ nullptr, /*IsDecltype=*/ true);
ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
if (E.isInvalid())
@@ -5419,7 +5455,7 @@
TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
// Transform the condition
ExprResult Cond;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (S->getConditionVariable()) {
ConditionVar
= cast_or_null<VarDecl>(
@@ -5436,7 +5472,7 @@
// Convert the condition to a boolean value.
if (S->getCond()) {
- ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getIfLoc(),
+ ExprResult CondE = getSema().ActOnBooleanCondition(nullptr, S->getIfLoc(),
Cond.get());
if (CondE.isInvalid())
return StmtError();
@@ -5476,7 +5512,7 @@
TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
// Transform the condition.
ExprResult Cond;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (S->getConditionVariable()) {
ConditionVar
= cast_or_null<VarDecl>(
@@ -5514,7 +5550,7 @@
TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
// Transform the condition
ExprResult Cond;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (S->getConditionVariable()) {
ConditionVar
= cast_or_null<VarDecl>(
@@ -5531,7 +5567,8 @@
if (S->getCond()) {
// Convert the condition to a boolean value.
- ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getWhileLoc(),
+ ExprResult CondE = getSema().ActOnBooleanCondition(nullptr,
+ S->getWhileLoc(),
Cond.get());
if (CondE.isInvalid())
return StmtError();
@@ -5591,7 +5628,7 @@
// Transform the condition
ExprResult Cond;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (S->getConditionVariable()) {
ConditionVar
= cast_or_null<VarDecl>(
@@ -5608,7 +5645,8 @@
if (S->getCond()) {
// Convert the condition to a boolean value.
- ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getForLoc(),
+ ExprResult CondE = getSema().ActOnBooleanCondition(nullptr,
+ S->getForLoc(),
Cond.get());
if (CondE.isInvalid())
return StmtError();
@@ -5863,9 +5901,9 @@
StmtResult
TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
// Transform the @catch parameter, if there is one.
- VarDecl *Var = 0;
+ VarDecl *Var = nullptr;
if (VarDecl *FromVar = S->getCatchParamDecl()) {
- TypeSourceInfo *TSInfo = 0;
+ TypeSourceInfo *TSInfo = nullptr;
if (FromVar->getTypeSourceInfo()) {
TSInfo = getDerived().TransformType(FromVar->getTypeSourceInfo());
if (!TSInfo)
@@ -6016,7 +6054,7 @@
template <typename Derived>
StmtResult TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
// Transform the exception declaration, if any.
- VarDecl *Var = 0;
+ VarDecl *Var = nullptr;
if (VarDecl *ExceptionDecl = S->getExceptionDecl()) {
TypeSourceInfo *T =
getDerived().TransformType(ExceptionDecl->getTypeSourceInfo());
@@ -6169,7 +6207,7 @@
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
bool Dependent = false;
- switch (getSema().CheckMicrosoftIfExistsSymbol(/*S=*/0, SS, NameInfo)) {
+ switch (getSema().CheckMicrosoftIfExistsSymbol(/*S=*/nullptr, SS, NameInfo)) {
case Sema::IER_Exists:
if (S->isIfExists())
break;
@@ -6301,7 +6339,7 @@
TClauses.push_back(Clause);
}
else {
- TClauses.push_back(0);
+ TClauses.push_back(nullptr);
}
}
if (!D->getAssociatedStmt()) {
@@ -6324,7 +6362,7 @@
StmtResult
TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, 0);
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr);
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -6334,7 +6372,7 @@
StmtResult
TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, 0);
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr);
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -6345,7 +6383,7 @@
TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
ExprResult Cond = getDerived().TransformExpr(C->getCondition());
if (Cond.isInvalid())
- return 0;
+ return nullptr;
return getDerived().RebuildOMPIfClause(Cond.take(), C->getLocStart(),
C->getLParenLoc(), C->getLocEnd());
}
@@ -6355,7 +6393,7 @@
TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) {
ExprResult NumThreads = getDerived().TransformExpr(C->getNumThreads());
if (NumThreads.isInvalid())
- return 0;
+ return nullptr;
return getDerived().RebuildOMPNumThreadsClause(NumThreads.take(),
C->getLocStart(),
C->getLParenLoc(),
@@ -6367,11 +6405,21 @@
TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
ExprResult E = getDerived().TransformExpr(C->getSafelen());
if (E.isInvalid())
- return 0;
+ return nullptr;
return getDerived().RebuildOMPSafelenClause(
E.take(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPCollapseClause(OMPCollapseClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getNumForLoops());
+ if (E.isInvalid())
+ return 0;
+ return getDerived().RebuildOMPCollapseClause(
+ E.take(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
template<typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
@@ -6384,13 +6432,23 @@
template<typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPProcBindClause(OMPProcBindClause *C) {
+ return getDerived().RebuildOMPProcBindClause(C->getProcBindKind(),
+ C->getProcBindKindKwLoc(),
+ C->getLocStart(),
+ C->getLParenLoc(),
+ C->getLocEnd());
+}
+
+template<typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
- for (auto *I : C->varlists()) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(I));
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
if (EVar.isInvalid())
- return 0;
+ return nullptr;
Vars.push_back(EVar.take());
}
return getDerived().RebuildOMPPrivateClause(Vars,
@@ -6405,10 +6463,10 @@
OMPFirstprivateClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
- for (auto *I : C->varlists()) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(I));
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
if (EVar.isInvalid())
- return 0;
+ return nullptr;
Vars.push_back(EVar.take());
}
return getDerived().RebuildOMPFirstprivateClause(Vars,
@@ -6422,10 +6480,10 @@
TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
- for (auto *I : C->varlists()) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(I));
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
if (EVar.isInvalid())
- return 0;
+ return nullptr;
Vars.push_back(EVar.take());
}
return getDerived().RebuildOMPSharedClause(Vars,
@@ -6436,13 +6494,32 @@
template<typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.take());
+ }
+ ExprResult Step = getDerived().TransformExpr(C->getStep());
+ if (Step.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPLinearClause(
+ Vars, Step.take(), C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
+ C->getLocEnd());
+}
+
+template<typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
- for (auto *I : C->varlists()) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(I));
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
if (EVar.isInvalid())
- return 0;
+ return nullptr;
Vars.push_back(EVar.take());
}
return getDerived().RebuildOMPCopyinClause(Vars,
@@ -6497,7 +6574,7 @@
return SemaRef.Owned(E);
}
- TemplateArgumentListInfo TransArgs, *TemplateArgs = 0;
+ TemplateArgumentListInfo TransArgs, *TemplateArgs = nullptr;
if (E->hasExplicitTemplateArgs()) {
TemplateArgs = &TransArgs;
TransArgs.setLAngleLoc(E->getLAngleLoc());
@@ -6568,7 +6645,7 @@
return ExprError();
AssocTypes.push_back(AssocType);
} else {
- AssocTypes.push_back(0);
+ AssocTypes.push_back(nullptr);
}
ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i));
@@ -6873,14 +6950,14 @@
}
// FIXME: Bogus source location for the operator
- SourceLocation FakeOperatorLoc
- = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+ SourceLocation FakeOperatorLoc =
+ SemaRef.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
// FIXME: to do this check properly, we will need to preserve the
// first-qualifier-in-scope here, just in case we had a dependent
// base (and therefore couldn't do the check) and a
// nested-name-qualifier (and therefore could do the lookup).
- NamedDecl *FirstQualifierInScope = 0;
+ NamedDecl *FirstQualifierInScope = nullptr;
return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc,
E->isArrow(),
@@ -6890,7 +6967,7 @@
Member,
FoundDecl,
(E->hasExplicitTemplateArgs()
- ? &TransArgs : 0),
+ ? &TransArgs : nullptr),
FirstQualifierInScope);
}
@@ -6945,7 +7022,7 @@
return getDerived().RebuildConditionalOperator(commonExpr.take(),
e->getQuestionLoc(),
- 0,
+ nullptr,
e->getColonLoc(),
rhs.get());
}
@@ -7047,8 +7124,8 @@
return SemaRef.Owned(E);
// FIXME: Bad source location
- SourceLocation FakeOperatorLoc
- = SemaRef.PP.getLocForEndOfToken(E->getBase()->getLocEnd());
+ SourceLocation FakeOperatorLoc =
+ SemaRef.getLocForEndOfToken(E->getBase()->getLocEnd());
return getDerived().RebuildExtVectorElementExpr(Base.get(), FakeOperatorLoc,
E->getAccessorLoc(),
E->getAccessor());
@@ -7284,9 +7361,8 @@
return ExprError();
// FIXME: Poor location information
- SourceLocation FakeLParenLoc
- = SemaRef.PP.getLocForEndOfToken(
- static_cast<Expr *>(Object.get())->getLocEnd());
+ SourceLocation FakeLParenLoc = SemaRef.getLocForEndOfToken(
+ static_cast<Expr *>(Object.get())->getLocEnd());
// Transform the call arguments.
SmallVector<Expr*, 8> Args;
@@ -7661,7 +7737,7 @@
return ExprError();
// Transform new operator and delete operator.
- FunctionDecl *OperatorNew = 0;
+ FunctionDecl *OperatorNew = nullptr;
if (E->getOperatorNew()) {
OperatorNew = cast_or_null<FunctionDecl>(
getDerived().TransformDecl(E->getLocStart(),
@@ -7670,7 +7746,7 @@
return ExprError();
}
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
if (E->getOperatorDelete()) {
OperatorDelete = cast_or_null<FunctionDecl>(
getDerived().TransformDecl(E->getLocStart(),
@@ -7755,7 +7831,7 @@
return ExprError();
// Transform the delete operator, if known.
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
if (E->getOperatorDelete()) {
OperatorDelete = cast_or_null<FunctionDecl>(
getDerived().TransformDecl(E->getLocStart(),
@@ -7801,7 +7877,7 @@
ParsedType ObjectTypePtr;
bool MayBePseudoDestructor = false;
- Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
+ Base = SemaRef.ActOnStartCXXMemberReference(nullptr, Base.get(),
E->getOperatorLoc(),
E->isArrow()? tok::arrow : tok::period,
ObjectTypePtr,
@@ -7824,7 +7900,7 @@
if (E->getDestroyedTypeInfo()) {
TypeSourceInfo *DestroyedTypeInfo
= getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
- ObjectType, 0, SS);
+ ObjectType, nullptr, SS);
if (!DestroyedTypeInfo)
return ExprError();
Destroyed = DestroyedTypeInfo;
@@ -7838,7 +7914,7 @@
ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(),
*E->getDestroyedTypeIdentifier(),
E->getDestroyedTypeLoc(),
- /*Scope=*/0,
+ /*Scope=*/nullptr,
SS, ObjectTypePtr,
false);
if (!T)
@@ -7849,11 +7925,11 @@
E->getDestroyedTypeLoc());
}
- TypeSourceInfo *ScopeTypeInfo = 0;
+ TypeSourceInfo *ScopeTypeInfo = nullptr;
if (E->getScopeTypeInfo()) {
CXXScopeSpec EmptySS;
ScopeTypeInfo = getDerived().TransformTypeInObjectScope(
- E->getScopeTypeInfo(), ObjectType, 0, EmptySS);
+ E->getScopeTypeInfo(), ObjectType, nullptr, EmptySS);
if (!ScopeTypeInfo)
return ExprError();
}
@@ -8172,10 +8248,10 @@
return SemaRef.Owned(E);
return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
- TemplateKWLoc,
- NameInfo,
- /*TemplateArgs*/ 0,
- IsAddressOfOperand);
+ TemplateKWLoc,
+ NameInfo,
+ /*TemplateArgs*/nullptr,
+ IsAddressOfOperand);
}
TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
@@ -8350,8 +8426,8 @@
TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
FunctionProtoTypeLoc OldCallOpFPTL =
OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
- TypeSourceInfo *NewCallOpTSI = 0;
-
+ TypeSourceInfo *NewCallOpTSI = nullptr;
+
const bool CallOpWasAlreadyTransformed =
getDerived().AlreadyTransformed(OldCallOpTSI->getType());
@@ -8367,7 +8443,7 @@
TypeLocBuilder NewCallOpTLBuilder;
QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder,
OldCallOpFPTL,
- 0, 0);
+ nullptr, 0);
NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
NewCallOpType);
}
@@ -8565,7 +8641,7 @@
getSema().PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
if (Invalid) {
- getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0,
+ getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr,
/*IsInstantiation=*/true);
return ExprError();
}
@@ -8573,13 +8649,14 @@
// Instantiate the body of the lambda expression.
StmtResult Body = getDerived().TransformStmt(E->getBody());
if (Body.isInvalid()) {
- getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0,
+ getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr,
/*IsInstantiation=*/true);
return ExprError();
}
return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(),
- /*CurScope=*/0, /*IsInstantiation=*/true);
+ /*CurScope=*/nullptr,
+ /*IsInstantiation=*/true);
}
template<typename Derived>
@@ -8614,7 +8691,7 @@
TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
CXXDependentScopeMemberExpr *E) {
// Transform the base of the expression.
- ExprResult Base((Expr*) 0);
+ ExprResult Base((Expr*) nullptr);
Expr *OldBase;
QualType BaseType;
QualType ObjectType;
@@ -8627,7 +8704,7 @@
// Start the member reference and compute the object's type.
ParsedType ObjectTy;
bool MayBePseudoDestructor = false;
- Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
+ Base = SemaRef.ActOnStartCXXMemberReference(nullptr, Base.get(),
E->getOperatorLoc(),
E->isArrow()? tok::arrow : tok::period,
ObjectTy,
@@ -8638,7 +8715,7 @@
ObjectType = ObjectTy.get();
BaseType = ((Expr*) Base.get())->getType();
} else {
- OldBase = 0;
+ OldBase = nullptr;
BaseType = getDerived().TransformType(E->getBaseType());
ObjectType = BaseType->getAs<PointerType>()->getPointeeType();
}
@@ -8690,7 +8767,7 @@
TemplateKWLoc,
FirstQualifierInScope,
NameInfo,
- /*TemplateArgs*/ 0);
+ /*TemplateArgs*/nullptr);
}
TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
@@ -8714,7 +8791,7 @@
ExprResult
TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) {
// Transform the base of the expression.
- ExprResult Base((Expr*) 0);
+ ExprResult Base((Expr*) nullptr);
QualType BaseType;
if (!Old->isImplicitAccess()) {
Base = getDerived().TransformExpr(Old->getBase());
@@ -8798,7 +8875,7 @@
// first-qualifier-in-scope here, just in case we had a dependent
// base (and therefore couldn't do the check) and a
// nested-name-qualifier (and therefore could do the lookup).
- NamedDecl *FirstQualifierInScope = 0;
+ NamedDecl *FirstQualifierInScope = nullptr;
return getDerived().RebuildUnresolvedMemberExpr(Base.get(),
BaseType,
@@ -8809,7 +8886,7 @@
FirstQualifierInScope,
R,
(Old->hasExplicitTemplateArgs()
- ? &TransArgs : 0));
+ ? &TransArgs : nullptr));
}
template<typename Derived>
@@ -9343,7 +9420,7 @@
TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
BlockDecl *oldBlock = E->getBlockDecl();
- SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/0);
+ SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/nullptr);
BlockScopeInfo *blockScope = SemaRef.getCurBlock();
blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic());
@@ -9357,8 +9434,8 @@
if (getDerived().TransformFunctionTypeParams(E->getCaretLocation(),
oldBlock->param_begin(),
oldBlock->param_size(),
- 0, paramTypes, ¶ms)) {
- getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0);
+ nullptr, paramTypes, ¶ms)) {
+ getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr);
return ExprError();
}
@@ -9383,7 +9460,7 @@
// Transform the body
StmtResult body = getDerived().TransformStmt(E->getBody());
if (body.isInvalid()) {
- getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0);
+ getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr);
return ExprError();
}
@@ -9409,7 +9486,7 @@
#endif
return SemaRef.ActOnBlockStmtExpr(E->getCaretLocation(), body.get(),
- /*Scope=*/0);
+ /*Scope=*/nullptr);
}
template<typename Derived>
@@ -9516,7 +9593,7 @@
const llvm::APInt &Size,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
+ return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, nullptr,
IndexTypeQuals, BracketsRange);
}
@@ -9526,7 +9603,7 @@
ArrayType::ArraySizeModifier SizeMod,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
+ return getDerived().RebuildArrayType(ElementType, SizeMod, nullptr, nullptr,
IndexTypeQuals, BracketsRange);
}
@@ -9537,7 +9614,7 @@
Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+ return getDerived().RebuildArrayType(ElementType, SizeMod, nullptr,
SizeExpr,
IndexTypeQuals, BracketsRange);
}
@@ -9549,7 +9626,7 @@
Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+ return getDerived().RebuildArrayType(ElementType, SizeMod, nullptr,
SizeExpr,
IndexTypeQuals, BracketsRange);
}
@@ -9681,7 +9758,7 @@
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
- getSema().ActOnDependentTemplateName(/*Scope=*/0,
+ getSema().ActOnDependentTemplateName(/*Scope=*/nullptr,
SS, TemplateKWLoc, TemplateName,
ParsedType::make(ObjectType),
/*EnteringContext=*/false,
@@ -9701,7 +9778,7 @@
Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations);
SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
Sema::TemplateTy Template;
- getSema().ActOnDependentTemplateName(/*Scope=*/0,
+ getSema().ActOnDependentTemplateName(/*Scope=*/nullptr,
SS, TemplateKWLoc, Name,
ParsedType::make(ObjectType),
/*EnteringContext=*/false,
@@ -9728,8 +9805,8 @@
Second, OpLoc);
} else if (Op == OO_Arrow) {
// -> is never a builtin operation.
- return SemaRef.BuildOverloadedArrowExpr(0, First, OpLoc);
- } else if (Second == 0 || isPostIncDec) {
+ return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
+ } else if (Second == nullptr || isPostIncDec) {
if (!First->getType()->isOverloadableType()) {
// The argument is not of overloadable type, so try to create a
// built-in unary operation.
@@ -9759,9 +9836,6 @@
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) {
assert(ULE->requiresADL());
-
- // FIXME: Do we have to check
- // IsAcceptableNonMemberOperatorCandidate for each of these?
Functions.append(ULE->decls_begin(), ULE->decls_end());
} else {
// If we've resolved this to a particular non-member function, just call
@@ -9774,7 +9848,7 @@
// Add any functions found via argument-dependent lookup.
Expr *Args[2] = { First, Second };
- unsigned NumArgs = 1 + (Second != 0);
+ unsigned NumArgs = 1 + (Second != nullptr);
// Create the overloaded operator invocation for unary operators.
if (NumArgs == 1 || isPostIncDec) {
@@ -9852,18 +9926,31 @@
return getSema().BuildMemberReferenceExpr(Base, BaseType,
OperatorLoc, isArrow,
SS, TemplateKWLoc,
- /*FIXME: FirstQualifier*/ 0,
+ /*FIXME: FirstQualifier*/ nullptr,
NameInfo,
- /*TemplateArgs*/ 0);
+ /*TemplateArgs*/ nullptr);
}
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) {
SourceLocation Loc = S->getLocStart();
- unsigned NumParams = S->getCapturedDecl()->getNumParams();
- getSema().ActOnCapturedRegionStart(Loc, /*CurScope*/0,
- S->getCapturedRegionKind(), NumParams);
+ CapturedDecl *CD = S->getCapturedDecl();
+ unsigned NumParams = CD->getNumParams();
+ unsigned ContextParamPos = CD->getContextParamPosition();
+ SmallVector<Sema::CapturedParamNameType, 4> Params;
+ for (unsigned I = 0; I < NumParams; ++I) {
+ if (I != ContextParamPos) {
+ Params.push_back(
+ std::make_pair(
+ CD->getParam(I)->getName(),
+ getDerived().TransformType(CD->getParam(I)->getType())));
+ } else {
+ Params.push_back(std::make_pair(StringRef(), QualType()));
+ }
+ }
+ getSema().ActOnCapturedRegionStart(Loc, /*CurScope*/nullptr,
+ S->getCapturedRegionKind(), Params);
StmtResult Body = getDerived().TransformStmt(S->getCapturedStmt());
if (Body.isInvalid()) {
diff --git a/lib/Sema/TypeLocBuilder.cpp b/lib/Sema/TypeLocBuilder.cpp
index c7d43b7..be99540 100644
--- a/lib/Sema/TypeLocBuilder.cpp
+++ b/lib/Sema/TypeLocBuilder.cpp
@@ -62,7 +62,7 @@
TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
#ifndef NDEBUG
- QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
+ QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();
assert(TLast == LastTy &&
"mismatch between last type and new type's inner type");
LastTy = T;
diff --git a/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h
index b1e9098..c3f874e 100644
--- a/lib/Sema/TypeLocBuilder.h
+++ b/lib/Sema/TypeLocBuilder.h
@@ -94,7 +94,7 @@
/// Pushes space for a new TypeLoc of the given type. Invalidates
/// any TypeLocs previously retrieved from this builder.
template <class TyLocType> TyLocType push(QualType T) {
- TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>();
+ TyLocType Loc = TypeLoc(T, nullptr).castAs<TyLocType>();
size_t LocalSize = Loc.getLocalDataSize();
unsigned LocalAlign = Loc.getLocalDataAlignment();
return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
index a817687..ad046ff 100644
--- a/lib/Serialization/ASTCommon.cpp
+++ b/lib/Serialization/ASTCommon.cpp
@@ -95,21 +95,21 @@
case Decl::TranslationUnit:
case Decl::Namespace:
case Decl::LinkageSpec:
- return 0;
+ return nullptr;
// C/C++ tag types can only be defined in one place.
case Decl::Enum:
case Decl::Record:
if (const TagDecl *Def = cast<TagDecl>(DC)->getDefinition())
return Def;
- return 0;
+ return nullptr;
// FIXME: These can be defined in one place... except special member
// functions and out-of-line definitions.
case Decl::CXXRecord:
case Decl::ClassTemplateSpecialization:
case Decl::ClassTemplatePartialSpecialization:
- return 0;
+ return nullptr;
// Each function, method, and block declaration is its own DeclContext.
case Decl::Function:
@@ -131,14 +131,14 @@
if (const ObjCProtocolDecl *Def
= cast<ObjCProtocolDecl>(DC)->getDefinition())
return Def;
- return 0;
+ return nullptr;
// FIXME: These are defined in one place, but properties in class extensions
// end up being back-patched into the main interface. See
// Sema::HandlePropertyInClassExtension for the offending code.
case Decl::ObjCInterface:
- return 0;
-
+ return nullptr;
+
default:
llvm_unreachable("Unhandled DeclContext in AST reader");
}
diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h
index 524a9c2..c766974 100644
--- a/lib/Serialization/ASTCommon.h
+++ b/lib/Serialization/ASTCommon.h
@@ -27,6 +27,7 @@
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION,
+ UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
UPD_CXX_DEDUCED_RETURN_TYPE,
UPD_DECL_MARKED_USED,
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index ff0b1dd..4ea95d0 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
@@ -29,6 +30,7 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
#include "clang/Basic/VersionTuple.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/MacroInfo.h"
@@ -70,6 +72,14 @@
return First->ReadFullVersionInformation(FullVersion) ||
Second->ReadFullVersionInformation(FullVersion);
}
+void ChainedASTReaderListener::ReadModuleName(StringRef ModuleName) {
+ First->ReadModuleName(ModuleName);
+ Second->ReadModuleName(ModuleName);
+}
+void ChainedASTReaderListener::ReadModuleMapFile(StringRef ModuleMapPath) {
+ First->ReadModuleMapFile(ModuleMapPath);
+ Second->ReadModuleMapFile(ModuleMapPath);
+}
bool ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
bool Complain) {
return First->ReadLanguageOptions(LangOpts, Complain) ||
@@ -82,7 +92,7 @@
Second->ReadTargetOptions(TargetOpts, Complain);
}
bool ChainedASTReaderListener::ReadDiagnosticOptions(
- const DiagnosticOptions &DiagOpts, bool Complain) {
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) {
return First->ReadDiagnosticOptions(DiagOpts, Complain) ||
Second->ReadDiagnosticOptions(DiagOpts, Complain);
}
@@ -125,8 +135,14 @@
bool ChainedASTReaderListener::visitInputFile(StringRef Filename,
bool isSystem,
bool isOverridden) {
- return First->visitInputFile(Filename, isSystem, isOverridden) ||
- Second->visitInputFile(Filename, isSystem, isOverridden);
+ bool Continue = false;
+ if (First->needsInputFileVisitation() &&
+ (!isSystem || First->needsSystemInputFileVisitation()))
+ Continue |= First->visitInputFile(Filename, isSystem, isOverridden);
+ if (Second->needsInputFileVisitation() &&
+ (!isSystem || Second->needsSystemInputFileVisitation()))
+ Continue |= Second->visitInputFile(Filename, isSystem, isOverridden);
+ return Continue;
}
//===----------------------------------------------------------------------===//
@@ -210,7 +226,6 @@
CHECK_TARGET_OPT(Triple, "target");
CHECK_TARGET_OPT(CPU, "target CPU");
CHECK_TARGET_OPT(ABI, "target ABI");
- CHECK_TARGET_OPT(LinkerVersion, "target linker version");
#undef CHECK_TARGET_OPT
// Compare feature sets.
@@ -266,14 +281,14 @@
bool Complain) {
const LangOptions &ExistingLangOpts = PP.getLangOpts();
return checkLanguageOptions(LangOpts, ExistingLangOpts,
- Complain? &Reader.Diags : 0);
+ Complain? &Reader.Diags : nullptr);
}
bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
bool Complain) {
const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
return checkTargetOptions(TargetOpts, ExistingTargetOpts,
- Complain? &Reader.Diags : 0);
+ Complain? &Reader.Diags : nullptr);
}
namespace {
@@ -283,11 +298,126 @@
DeclsMap;
}
+static bool checkDiagnosticGroupMappings(DiagnosticsEngine &StoredDiags,
+ DiagnosticsEngine &Diags,
+ bool Complain) {
+ typedef DiagnosticsEngine::Level Level;
+
+ // Check current mappings for new -Werror mappings, and the stored mappings
+ // for cases that were explicitly mapped to *not* be errors that are now
+ // errors because of options like -Werror.
+ DiagnosticsEngine *MappingSources[] = { &Diags, &StoredDiags };
+
+ for (DiagnosticsEngine *MappingSource : MappingSources) {
+ for (auto DiagIDMappingPair : MappingSource->getDiagnosticMappings()) {
+ diag::kind DiagID = DiagIDMappingPair.first;
+ Level CurLevel = Diags.getDiagnosticLevel(DiagID, SourceLocation());
+ if (CurLevel < DiagnosticsEngine::Error)
+ continue; // not significant
+ Level StoredLevel =
+ StoredDiags.getDiagnosticLevel(DiagID, SourceLocation());
+ if (StoredLevel < DiagnosticsEngine::Error) {
+ if (Complain)
+ Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror=" +
+ Diags.getDiagnosticIDs()->getWarningOptionForDiag(DiagID).str();
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static DiagnosticsEngine::ExtensionHandling
+isExtHandlingFromDiagsError(DiagnosticsEngine &Diags) {
+ DiagnosticsEngine::ExtensionHandling Ext =
+ Diags.getExtensionHandlingBehavior();
+ if (Ext == DiagnosticsEngine::Ext_Warn && Diags.getWarningsAsErrors())
+ Ext = DiagnosticsEngine::Ext_Error;
+ return Ext;
+}
+
+static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags,
+ DiagnosticsEngine &Diags,
+ bool IsSystem, bool Complain) {
+ // Top-level options
+ if (IsSystem) {
+ if (Diags.getSuppressSystemWarnings())
+ return false;
+ // If -Wsystem-headers was not enabled before, be conservative
+ if (StoredDiags.getSuppressSystemWarnings()) {
+ if (Complain)
+ Diags.Report(diag::err_pch_diagopt_mismatch) << "-Wsystem-headers";
+ return true;
+ }
+ }
+
+ if (Diags.getWarningsAsErrors() && !StoredDiags.getWarningsAsErrors()) {
+ if (Complain)
+ Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror";
+ return true;
+ }
+
+ if (Diags.getWarningsAsErrors() && Diags.getEnableAllWarnings() &&
+ !StoredDiags.getEnableAllWarnings()) {
+ if (Complain)
+ Diags.Report(diag::err_pch_diagopt_mismatch) << "-Weverything -Werror";
+ return true;
+ }
+
+ if (isExtHandlingFromDiagsError(Diags) &&
+ !isExtHandlingFromDiagsError(StoredDiags)) {
+ if (Complain)
+ Diags.Report(diag::err_pch_diagopt_mismatch) << "-pedantic-errors";
+ return true;
+ }
+
+ return checkDiagnosticGroupMappings(StoredDiags, Diags, Complain);
+}
+
+bool PCHValidator::ReadDiagnosticOptions(
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) {
+ DiagnosticsEngine &ExistingDiags = PP.getDiagnostics();
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(ExistingDiags.getDiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagIDs, DiagOpts.getPtr()));
+ // This should never fail, because we would have processed these options
+ // before writing them to an ASTFile.
+ ProcessWarningOptions(*Diags, *DiagOpts, /*Report*/false);
+
+ ModuleManager &ModuleMgr = Reader.getModuleManager();
+ assert(ModuleMgr.size() >= 1 && "what ASTFile is this then");
+
+ // If the original import came from a file explicitly generated by the user,
+ // don't check the diagnostic mappings.
+ // FIXME: currently this is approximated by checking whether this is not a
+ // module import.
+ // Note: ModuleMgr.rbegin() may not be the current module, but it must be in
+ // the transitive closure of its imports, since unrelated modules cannot be
+ // imported until after this module finishes validation.
+ ModuleFile *TopImport = *ModuleMgr.rbegin();
+ while (!TopImport->ImportedBy.empty())
+ TopImport = TopImport->ImportedBy[0];
+ if (TopImport->Kind != MK_Module)
+ return false;
+
+ StringRef ModuleName = TopImport->ModuleName;
+ assert(!ModuleName.empty() && "diagnostic options read before module name");
+
+ Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName);
+ assert(M && "missing module");
+
+ // FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that
+ // contains the union of their flags.
+ return checkDiagnosticMappings(*Diags, ExistingDiags, M->IsSystem, Complain);
+}
+
/// \brief Collect the macro definitions provided by the given preprocessor
/// options.
-static void collectMacroDefinitions(const PreprocessorOptions &PPOpts,
- MacroDefinitionsMap &Macros,
- SmallVectorImpl<StringRef> *MacroNames = 0){
+static void
+collectMacroDefinitions(const PreprocessorOptions &PPOpts,
+ MacroDefinitionsMap &Macros,
+ SmallVectorImpl<StringRef> *MacroNames = nullptr) {
for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {
StringRef Macro = PPOpts.Macros[I].first;
bool IsUndef = PPOpts.Macros[I].second;
@@ -442,7 +572,7 @@
const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts();
return checkPreprocessorOptions(PPOpts, ExistingPPOpts,
- Complain? &Reader.Diags : 0,
+ Complain? &Reader.Diags : nullptr,
PP.getFileManager(),
SuggestedPredefines,
PP.getLangOpts());
@@ -456,9 +586,10 @@
// AST reader implementation
//===----------------------------------------------------------------------===//
-void
-ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) {
+void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener,
+ bool TakeOwnership) {
DeserializationListener = Listener;
+ OwnsDeserializationListener = TakeOwnership;
}
@@ -851,11 +982,11 @@
Error("Expected visible lookup table block");
return true;
}
- Info.NameLookupTableData
- = ASTDeclContextNameLookupTable::Create(
- (const unsigned char *)Blob.data() + Record[0],
- (const unsigned char *)Blob.data(),
- ASTDeclContextNameLookupTrait(*this, M));
+ Info.NameLookupTableData = ASTDeclContextNameLookupTable::Create(
+ (const unsigned char *)Blob.data() + Record[0],
+ (const unsigned char *)Blob.data() + sizeof(uint32_t),
+ (const unsigned char *)Blob.data(),
+ ASTDeclContextNameLookupTrait(*this, M));
}
return false;
@@ -1125,8 +1256,8 @@
llvm::MemoryBuffer *Buffer
= llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name);
- SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID,
- BaseOffset + Offset, IncludeLoc);
+ SourceMgr.createFileID(Buffer, FileCharacter, ID, BaseOffset + Offset,
+ IncludeLoc);
break;
}
@@ -1161,7 +1292,7 @@
// FIXME: Can we map this down to a particular submodule? That would be
// ideal.
- return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName));
+ return std::make_pair(M->ImportLoc, StringRef(M->ModuleName));
}
/// \brief Find the location where the module F is imported.
@@ -1172,14 +1303,10 @@
// Otherwise we have a PCH. It's considered to be "imported" at the first
// location of its includer.
if (F->ImportedBy.empty() || !F->ImportedBy[0]) {
- // Main file is the importer. We assume that it is the first entry in the
- // entry table. We can't ask the manager, because at the time of PCH loading
- // the main file entry doesn't exist yet.
- // The very first entry is the invalid instantiation loc, which takes up
- // offsets 0 and 1.
- return SourceLocation::getFromRawEncoding(2U);
+ // Main file is the importer.
+ assert(!SourceMgr.getMainFileID().isInvalid() && "missing main file");
+ return SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
}
- //return F->Loaders[0]->FirstLoc;
return F->ImportedBy[0]->FirstLoc;
}
@@ -1228,7 +1355,7 @@
Stream.JumpToBit(Offset);
RecordData Record;
SmallVector<IdentifierInfo*, 16> MacroArgs;
- MacroInfo *Macro = 0;
+ MacroInfo *Macro = nullptr;
while (true) {
// Advance to the next record, but if we get to the end of the block, don't
@@ -1271,6 +1398,7 @@
MacroInfo *MI = PP.AllocateDeserializedMacroInfo(Loc, SubModID);
MI->setDefinitionEndLoc(ReadSourceLocation(F, Record, NextIndex));
MI->setIsUsed(Record[NextIndex++]);
+ MI->setUsedForHeaderGuard(Record[NextIndex++]);
if (RecType == PP_MACRO_FUNCTION_LIKE) {
// Decode function-like macro info.
@@ -1316,7 +1444,7 @@
case PP_TOKEN: {
// If we see a TOKEN before a PP_MACRO_*, then the file is
// erroneous, just pretend we didn't see this.
- if (Macro == 0) break;
+ if (!Macro) break;
unsigned Idx = 0;
Token Tok = ReadToken(F, Record, Idx);
@@ -1433,7 +1561,7 @@
GlobalMacroID GMacID,
llvm::ArrayRef<SubmoduleID> Overrides) {
assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
- SubmoduleID *OverrideData = 0;
+ SubmoduleID *OverrideData = nullptr;
if (!Overrides.empty()) {
OverrideData = new (Context) SubmoduleID[Overrides.size() + 1];
OverrideData[0] = Overrides.size();
@@ -1564,7 +1692,7 @@
// If there is a global index, look there first to determine which modules
// provably do not have any results for this identifier.
GlobalModuleIndex::HitSet Hits;
- GlobalModuleIndex::HitSet *HitsPtr = 0;
+ GlobalModuleIndex::HitSet *HitsPtr = nullptr;
if (!loadGlobalIndex()) {
if (GlobalIndex->lookupIdentifier(II.getName(), Hits)) {
HitsPtr = &Hits;
@@ -1586,7 +1714,7 @@
// Update the generation for this identifier.
if (getContext().getLangOpts().Modules)
- IdentifierGeneration[II] = CurrentGeneration;
+ IdentifierGeneration[II] = getGeneration();
}
struct ASTReader::ModuleMacroInfo {
@@ -1608,7 +1736,7 @@
DefMacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const {
if (!MI)
- return 0;
+ return nullptr;
return PP.AllocateDefMacroDirective(MI, ImportLoc, /*isImported=*/true);
}
};
@@ -1621,7 +1749,7 @@
if (ID & 1) {
// Macro undefinition.
Info.SubModID = getGlobalSubmoduleID(*PMInfo.M, ID >> 1);
- Info.MI = 0;
+ Info.MI = nullptr;
} else {
// Macro definition.
GlobalMacroID GMacID = getGlobalMacroID(*PMInfo.M, ID >> 1);
@@ -1631,7 +1759,7 @@
// FIXME: This is highly dubious. Multiple macro definitions can have the
// same MacroInfo (and hence the same GMacID) due to #pragma push_macro etc.
if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS])
- return 0;
+ return nullptr;
Info.MI = getMacro(GMacID);
Info.SubModID = Info.MI->getOwningModuleID();
@@ -1692,10 +1820,10 @@
}
// Deserialize the macro directives history in reverse source-order.
- MacroDirective *Latest = 0, *Earliest = 0;
+ MacroDirective *Latest = nullptr, *Earliest = nullptr;
unsigned Idx = 0, N = Record.size();
while (Idx < N) {
- MacroDirective *MD = 0;
+ MacroDirective *MD = nullptr;
SourceLocation Loc = ReadSourceLocation(M, Record, Idx);
MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++];
switch (K) {
@@ -1735,7 +1863,7 @@
static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI,
Module *NewOwner, ASTReader &Reader) {
assert(PrevMI && NewMI);
- Module *PrevOwner = 0;
+ Module *PrevOwner = nullptr;
if (SubmoduleID PrevModID = PrevMI->getOwningModuleID())
PrevOwner = Reader.getSubmodule(PrevModID);
SourceManager &SrcMgr = Reader.getSourceManager();
@@ -1780,9 +1908,10 @@
llvm::ArrayRef<SubmoduleID> Overrides) {
MacroDirective *Prev = PP.getMacroDirective(II);
if (!Prev && Overrides.empty())
- return 0;
+ return nullptr;
- DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective() : 0;
+ DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective()
+ : nullptr;
if (PrevDef && PrevDef->isAmbiguous()) {
// We had a prior ambiguity. Check whether we resolve it (or make it worse).
AmbiguousMacros &Ambig = AmbiguousMacroDefs[II];
@@ -1796,7 +1925,7 @@
AmbiguousMacroDefs.erase(II);
} else {
// There's no ambiguity yet. Maybe we're introducing one.
- llvm::SmallVector<DefMacroDirective*, 1> Ambig;
+ AmbiguousMacros Ambig;
if (PrevDef)
Ambig.push_back(PrevDef);
@@ -1804,13 +1933,13 @@
if (!Ambig.empty()) {
AmbiguousMacros &Result = AmbiguousMacroDefs[II];
- Result.swap(Ambig);
+ std::swap(Result, Ambig);
return &Result;
}
}
// We ended up with no ambiguity.
- return 0;
+ return nullptr;
}
void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
@@ -1827,10 +1956,9 @@
assert(ImportLoc.isValid() && "no import location for a visible macro?");
}
- llvm::SmallVectorImpl<DefMacroDirective*> *Prev =
+ AmbiguousMacros *Prev =
removeOverriddenMacros(II, MMI->getOverriddenSubmodules());
-
// Create a synthetic macro definition corresponding to the import (or null
// if this was an undefinition of the macro).
DefMacroDirective *MD = MMI->import(PP, ImportLoc);
@@ -1954,7 +2082,7 @@
// If we didn't find the file, resolve it relative to the
// original directory from which this AST file was created.
- if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() &&
+ if (File == nullptr && !F.OriginalDir.empty() && !CurrentDir.empty() &&
F.OriginalDir != CurrentDir) {
std::string Resolved = resolveFileRelativeToOriginalDir(Filename,
F.OriginalDir,
@@ -1965,11 +2093,11 @@
// For an overridden file, create a virtual file with the stored
// size/timestamp.
- if (Overridden && File == 0) {
+ if (Overridden && File == nullptr) {
File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
}
- if (File == 0) {
+ if (File == nullptr) {
if (Complain) {
std::string ErrorStr = "could not find file '";
ErrorStr += Filename;
@@ -2048,7 +2176,7 @@
std::string Filename = filenameStrRef;
MaybeAddSystemRootToFilename(M, Filename);
const FileEntry *File = FileMgr.getFile(Filename);
- if (File == 0 && !M.OriginalDir.empty() && !CurrentDir.empty() &&
+ if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() &&
M.OriginalDir != CurrentDir) {
std::string resolved = resolveFileRelativeToOriginalDir(Filename,
M.OriginalDir,
@@ -2088,6 +2216,7 @@
ASTReader::ASTReadResult
ASTReader::ReadControlBlock(ModuleFile &F,
SmallVectorImpl<ImportedModule> &Loaded,
+ const ModuleFile *ImportedBy,
unsigned ClientLoadCapabilities) {
BitstreamCursor &Stream = F.Stream;
@@ -2117,7 +2246,7 @@
unsigned NumUserInputs = Record[1];
if (!DisableValidation &&
- (!HSOpts.ModulesValidateOncePerBuildSession ||
+ (ValidateSystemInputs || !HSOpts.ModulesValidateOncePerBuildSession ||
F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp)) {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
@@ -2262,11 +2391,11 @@
}
case DIAGNOSTIC_OPTIONS: {
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0;
if (Listener && &F == *ModuleMgr.begin() &&
ParseDiagnosticOptions(Record, Complain, *Listener) &&
- !DisableValidation && !AllowConfigurationMismatch)
- return ConfigurationMismatch;
+ !DisableValidation)
+ return OutOfDate;
break;
}
@@ -2313,6 +2442,49 @@
F.OriginalDir = Blob;
break;
+ case MODULE_NAME:
+ F.ModuleName = Blob;
+ if (Listener)
+ Listener->ReadModuleName(F.ModuleName);
+ break;
+
+ case MODULE_MAP_FILE:
+ F.ModuleMapPath = Blob;
+
+ // Try to resolve ModuleName in the current header search context and
+ // verify that it is found in the same module map file as we saved. If the
+ // top-level AST file is a main file, skip this check because there is no
+ // usable header search context.
+ assert(!F.ModuleName.empty() &&
+ "MODULE_NAME should come before MOUDLE_MAP_FILE");
+ if (F.Kind == MK_Module &&
+ (*ModuleMgr.begin())->Kind != MK_MainFile) {
+ Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName);
+ if (!M) {
+ assert(ImportedBy && "top-level import should be verified");
+ if ((ClientLoadCapabilities & ARR_Missing) == 0)
+ Diag(diag::err_imported_module_not_found)
+ << F.ModuleName << ImportedBy->FileName;
+ return Missing;
+ }
+
+ const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath);
+ if (StoredModMap == nullptr || StoredModMap != M->ModuleMap) {
+ assert(M->ModuleMap && "found module is missing module map file");
+ assert(M->Name == F.ModuleName && "found module with different name");
+ assert(ImportedBy && "top-level import should be verified");
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Diag(diag::err_imported_module_modmap_changed)
+ << F.ModuleName << ImportedBy->FileName
+ << M->ModuleMap->getName() << F.ModuleMapPath;
+ return OutOfDate;
+ }
+ }
+
+ if (Listener)
+ Listener->ReadModuleMapFile(F.ModuleMapPath);
+ break;
+
case INPUT_FILE_OFFSETS:
F.InputFileOffsets = (const uint32_t *)Blob.data();
F.InputFilesLoaded.resize(Record[0]);
@@ -2321,12 +2493,13 @@
}
}
-bool ASTReader::ReadASTBlock(ModuleFile &F) {
+ASTReader::ASTReadResult
+ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
BitstreamCursor &Stream = F.Stream;
if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
Error("malformed block record in AST file");
- return true;
+ return Failure;
}
// Read all of the records and blocks for the AST file.
@@ -2337,7 +2510,7 @@
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
Error("error at end of module block in AST file");
- return true;
+ return Failure;
case llvm::BitstreamEntry::EndBlock: {
// Outside of C++, we do not store a lookup map for the translation unit.
// Instead, mark it as needing a lookup map to be built if this module
@@ -2349,7 +2522,7 @@
!getContext().getLangOpts().CPlusPlus)
DC->setMustBuildLookupTable();
- return false;
+ return Success;
}
case llvm::BitstreamEntry::SubBlock:
switch (Entry.ID) {
@@ -2363,7 +2536,7 @@
// Read the abbrevs.
ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
Error("malformed block record in AST file");
- return true;
+ return Failure;
}
break;
@@ -2375,7 +2548,7 @@
if (Stream.SkipBlock() ||
ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
Error("malformed block record in AST file");
- return true;
+ return Failure;
}
F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
break;
@@ -2386,7 +2559,7 @@
ReadBlockAbbrevs(F.PreprocessorDetailCursor,
PREPROCESSOR_DETAIL_BLOCK_ID)) {
Error("malformed preprocessor detail record in AST file");
- return true;
+ return Failure;
}
F.PreprocessorDetailStartOffset
= F.PreprocessorDetailCursor.GetCurrentBitNo();
@@ -2399,12 +2572,12 @@
case SOURCE_MANAGER_BLOCK_ID:
if (ReadSourceManagerBlock(F))
- return true;
+ return Failure;
break;
case SUBMODULE_BLOCK_ID:
- if (ReadSubmoduleBlock(F))
- return true;
+ if (ASTReadResult Result = ReadSubmoduleBlock(F, ClientLoadCapabilities))
+ return Result;
break;
case COMMENTS_BLOCK_ID: {
@@ -2412,7 +2585,7 @@
if (Stream.SkipBlock() ||
ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
Error("malformed comments block in AST file");
- return true;
+ return Failure;
}
CommentsCursors.push_back(std::make_pair(C, &F));
break;
@@ -2421,7 +2594,7 @@
default:
if (Stream.SkipBlock()) {
Error("malformed block record in AST file");
- return true;
+ return Failure;
}
break;
}
@@ -2442,7 +2615,7 @@
case TYPE_OFFSET: {
if (F.LocalNumTypes != 0) {
Error("duplicate TYPE_OFFSET record in AST file");
- return true;
+ return Failure;
}
F.TypeOffsets = (const uint32_t *)Blob.data();
F.LocalNumTypes = Record[0];
@@ -2466,7 +2639,7 @@
case DECL_OFFSET: {
if (F.LocalNumDecls != 0) {
Error("duplicate DECL_OFFSET record in AST file");
- return true;
+ return Failure;
}
F.DeclOffsets = (const DeclOffset *)Blob.data();
F.LocalNumDecls = Record[0];
@@ -2507,18 +2680,16 @@
unsigned Idx = 0;
serialization::DeclID ID = ReadDeclID(F, Record, Idx);
ASTDeclContextNameLookupTable *Table =
- ASTDeclContextNameLookupTable::Create(
- (const unsigned char *)Blob.data() + Record[Idx++],
- (const unsigned char *)Blob.data(),
- ASTDeclContextNameLookupTrait(*this, F));
- if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU?
- DeclContext *TU = Context.getTranslationUnitDecl();
- F.DeclContextInfos[TU].NameLookupTableData = Table;
- TU->setHasExternalVisibleStorage(true);
- } else if (Decl *D = DeclsLoaded[ID - NUM_PREDEF_DECL_IDS]) {
+ ASTDeclContextNameLookupTable::Create(
+ (const unsigned char *)Blob.data() + Record[Idx++],
+ (const unsigned char *)Blob.data() + sizeof(uint32_t),
+ (const unsigned char *)Blob.data(),
+ ASTDeclContextNameLookupTrait(*this, F));
+ if (Decl *D = GetExistingDecl(ID)) {
auto *DC = cast<DeclContext>(D);
DC->getPrimaryContext()->setHasExternalVisibleStorage(true);
auto *&LookupTable = F.DeclContextInfos[DC].NameLookupTableData;
+ // FIXME: There should never be an existing lookup table.
delete LookupTable;
LookupTable = Table;
} else
@@ -2529,11 +2700,11 @@
case IDENTIFIER_TABLE:
F.IdentifierTableData = Blob.data();
if (Record[0]) {
- F.IdentifierLookupTable
- = ASTIdentifierLookupTable::Create(
- (const unsigned char *)F.IdentifierTableData + Record[0],
- (const unsigned char *)F.IdentifierTableData,
- ASTIdentifierLookupTrait(*this, F));
+ F.IdentifierLookupTable = ASTIdentifierLookupTable::Create(
+ (const unsigned char *)F.IdentifierTableData + Record[0],
+ (const unsigned char *)F.IdentifierTableData + sizeof(uint32_t),
+ (const unsigned char *)F.IdentifierTableData,
+ ASTIdentifierLookupTrait(*this, F));
PP.getIdentifierTable().setExternalIdentifierLookup(this);
}
@@ -2542,7 +2713,7 @@
case IDENTIFIER_OFFSET: {
if (F.LocalNumIdentifiers != 0) {
Error("duplicate IDENTIFIER_OFFSET record in AST file");
- return true;
+ return Failure;
}
F.IdentifierOffsets = (const uint32_t *)Blob.data();
F.LocalNumIdentifiers = Record[0];
@@ -2581,7 +2752,7 @@
if (SpecialTypes.size() != Record.size()) {
Error("invalid special-types record");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; ++I) {
@@ -2613,7 +2784,7 @@
case WEAK_UNDECLARED_IDENTIFIERS:
if (Record.size() % 4 != 0) {
Error("invalid weak identifiers record");
- return true;
+ return Failure;
}
// FIXME: Ignore weak undeclared identifiers from non-original PCH
@@ -2757,7 +2928,7 @@
ModuleFile *OM = ModuleMgr.lookup(Name);
if (!OM) {
Error("SourceLocation remap refers to unknown module");
- return true;
+ return Failure;
}
uint32_t SLocOffset =
@@ -2806,7 +2977,7 @@
case SOURCE_MANAGER_LINE_TABLE:
if (ParseLineTable(F, Record))
- return true;
+ return Failure;
break;
case SOURCE_LOCATION_PRELOADS: {
@@ -2814,7 +2985,7 @@
// which is based off F.SLocEntryBaseID.
if (!F.PreloadSLocEntries.empty()) {
Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");
- return true;
+ return Failure;
}
F.PreloadSLocEntries.swap(Record);
@@ -2829,7 +3000,7 @@
case VTABLE_USES:
if (Record.size() % 3 != 0) {
Error("Invalid VTABLE_USES record");
- return true;
+ return Failure;
}
// Later tables overwrite earlier ones.
@@ -2853,12 +3024,12 @@
case PENDING_IMPLICIT_INSTANTIATIONS:
if (PendingInstantiations.size() % 2 != 0) {
Error("Invalid existing PendingInstantiations");
- return true;
+ return Failure;
}
if (Record.size() % 2 != 0) {
Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
@@ -2871,7 +3042,7 @@
case SEMA_DECL_REFS:
if (Record.size() != 2) {
Error("Invalid SEMA_DECL_REFS block");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; ++I)
SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
@@ -2912,19 +3083,24 @@
case DECL_UPDATE_OFFSETS: {
if (Record.size() % 2 != 0) {
Error("invalid DECL_UPDATE_OFFSETS block in AST file");
- return true;
+ return Failure;
}
- // FIXME: If we've already loaded the decl, perform the updates now.
- for (unsigned I = 0, N = Record.size(); I != N; I += 2)
- DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]
- .push_back(std::make_pair(&F, Record[I+1]));
+ for (unsigned I = 0, N = Record.size(); I != N; I += 2) {
+ GlobalDeclID ID = getGlobalDeclID(F, Record[I]);
+ DeclUpdateOffsets[ID].push_back(std::make_pair(&F, Record[I + 1]));
+
+ // If we've already loaded the decl, perform the updates when we finish
+ // loading this block.
+ if (Decl *D = GetExistingDecl(ID))
+ PendingUpdateRecords.push_back(std::make_pair(ID, D));
+ }
break;
}
case DECL_REPLACEMENTS: {
if (Record.size() % 3 != 0) {
Error("invalid DECL_REPLACEMENTS block in AST file");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; I += 3)
ReplacedDecls[getGlobalDeclID(F, Record[I])]
@@ -2935,7 +3111,7 @@
case OBJC_CATEGORIES_MAP: {
if (F.LocalNumObjCCategoriesInMap != 0) {
Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
- return true;
+ return Failure;
}
F.LocalNumObjCCategoriesInMap = Record[0];
@@ -2950,7 +3126,7 @@
case CXX_BASE_SPECIFIER_OFFSETS: {
if (F.LocalNumCXXBaseSpecifiers != 0) {
Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
- return true;
+ return Failure;
}
F.LocalNumCXXBaseSpecifiers = Record[0];
@@ -3017,12 +3193,12 @@
case UNDEFINED_BUT_USED:
if (UndefinedButUsed.size() % 2 != 0) {
Error("Invalid existing UndefinedButUsed");
- return true;
+ return Failure;
}
if (Record.size() % 2 != 0) {
Error("invalid undefined-but-used record");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++]));
@@ -3054,7 +3230,7 @@
case LOCAL_REDECLARATIONS_MAP: {
if (F.LocalNumRedeclarationsInMap != 0) {
Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
- return true;
+ return Failure;
}
F.LocalNumRedeclarationsInMap = Record[0];
@@ -3075,7 +3251,7 @@
case MACRO_OFFSET: {
if (F.LocalNumMacros != 0) {
Error("duplicate MACRO_OFFSET record in AST file");
- return true;
+ return Failure;
}
F.MacroOffsets = (const uint32_t *)Blob.data();
F.LocalNumMacros = Record[0];
@@ -3105,6 +3281,14 @@
LateParsedTemplates.append(Record.begin(), Record.end());
break;
}
+
+ case OPTIMIZE_PRAGMA_OPTIONS:
+ if (Record.size() != 1) {
+ Error("invalid pragma optimize record");
+ return Failure;
+ }
+ OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]);
+ break;
}
}
}
@@ -3263,13 +3447,16 @@
llvm::SaveAndRestore<SourceLocation>
SetCurImportLocRAII(CurrentImportLoc, ImportLoc);
+ // Defer any pending actions until we get to the end of reading the AST file.
+ Deserializing AnASTFile(this);
+
// Bump the generation number.
- unsigned PreviousGeneration = CurrentGeneration++;
+ unsigned PreviousGeneration = incrementGeneration(Context);
unsigned NumModules = ModuleMgr.size();
SmallVector<ImportedModule, 4> Loaded;
switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc,
- /*ImportedBy=*/0, Loaded,
+ /*ImportedBy=*/nullptr, Loaded,
0, 0,
ClientLoadCapabilities)) {
case Failure:
@@ -3281,12 +3468,12 @@
ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end(),
Context.getLangOpts().Modules
? &PP.getHeaderSearchInfo().getModuleMap()
- : 0);
+ : nullptr);
// If we find that any modules are unusable, the global index is going
// to be out-of-date. Just remove it.
GlobalIndex.reset();
- ModuleMgr.setGlobalIndex(0);
+ ModuleMgr.setGlobalIndex(nullptr);
return ReadResult;
case Success:
@@ -3302,8 +3489,8 @@
ModuleFile &F = *M->Mod;
// Read the AST block.
- if (ReadASTBlock(F))
- return Failure;
+ if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities))
+ return Result;
// Once read, set the ModuleFile bit base offset and update the size in
// bits of all files we've seen.
@@ -3444,7 +3631,7 @@
std::string ErrorStr;
ModuleManager::AddModuleResult AddResult
= ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy,
- CurrentGeneration, ExpectedSize, ExpectedModTime,
+ getGeneration(), ExpectedSize, ExpectedModTime,
M, ErrorStr);
switch (AddResult) {
@@ -3534,7 +3721,7 @@
break;
case CONTROL_BLOCK_ID:
HaveReadControlBlock = true;
- switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) {
+ switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) {
case Success:
break;
@@ -3575,11 +3762,6 @@
DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
Context.getTranslationUnitDecl());
- // Make sure we load the declaration update records for the translation unit,
- // if there are any.
- loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID,
- Context.getTranslationUnitDecl());
-
// FIXME: Find a better way to deal with collisions between these
// built-in types. Right now, we just ignore the problem.
@@ -3824,16 +4006,16 @@
bool ReadLanguageOptions(const LangOptions &LangOpts,
bool Complain) override {
- return checkLanguageOptions(ExistingLangOpts, LangOpts, 0);
+ return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr);
}
bool ReadTargetOptions(const TargetOptions &TargetOpts,
bool Complain) override {
- return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0);
+ return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr);
}
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
bool Complain,
std::string &SuggestedPredefines) override {
- return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr,
+ return checkPreprocessorOptions(ExistingPPOpts, PPOpts, nullptr, FileMgr,
SuggestedPredefines, ExistingLangOpts);
}
};
@@ -3914,6 +4096,12 @@
break;
}
+ case MODULE_NAME:
+ Listener.ReadModuleName(Blob);
+ break;
+ case MODULE_MAP_FILE:
+ Listener.ReadModuleMapFile(Blob);
+ break;
case LANGUAGE_OPTIONS:
if (ParseLanguageOptions(Record, false, Listener))
return true;
@@ -3998,16 +4186,17 @@
return !readASTFileControlBlock(Filename, FileMgr, validator);
}
-bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
+ASTReader::ASTReadResult
+ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// Enter the submodule block.
if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
Error("malformed submodule block record in AST file");
- return true;
+ return Failure;
}
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
bool First = true;
- Module *CurrentModule = 0;
+ Module *CurrentModule = nullptr;
RecordData Record;
while (true) {
llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks();
@@ -4016,9 +4205,9 @@
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
Error("malformed block record in AST file");
- return true;
+ return Failure;
case llvm::BitstreamEntry::EndBlock:
- return false;
+ return Success;
case llvm::BitstreamEntry::Record:
// The interesting case.
break;
@@ -4034,12 +4223,12 @@
case SUBMODULE_DEFINITION: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (Record.size() < 8) {
Error("malformed module definition");
- return true;
+ return Failure;
}
StringRef Name = Blob;
@@ -4055,20 +4244,26 @@
bool InferExportWildcard = Record[Idx++];
bool ConfigMacrosExhaustive = Record[Idx++];
- Module *ParentModule = 0;
- if (Parent)
+ Module *ParentModule = nullptr;
+ const FileEntry *ModuleMap = nullptr;
+ if (Parent) {
ParentModule = getSubmodule(Parent);
-
+ ModuleMap = ParentModule->ModuleMap;
+ }
+
+ if (!F.ModuleMapPath.empty())
+ ModuleMap = FileMgr.getFile(F.ModuleMapPath);
+
// Retrieve this (sub)module from the module map, creating it if
// necessary.
- CurrentModule = ModMap.findOrCreateModule(Name, ParentModule,
+ CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, ModuleMap,
IsFramework,
IsExplicit).first;
SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;
if (GlobalIndex >= SubmodulesLoaded.size() ||
SubmodulesLoaded[GlobalIndex]) {
Error("too many submodules");
- return true;
+ return Failure;
}
if (!ParentModule) {
@@ -4080,13 +4275,13 @@
<< CurFile->getName()
<< F.File->getName();
}
- return true;
+ return Failure;
}
}
CurrentModule->setASTFile(F.File);
}
-
+
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
CurrentModule->IsExternC = IsExternC;
@@ -4110,7 +4305,7 @@
case SUBMODULE_UMBRELLA_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4120,8 +4315,9 @@
if (!CurrentModule->getUmbrellaHeader())
ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
- Error("mismatched umbrella headers in submodule");
- return true;
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Error("mismatched umbrella headers in submodule");
+ return OutOfDate;
}
}
break;
@@ -4130,7 +4326,7 @@
case SUBMODULE_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4145,7 +4341,7 @@
case SUBMODULE_EXCLUDED_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4160,7 +4356,7 @@
case SUBMODULE_PRIVATE_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4175,7 +4371,7 @@
case SUBMODULE_TOPHEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4188,7 +4384,7 @@
case SUBMODULE_UMBRELLA_DIR: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4199,8 +4395,9 @@
if (!CurrentModule->getUmbrellaDir())
ModMap.setUmbrellaDir(CurrentModule, Umbrella);
else if (CurrentModule->getUmbrellaDir() != Umbrella) {
- Error("mismatched umbrella directories in submodule");
- return true;
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Error("mismatched umbrella directories in submodule");
+ return OutOfDate;
}
}
break;
@@ -4209,7 +4406,7 @@
case SUBMODULE_METADATA: {
if (!First) {
Error("submodule metadata record not at beginning of block");
- return true;
+ return Failure;
}
First = false;
@@ -4235,7 +4432,7 @@
case SUBMODULE_IMPORTS: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4256,7 +4453,7 @@
case SUBMODULE_EXPORTS: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4280,7 +4477,7 @@
case SUBMODULE_REQUIRES: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4294,7 +4491,7 @@
case SUBMODULE_LINK_LIBRARY:
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4307,7 +4504,7 @@
case SUBMODULE_CONFIG_MACRO:
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4319,7 +4516,7 @@
case SUBMODULE_CONFLICT: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
@@ -4387,7 +4584,6 @@
TargetOpts.Triple = ReadString(Record, Idx);
TargetOpts.CPU = ReadString(Record, Idx);
TargetOpts.ABI = ReadString(Record, Idx);
- TargetOpts.LinkerVersion = ReadString(Record, Idx);
for (unsigned N = Record[Idx++]; N; --N) {
TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
}
@@ -4400,15 +4596,15 @@
bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,
ASTReaderListener &Listener) {
- DiagnosticOptions DiagOpts;
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions);
unsigned Idx = 0;
-#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++];
+#define DIAGOPT(Name, Bits, Default) DiagOpts->Name = Record[Idx++];
#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
- DiagOpts.set##Name(static_cast<Type>(Record[Idx++]));
+ DiagOpts->set##Name(static_cast<Type>(Record[Idx++]));
#include "clang/Basic/DiagnosticOptions.def"
for (unsigned N = Record[Idx++]; N; --N) {
- DiagOpts.Warnings.push_back(ReadString(Record, Idx));
+ DiagOpts->Warnings.push_back(ReadString(Record, Idx));
}
return Listener.ReadDiagnosticOptions(DiagOpts, Complain);
@@ -4532,7 +4728,7 @@
if (!PP.getPreprocessingRecord()) {
Error("no preprocessing record");
- return 0;
+ return nullptr;
}
SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor);
@@ -4541,7 +4737,7 @@
llvm::BitstreamEntry Entry =
M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
if (Entry.Kind != llvm::BitstreamEntry::Record)
- return 0;
+ return nullptr;
// Read the record.
SourceRange Range(ReadSourceLocation(M, PPOffs.Begin),
@@ -4555,8 +4751,8 @@
switch (RecType) {
case PPD_MACRO_EXPANSION: {
bool isBuiltin = Record[0];
- IdentifierInfo *Name = 0;
- MacroDefinition *Def = 0;
+ IdentifierInfo *Name = nullptr;
+ MacroDefinition *Def = nullptr;
if (isBuiltin)
Name = getLocalIdentifier(M, Record[1]);
else {
@@ -4590,7 +4786,7 @@
case PPD_INCLUSION_DIRECTIVE: {
const char *FullFileNameStart = Blob.data() + Record[0];
StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]);
- const FileEntry *File = 0;
+ const FileEntry *File = nullptr;
if (!FullFileName.empty())
File = PP.getFileManager().getFile(FullFileName);
@@ -4659,15 +4855,13 @@
}
-/// \brief Returns the first preprocessed entity ID that ends after \arg BLoc.
-PreprocessedEntityID
-ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const {
- if (SourceMgr.isLocalSourceLocation(BLoc))
+PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc,
+ bool EndsAfter) const {
+ if (SourceMgr.isLocalSourceLocation(Loc))
return getTotalNumPreprocessedEntities();
- GlobalSLocOffsetMapType::const_iterator
- SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
- BLoc.getOffset() - 1);
+ GlobalSLocOffsetMapType::const_iterator SLocMapI = GlobalSLocOffsetMap.find(
+ SourceManager::MaxLoadedOffset - Loc.getOffset() - 1);
assert(SLocMapI != GlobalSLocOffsetMap.end() &&
"Corrupted global sloc offset map");
@@ -4684,21 +4878,26 @@
pp_iterator First = pp_begin;
pp_iterator PPI;
- // Do a binary search manually instead of using std::lower_bound because
- // The end locations of entities may be unordered (when a macro expansion
- // is inside another macro argument), but for this case it is not important
- // whether we get the first macro expansion or its containing macro.
- while (Count > 0) {
- Half = Count/2;
- PPI = First;
- std::advance(PPI, Half);
- if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End),
- BLoc)){
- First = PPI;
- ++First;
- Count = Count - Half - 1;
- } else
- Count = Half;
+ if (EndsAfter) {
+ PPI = std::upper_bound(pp_begin, pp_end, Loc,
+ PPEntityComp<&PPEntityOffset::Begin>(*this, M));
+ } else {
+ // Do a binary search manually instead of using std::lower_bound because
+ // The end locations of entities may be unordered (when a macro expansion
+ // is inside another macro argument), but for this case it is not important
+ // whether we get the first macro expansion or its containing macro.
+ while (Count > 0) {
+ Half = Count / 2;
+ PPI = First;
+ std::advance(PPI, Half);
+ if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End),
+ Loc)) {
+ First = PPI;
+ ++First;
+ Count = Count - Half - 1;
+ } else
+ Count = Half;
+ }
}
if (PPI == pp_end)
@@ -4707,35 +4906,6 @@
return M.BasePreprocessedEntityID + (PPI - pp_begin);
}
-/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc.
-PreprocessedEntityID
-ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const {
- if (SourceMgr.isLocalSourceLocation(ELoc))
- return getTotalNumPreprocessedEntities();
-
- GlobalSLocOffsetMapType::const_iterator
- SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
- ELoc.getOffset() - 1);
- assert(SLocMapI != GlobalSLocOffsetMap.end() &&
- "Corrupted global sloc offset map");
-
- if (SLocMapI->second->NumPreprocessedEntities == 0)
- return findNextPreprocessedEntity(SLocMapI);
-
- ModuleFile &M = *SLocMapI->second;
- typedef const PPEntityOffset *pp_iterator;
- pp_iterator pp_begin = M.PreprocessedEntityOffsets;
- pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
- pp_iterator PPI =
- std::upper_bound(pp_begin, pp_end, ELoc,
- PPEntityComp<&PPEntityOffset::Begin>(*this, M));
-
- if (PPI == pp_end)
- return findNextPreprocessedEntity(SLocMapI);
-
- return M.BasePreprocessedEntityID + (PPI - pp_begin);
-}
-
/// \brief Returns a pair of [Begin, End) indices of preallocated
/// preprocessed entities that \arg Range encompasses.
std::pair<unsigned, unsigned>
@@ -4744,8 +4914,9 @@
return std::make_pair(0,0);
assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
- PreprocessedEntityID BeginID = findBeginPreprocessedEntity(Range.getBegin());
- PreprocessedEntityID EndID = findEndPreprocessedEntity(Range.getEnd());
+ PreprocessedEntityID BeginID =
+ findPreprocessedEntity(Range.getBegin(), false);
+ PreprocessedEntityID EndID = findPreprocessedEntity(Range.getEnd(), true);
return std::make_pair(BeginID, EndID);
}
@@ -5234,8 +5405,14 @@
QualType TST = readType(*Loc.F, Record, Idx); // probably derivable
// FIXME: ASTContext::getInjectedClassNameType is not currently suitable
// for AST reading, too much interdependencies.
- return
- QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0);
+ const Type *T;
+ if (const Type *Existing = D->getTypeForDecl())
+ T = Existing;
+ else if (auto *Prev = D->getPreviousDecl())
+ T = Prev->getTypeForDecl();
+ else
+ T = new (Context, TypeAlignment) InjectedClassNameType(D, TST);
+ return QualType(T, 0);
}
case TYPE_TEMPLATE_TYPE_PARM: {
@@ -5420,7 +5597,7 @@
if (Record[Idx++])
TL.setSizeExpr(Reader.ReadExpr(F));
else
- TL.setSizeExpr(0);
+ TL.setSizeExpr(nullptr);
}
void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
@@ -5507,7 +5684,7 @@
if (Record[Idx++])
TL.setAttrExprOperand(Reader.ReadExpr(F));
else
- TL.setAttrExprOperand(0);
+ TL.setAttrExprOperand(nullptr);
} else if (TL.hasAttrEnumOperand())
TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));
}
@@ -5591,7 +5768,7 @@
unsigned &Idx) {
QualType InfoTy = readType(F, Record, Idx);
if (InfoTy.isNull())
- return 0;
+ return nullptr;
TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy);
TypeLocReader TLR(*this, F, Record, Idx);
@@ -5778,11 +5955,54 @@
return GetDecl(ID);
}
-uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record,
- unsigned &Idx){
- if (Idx >= Record.size())
+void ASTReader::CompleteRedeclChain(const Decl *D) {
+ if (NumCurrentElementsDeserializing) {
+ // We arrange to not care about the complete redeclaration chain while we're
+ // deserializing. Just remember that the AST has marked this one as complete
+ // but that it's not actually complete yet, so we know we still need to
+ // complete it later.
+ PendingIncompleteDeclChains.push_back(const_cast<Decl*>(D));
+ return;
+ }
+
+ const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+
+ // Recursively ensure that the decl context itself is complete
+ // (in particular, this matters if the decl context is a namespace).
+ //
+ // FIXME: This should be performed by lookup instead of here.
+ cast<Decl>(DC)->getMostRecentDecl();
+
+ // If this is a named declaration, complete it by looking it up
+ // within its context.
+ //
+ // FIXME: We don't currently handle the cases where we can't do this;
+ // merging a class definition that contains unnamed entities should merge
+ // those entities. Likewise, merging a function definition should merge
+ // all mergeable entities within it.
+ if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) ||
+ isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) {
+ if (DeclarationName Name = cast<NamedDecl>(D)->getDeclName()) {
+ auto *II = Name.getAsIdentifierInfo();
+ if (isa<TranslationUnitDecl>(DC) && II) {
+ // Outside of C++, we don't have a lookup table for the TU, so update
+ // the identifier instead. In C++, either way should work fine.
+ if (II->isOutOfDate())
+ updateOutOfDateIdentifier(*II);
+ } else
+ DC->lookup(Name);
+ }
+ }
+}
+
+uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M,
+ const RecordData &Record,
+ unsigned &Idx) {
+ if (Idx >= Record.size() || Record[Idx] > M.LocalNumCXXBaseSpecifiers) {
+ Error("malformed AST file: missing C++ base specifier");
return 0;
-
+ }
+
unsigned LocalID = Record[Idx++];
return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]);
}
@@ -5797,8 +6017,8 @@
unsigned Code = Cursor.ReadCode();
unsigned RecCode = Cursor.readRecord(Code, Record);
if (RecCode != DECL_CXX_BASE_SPECIFIERS) {
- Error("Malformed AST file: missing C++ base specifiers");
- return 0;
+ Error("malformed AST file: missing C++ base specifiers");
+ return nullptr;
}
unsigned Idx = 0;
@@ -5831,7 +6051,7 @@
ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) {
if (!D->isFromASTFile())
- return 0;
+ return nullptr;
GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID());
assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
return I->second;
@@ -5840,14 +6060,14 @@
SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
if (ID < NUM_PREDEF_DECL_IDS)
return SourceLocation();
-
+
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
if (Index > DeclsLoaded.size()) {
Error("declaration ID out-of-range for AST file");
return SourceLocation();
}
-
+
if (Decl *D = DeclsLoaded[Index])
return D->getLocation();
@@ -5856,15 +6076,15 @@
return ReadSourceLocation(*Rec.F, RawLocation);
}
-Decl *ASTReader::GetDecl(DeclID ID) {
- if (ID < NUM_PREDEF_DECL_IDS) {
+Decl *ASTReader::GetExistingDecl(DeclID ID) {
+ if (ID < NUM_PREDEF_DECL_IDS) {
switch ((PredefinedDeclIDs)ID) {
case PREDEF_DECL_NULL_ID:
- return 0;
-
+ return nullptr;
+
case PREDEF_DECL_TRANSLATION_UNIT_ID:
return Context.getTranslationUnitDecl();
-
+
case PREDEF_DECL_OBJC_ID_ID:
return Context.getObjCIdDecl();
@@ -5873,16 +6093,16 @@
case PREDEF_DECL_OBJC_CLASS_ID:
return Context.getObjCClassDecl();
-
+
case PREDEF_DECL_OBJC_PROTOCOL_ID:
return Context.getObjCProtocolDecl();
-
+
case PREDEF_DECL_INT_128_ID:
return Context.getInt128Decl();
case PREDEF_DECL_UNSIGNED_INT_128_ID:
return Context.getUInt128Decl();
-
+
case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
return Context.getObjCInstanceTypeDecl();
@@ -5890,15 +6110,30 @@
return Context.getBuiltinVaListDecl();
}
}
-
+
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
if (Index >= DeclsLoaded.size()) {
assert(0 && "declaration ID out-of-range for AST file");
Error("declaration ID out-of-range for AST file");
- return 0;
+ return nullptr;
}
-
+
+ return DeclsLoaded[Index];
+}
+
+Decl *ASTReader::GetDecl(DeclID ID) {
+ if (ID < NUM_PREDEF_DECL_IDS)
+ return GetExistingDecl(ID);
+
+ unsigned Index = ID - NUM_PREDEF_DECL_IDS;
+
+ if (Index >= DeclsLoaded.size()) {
+ assert(0 && "declaration ID out-of-range for AST file");
+ Error("declaration ID out-of-range for AST file");
+ return nullptr;
+ }
+
if (!DeclsLoaded[Index]) {
ReadDeclRecord(ID);
if (DeserializationListener)
@@ -6183,7 +6418,7 @@
if (const DeclContext *DefDC = getDefinitiveDeclContext(DC))
return Reader.getOwningModuleFile(cast<Decl>(DefDC));
- return 0;
+ return nullptr;
}
bool
@@ -6204,14 +6439,19 @@
Contexts.push_back(DC);
if (DC->isNamespace()) {
- MergedDeclsMap::iterator Merged
- = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ auto Merged = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
if (Merged != MergedDecls.end()) {
for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
}
}
-
+ if (isa<CXXRecordDecl>(DC)) {
+ auto Merged = MergedLookups.find(DC);
+ if (Merged != MergedLookups.end())
+ Contexts.insert(Contexts.end(), Merged->second.begin(),
+ Merged->second.end());
+ }
+
DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
// If we can definitively determine which module file to look into,
@@ -6384,15 +6624,15 @@
QualType());
unsigned NumDeclsLoaded
= DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
- (Decl *)0);
+ (Decl *)nullptr);
unsigned NumIdentifiersLoaded
= IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
IdentifiersLoaded.end(),
- (IdentifierInfo *)0);
+ (IdentifierInfo *)nullptr);
unsigned NumMacrosLoaded
= MacrosLoaded.size() - std::count(MacrosLoaded.begin(),
MacrosLoaded.end(),
- (MacroInfo *)0);
+ (MacroInfo *)nullptr);
unsigned NumSelectorsLoaded
= SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
SelectorsLoaded.end(),
@@ -6576,6 +6816,11 @@
}
SemaDeclRefs.clear();
}
+
+ // Update the state of 'pragma clang optimize'. Use the same API as if we had
+ // encountered the pragma in the source.
+ if(OptimizeOffPragmaLocation.isValid())
+ SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation);
}
IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
@@ -6586,7 +6831,7 @@
// If there is a global index, look there first to determine which modules
// provably do not have any results for this identifier.
GlobalModuleIndex::HitSet Hits;
- GlobalModuleIndex::HitSet *HitsPtr = 0;
+ GlobalModuleIndex::HitSet *HitsPtr = nullptr;
if (!loadGlobalIndex()) {
if (GlobalIndex->lookupIdentifier(Name, Hits)) {
HitsPtr = &Hits;
@@ -6742,7 +6987,7 @@
// Get the selector generation and update it to the current generation.
unsigned &Generation = SelectorGeneration[Sel];
unsigned PriorGeneration = Generation;
- Generation = CurrentGeneration;
+ Generation = getGeneration();
// Search for methods defined with this selector.
++NumMethodPoolLookups;
@@ -6999,11 +7244,11 @@
IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) {
if (ID == 0)
- return 0;
+ return nullptr;
if (IdentifiersLoaded.empty()) {
Error("no identifier table in AST file");
- return 0;
+ return nullptr;
}
ID -= 1;
@@ -7049,11 +7294,11 @@
MacroInfo *ASTReader::getMacro(MacroID ID) {
if (ID == 0)
- return 0;
+ return nullptr;
if (MacrosLoaded.empty()) {
Error("no macro table in AST file");
- return 0;
+ return nullptr;
}
ID -= NUM_PREDEF_MACRO_IDS;
@@ -7100,12 +7345,12 @@
Module *ASTReader::getSubmodule(SubmoduleID GlobalID) {
if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) {
assert(GlobalID == 0 && "Unhandled global submodule ID");
- return 0;
+ return nullptr;
}
if (GlobalID > SubmodulesLoaded.size()) {
Error("submodule ID out of range in AST file");
- return 0;
+ return nullptr;
}
return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS];
@@ -7128,7 +7373,7 @@
return Selector();
}
- if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) {
+ if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == nullptr) {
// Load this selector from the selector table.
GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID);
assert(I != GlobalSelectorMap.end() && "Corrupted global selector map");
@@ -7424,16 +7669,16 @@
std::pair<CXXCtorInitializer **, unsigned>
ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
- CXXCtorInitializer **CtorInitializers = 0;
+ CXXCtorInitializer **CtorInitializers = nullptr;
unsigned NumInitializers = Record[Idx++];
if (NumInitializers) {
CtorInitializers
= new (Context) CXXCtorInitializer*[NumInitializers];
for (unsigned i=0; i != NumInitializers; ++i) {
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
bool IsBaseVirtual = false;
- FieldDecl *Member = 0;
- IndirectFieldDecl *IndirectMember = 0;
+ FieldDecl *Member = nullptr;
+ IndirectFieldDecl *IndirectMember = nullptr;
CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
switch (Type) {
@@ -7513,7 +7758,7 @@
ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
const RecordData &Record, unsigned &Idx) {
unsigned N = Record[Idx++];
- NestedNameSpecifier *NNS = 0, *Prev = 0;
+ NestedNameSpecifier *NNS = nullptr, *Prev = nullptr;
for (unsigned I = 0; I != N; ++I) {
NestedNameSpecifier::SpecifierKind Kind
= (NestedNameSpecifier::SpecifierKind)Record[Idx++];
@@ -7540,8 +7785,8 @@
case NestedNameSpecifier::TypeSpecWithTemplate: {
const Type *T = readType(F, Record, Idx).getTypePtrOrNull();
if (!T)
- return 0;
-
+ return nullptr;
+
bool Template = Record[Idx++];
NNS = NestedNameSpecifier::Create(Context, Prev, Template, T);
break;
@@ -7688,14 +7933,14 @@
/// \brief Record that the given ID maps to the given switch-case
/// statement.
void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
- assert((*CurrSwitchCaseStmts)[ID] == 0 &&
+ assert((*CurrSwitchCaseStmts)[ID] == nullptr &&
"Already have a SwitchCase with this ID");
(*CurrSwitchCaseStmts)[ID] = SC;
}
/// \brief Retrieve the switch-case statement with the given ID.
SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) {
- assert((*CurrSwitchCaseStmts)[ID] != 0 && "No SwitchCase with this ID");
+ assert((*CurrSwitchCaseStmts)[ID] != nullptr && "No SwitchCase with this ID");
return (*CurrSwitchCaseStmts)[ID];
}
@@ -7754,10 +7999,24 @@
}
}
+std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
+ // If we know the owning module, use it.
+ if (Module *M = D->getOwningModule())
+ return M->getFullModuleName();
+
+ // Otherwise, use the name of the top-level module the decl is within.
+ if (ModuleFile *M = getOwningModuleFile(D))
+ return M->ModuleName;
+
+ // Not from a module.
+ return "";
+}
+
void ASTReader::finishPendingActions() {
- while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
+ while (!PendingIdentifierInfos.empty() ||
+ !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() ||
!PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() ||
- !PendingOdrMergeChecks.empty()) {
+ !PendingUpdateRecords.empty() || !PendingOdrMergeChecks.empty()) {
// If any identifiers with corresponding top-level declarations have
// been loaded, load those declarations now.
typedef llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> >
@@ -7773,6 +8032,13 @@
SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]);
}
+ // For each decl chain that we wanted to complete while deserializing, mark
+ // it as "still needs to be completed".
+ for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) {
+ markIncompleteDeclChain(PendingIncompleteDeclChains[I]);
+ }
+ PendingIncompleteDeclChains.clear();
+
// Load pending declaration chains.
for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
loadPendingDeclChain(PendingDeclChains[I]);
@@ -7821,6 +8087,27 @@
Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext());
}
+ // Perform any pending declaration updates.
+ while (!PendingUpdateRecords.empty()) {
+ auto Update = PendingUpdateRecords.pop_back_val();
+ ReadingKindTracker ReadingKind(Read_Decl, *this);
+ loadDeclUpdateRecords(Update.first, Update.second);
+ }
+
+ // Trigger the import of the full definition of each class that had any
+ // odr-merging problems, so we can produce better diagnostics for them.
+ for (auto &Merge : PendingOdrMergeFailures) {
+ Merge.first->buildLookup();
+ Merge.first->decls_begin();
+ Merge.first->bases_begin();
+ Merge.first->vbases_begin();
+ for (auto *RD : Merge.second) {
+ RD->decls_begin();
+ RD->bases_begin();
+ RD->vbases_begin();
+ }
+ }
+
// For each declaration from a merged context, check that the canonical
// definition of that context also contains a declaration of the same
// entity.
@@ -7859,11 +8146,11 @@
if (!Found) {
D->setInvalidDecl();
- Module *CanonDefModule = cast<Decl>(CanonDef)->getOwningModule();
+ std::string CanonDefModule =
+ getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef));
Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl)
- << D << D->getOwningModule()->getFullModuleName()
- << CanonDef << !CanonDefModule
- << (CanonDefModule ? CanonDefModule->getFullModuleName() : "");
+ << D << getOwningModuleNameForDiagnostic(D)
+ << CanonDef << CanonDefModule.empty() << CanonDefModule;
if (Candidates.empty())
Diag(cast<Decl>(CanonDef)->getLocation(),
@@ -7874,6 +8161,8 @@
diag::note_module_odr_violation_possible_decl)
<< Candidates[I];
}
+
+ DiagnosedOdrMergeFailures.insert(CanonDef);
}
}
}
@@ -7886,7 +8175,7 @@
DEnd = PendingDefinitions.end();
D != DEnd; ++D) {
if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {
- if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) {
+ if (const TagType *TagT = dyn_cast<TagType>(TD->getTypeForDecl())) {
// Make sure that the TagType points at the definition.
const_cast<TagType*>(TagT)->decl = TD;
}
@@ -7894,7 +8183,6 @@
if (auto RD = dyn_cast<CXXRecordDecl>(*D)) {
for (auto R : RD->redecls())
cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData;
-
}
continue;
@@ -7943,6 +8231,46 @@
MD->setLazyBody(PB->second);
}
PendingBodies.clear();
+
+ // Issue any pending ODR-failure diagnostics.
+ for (auto &Merge : PendingOdrMergeFailures) {
+ if (!DiagnosedOdrMergeFailures.insert(Merge.first))
+ continue;
+
+ bool Diagnosed = false;
+ for (auto *RD : Merge.second) {
+ // Multiple different declarations got merged together; tell the user
+ // where they came from.
+ if (Merge.first != RD) {
+ // FIXME: Walk the definition, figure out what's different,
+ // and diagnose that.
+ if (!Diagnosed) {
+ std::string Module = getOwningModuleNameForDiagnostic(Merge.first);
+ Diag(Merge.first->getLocation(),
+ diag::err_module_odr_violation_different_definitions)
+ << Merge.first << Module.empty() << Module;
+ Diagnosed = true;
+ }
+
+ Diag(RD->getLocation(),
+ diag::note_module_odr_violation_different_definitions)
+ << getOwningModuleNameForDiagnostic(RD);
+ }
+ }
+
+ if (!Diagnosed) {
+ // All definitions are updates to the same declaration. This happens if a
+ // module instantiates the declaration of a class template specialization
+ // and two or more other modules instantiate its definition.
+ //
+ // FIXME: Indicate which modules had instantiations of this definition.
+ // FIXME: How can this even happen?
+ Diag(Merge.first->getLocation(),
+ diag::err_module_odr_violation_different_instantiations)
+ << Merge.first;
+ }
+ }
+ PendingOdrMergeFailures.clear();
}
void ASTReader::FinishedDeserializing() {
@@ -7977,39 +8305,39 @@
}
}
-ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
- StringRef isysroot, bool DisableValidation,
- bool AllowASTWithCompilerErrors,
- bool AllowConfigurationMismatch,
- bool ValidateSystemInputs,
+ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot,
+ bool DisableValidation, bool AllowASTWithCompilerErrors,
+ bool AllowConfigurationMismatch, bool ValidateSystemInputs,
bool UseGlobalIndex)
- : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
- SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
- Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context),
- Consumer(0), ModuleMgr(PP.getFileManager()),
- isysroot(isysroot), DisableValidation(DisableValidation),
- AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
- AllowConfigurationMismatch(AllowConfigurationMismatch),
- ValidateSystemInputs(ValidateSystemInputs),
- UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false),
- CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts),
- NumSLocEntriesRead(0), TotalNumSLocEntries(0),
- NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
- TotalNumMacros(0), NumIdentifierLookups(0), NumIdentifierLookupHits(0),
- NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
- NumMethodPoolLookups(0), NumMethodPoolHits(0),
- NumMethodPoolTableLookups(0), NumMethodPoolTableHits(0),
- TotalNumMethodPoolEntries(0),
- NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
- NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
- TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
- PassingDeclsToConsumer(false),
- NumCXXBaseSpecifiersLoaded(0), ReadingKind(Read_None)
-{
+ : Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr),
+ OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()),
+ FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
+ SemaObj(nullptr), PP(PP), Context(Context), Consumer(nullptr),
+ ModuleMgr(PP.getFileManager()), isysroot(isysroot),
+ DisableValidation(DisableValidation),
+ AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
+ AllowConfigurationMismatch(AllowConfigurationMismatch),
+ ValidateSystemInputs(ValidateSystemInputs),
+ UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false),
+ CurrSwitchCaseStmts(&SwitchCaseStmts),
+ NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0),
+ TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0),
+ NumIdentifierLookups(0), NumIdentifierLookupHits(0), NumSelectorsRead(0),
+ NumMethodPoolEntriesRead(0), NumMethodPoolLookups(0),
+ NumMethodPoolHits(0), NumMethodPoolTableLookups(0),
+ NumMethodPoolTableHits(0), TotalNumMethodPoolEntries(0),
+ NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
+ NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
+ TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
+ PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0),
+ ReadingKind(Read_None) {
SourceMgr.setExternalSLocEntrySource(this);
}
ASTReader::~ASTReader() {
+ if (OwnsDeserializationListener)
+ delete DeserializationListener;
+
for (DeclContextVisibleUpdatesPending::iterator
I = PendingVisibleUpdates.begin(),
E = PendingVisibleUpdates.end();
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 7d95072..8a0849c 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -99,9 +99,12 @@
Module *readModule(const RecordData &R, unsigned &I) {
return Reader.getSubmodule(readSubmoduleID(R, I));
}
-
+
+ void ReadCXXRecordDefinition(CXXRecordDecl *D);
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
const RecordData &R, unsigned &I);
+ void MergeDefinitionData(CXXRecordDecl *D,
+ struct CXXRecordDecl::DefinitionData &NewDD);
/// \brief RAII class used to capture the first ID within a redeclaration
/// chain and to introduce it into the list of pending redeclaration chains
@@ -160,8 +163,8 @@
public:
FindExistingResult(ASTReader &Reader)
- : Reader(Reader), New(0), Existing(0), AddResult(false) { }
-
+ : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false) {}
+
FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing)
: Reader(Reader), New(New), Existing(Existing), AddResult(true) { }
@@ -195,9 +198,20 @@
RawLocation(RawLocation), Record(Record), Idx(Idx),
TypeIDForTypeDecl(0), HasPendingBody(false) { }
+ template <typename DeclT>
+ static void attachPreviousDeclImpl(Redeclarable<DeclT> *D, Decl *Previous);
+ static void attachPreviousDeclImpl(...);
static void attachPreviousDecl(Decl *D, Decl *previous);
+
+ template <typename DeclT>
+ static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest);
+ static void attachLatestDeclImpl(...);
static void attachLatestDecl(Decl *D, Decl *latest);
+ template <typename DeclT>
+ static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D);
+ static void markIncompleteDeclChainImpl(...);
+
/// \brief Determine whether this declaration has a pending body.
bool hasPendingBody() const { return HasPendingBody; }
@@ -264,7 +278,7 @@
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
void VisitParmVarDecl(ParmVarDecl *PD);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
- void VisitTemplateDecl(TemplateDecl *D);
+ DeclID VisitTemplateDecl(TemplateDecl *D);
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitVarTemplateDecl(VarTemplateDecl *D);
@@ -285,20 +299,26 @@
void VisitEmptyDecl(EmptyDecl *D);
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
-
- template<typename T>
+
+ template<typename T>
RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);
template<typename T>
- void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
+ void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl,
+ DeclID TemplatePatternID = 0);
template<typename T>
void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
- RedeclarableResult &Redecl);
+ RedeclarableResult &Redecl,
+ DeclID TemplatePatternID = 0);
template<typename T>
void mergeMergeable(Mergeable<T> *D);
+ void mergeTemplatePattern(RedeclarableTemplateDecl *D,
+ RedeclarableTemplateDecl *Existing,
+ DeclID DsID);
+
// FIXME: Reorder according to DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *D);
@@ -337,7 +357,7 @@
}
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
- // if we have a fully initialized TypeDecl, we can safely read its type now.
+ // We have a fully initialized TypeDecl. Read its type now.
TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull());
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
// if we have a fully initialized TypeDecl, we can safely read its type now.
@@ -474,7 +494,8 @@
} else
TD->NamedDeclOrQualifier = ReadDeclAs<NamedDecl>(Record, Idx);
- mergeRedeclarable(TD, Redecl);
+ if (!isa<CXXRecordDecl>(TD))
+ mergeRedeclarable(TD, Redecl);
return Redecl;
}
@@ -576,9 +597,10 @@
switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
case FunctionDecl::TK_NonTemplate:
- mergeRedeclarable(FD, Redecl);
+ mergeRedeclarable(FD, Redecl);
break;
case FunctionDecl::TK_FunctionTemplate:
+ // Merged when we merge the template.
FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record,
Idx));
break;
@@ -588,6 +610,7 @@
SourceLocation POI = ReadSourceLocation(Record, Idx);
FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
+ mergeRedeclarable(FD, Redecl);
break;
}
case FunctionDecl::TK_FunctionTemplateSpecialization: {
@@ -625,7 +648,8 @@
FunctionTemplateSpecializationInfo *FTInfo
= FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK,
TemplArgList,
- HasTemplateArgumentsAsWritten ? &TemplArgsInfo : 0,
+ HasTemplateArgumentsAsWritten ? &TemplArgsInfo
+ : nullptr,
POI);
FD->TemplateOrSpecialization = FTInfo;
@@ -642,7 +666,7 @@
llvm::FoldingSetNodeID ID;
FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(),
TemplArgs.size(), C);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr();
CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos);
if (InsertPos)
@@ -673,6 +697,8 @@
FD->setDependentTemplateSpecialization(Reader.getContext(),
TemplDecls, TemplArgs);
+
+ // FIXME: Merging.
break;
}
}
@@ -783,8 +809,8 @@
Reader.getContext());
// We will rebuild this list lazily.
- ID->setIvarList(0);
-
+ ID->setIvarList(nullptr);
+
// Note that we have deserialized a definition.
Reader.PendingDefinitions.insert(ID);
@@ -799,7 +825,7 @@
VisitFieldDecl(IVD);
IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
// This field will be built lazily.
- IVD->setNextIvar(0);
+ IVD->setNextIvar(nullptr);
bool synth = Record[Idx++];
IVD->setSynthesize(synth);
}
@@ -977,10 +1003,6 @@
VD->getLexicalDeclContext()->isFunctionOrMethod())
VD->setLocalExternDecl();
- // Only true variables (not parameters or implicit parameters) can be merged.
- if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam)
- mergeRedeclarable(VD, Redecl);
-
if (uint64_t Val = Record[Idx++]) {
VD->setInit(Reader.ReadExpr(F));
if (Val > 1) {
@@ -995,8 +1017,12 @@
};
switch ((VarKind)Record[Idx++]) {
case VarNotTemplate:
+ // Only true variables (not parameters or implicit parameters) can be merged
+ if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam)
+ mergeRedeclarable(VD, Redecl);
break;
case VarTemplate:
+ // Merged when we merge the template.
VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx));
break;
case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo.
@@ -1004,6 +1030,7 @@
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
SourceLocation POI = ReadSourceLocation(Record, Idx);
Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
+ mergeRedeclarable(VD, Redecl);
break;
}
}
@@ -1067,7 +1094,7 @@
unsigned flags = Record[Idx++];
bool byRef = (flags & 1);
bool nested = (flags & 2);
- Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : 0);
+ Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : nullptr);
captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr));
}
@@ -1077,9 +1104,15 @@
void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) {
VisitDecl(CD);
+ unsigned ContextParamPos = Record[Idx++];
+ CD->setNothrow(Record[Idx++] != 0);
// Body is set by VisitCapturedStmt.
- for (unsigned i = 0; i < CD->NumParams; ++i)
- CD->setParam(i, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
+ for (unsigned I = 0; I < CD->NumParams; ++I) {
+ if (I != ContextParamPos)
+ CD->setParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
+ else
+ CD->setContextParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
+ }
}
void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
@@ -1199,6 +1232,7 @@
Data.DefaultedMoveAssignmentIsDeleted = Record[Idx++];
Data.DefaultedDestructorIsDeleted = Record[Idx++];
Data.HasTrivialSpecialMembers = Record[Idx++];
+ Data.DeclaredNonTrivialSpecialMembers = Record[Idx++];
Data.HasIrrelevantDestructor = Record[Idx++];
Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
@@ -1225,7 +1259,7 @@
Data.FirstFriend = ReadDeclID(Record, Idx);
if (Data.IsLambda) {
- typedef LambdaExpr::Capture Capture;
+ typedef LambdaCapture Capture;
CXXRecordDecl::LambdaDefinitionData &Lambda
= static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
Lambda.Dependent = Record[Idx++];
@@ -1245,7 +1279,7 @@
LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]);
switch (Kind) {
case LCK_This:
- *ToCapture++ = Capture(Loc, IsImplicit, Kind, 0, SourceLocation());
+ *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation());
break;
case LCK_ByCopy:
case LCK_ByRef:
@@ -1258,61 +1292,170 @@
}
}
+void ASTDeclReader::MergeDefinitionData(
+ CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &MergeDD) {
+ assert(D->DefinitionData.getNotUpdated() &&
+ "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.
+ if ((MergeDD.DeclaredSpecialMembers & ~DD.DeclaredSpecialMembers) &&
+ DD.Definition != MergeDD.Definition) {
+ Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
+ DD.Definition->setHasExternalVisibleStorage();
+ }
+
+ // FIXME: Move this out into a .def file?
+ // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than
+ // asserting; this can happen in the case of an ODR violation.
+ bool DetectedOdrViolation = false;
+#define OR_FIELD(Field) DD.Field |= MergeDD.Field;
+#define MATCH_FIELD(Field) \
+ DetectedOdrViolation |= DD.Field != MergeDD.Field; \
+ OR_FIELD(Field)
+ MATCH_FIELD(UserDeclaredConstructor)
+ MATCH_FIELD(UserDeclaredSpecialMembers)
+ MATCH_FIELD(Aggregate)
+ MATCH_FIELD(PlainOldData)
+ MATCH_FIELD(Empty)
+ MATCH_FIELD(Polymorphic)
+ MATCH_FIELD(Abstract)
+ MATCH_FIELD(IsStandardLayout)
+ MATCH_FIELD(HasNoNonEmptyBases)
+ MATCH_FIELD(HasPrivateFields)
+ MATCH_FIELD(HasProtectedFields)
+ MATCH_FIELD(HasPublicFields)
+ MATCH_FIELD(HasMutableFields)
+ MATCH_FIELD(HasVariantMembers)
+ MATCH_FIELD(HasOnlyCMembers)
+ MATCH_FIELD(HasInClassInitializer)
+ MATCH_FIELD(HasUninitializedReferenceMember)
+ MATCH_FIELD(NeedOverloadResolutionForMoveConstructor)
+ MATCH_FIELD(NeedOverloadResolutionForMoveAssignment)
+ MATCH_FIELD(NeedOverloadResolutionForDestructor)
+ MATCH_FIELD(DefaultedMoveConstructorIsDeleted)
+ MATCH_FIELD(DefaultedMoveAssignmentIsDeleted)
+ MATCH_FIELD(DefaultedDestructorIsDeleted)
+ OR_FIELD(HasTrivialSpecialMembers)
+ OR_FIELD(DeclaredNonTrivialSpecialMembers)
+ MATCH_FIELD(HasIrrelevantDestructor)
+ OR_FIELD(HasConstexprNonCopyMoveConstructor)
+ MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
+ OR_FIELD(HasConstexprDefaultConstructor)
+ MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
+ // ComputedVisibleConversions is handled below.
+ MATCH_FIELD(UserProvidedDefaultConstructor)
+ OR_FIELD(DeclaredSpecialMembers)
+ MATCH_FIELD(ImplicitCopyConstructorHasConstParam)
+ MATCH_FIELD(ImplicitCopyAssignmentHasConstParam)
+ OR_FIELD(HasDeclaredCopyConstructorWithConstParam)
+ OR_FIELD(HasDeclaredCopyAssignmentWithConstParam)
+ MATCH_FIELD(IsLambda)
+#undef OR_FIELD
+#undef MATCH_FIELD
+
+ if (DD.NumBases != MergeDD.NumBases || DD.NumVBases != MergeDD.NumVBases)
+ DetectedOdrViolation = true;
+ // FIXME: Issue a diagnostic if the base classes don't match when we come
+ // to lazily load them.
+
+ // FIXME: Issue a diagnostic if the list of conversion functions doesn't
+ // match when we come to lazily load them.
+ if (MergeDD.ComputedVisibleConversions && !DD.ComputedVisibleConversions) {
+ DD.VisibleConversions = std::move(MergeDD.VisibleConversions);
+ DD.ComputedVisibleConversions = true;
+ }
+
+ // FIXME: Issue a diagnostic if FirstFriend doesn't match when we come to
+ // lazily load it.
+
+ if (DD.IsLambda) {
+ // FIXME: ODR-checking for merging lambdas (this happens, for instance,
+ // when they occur within the body of a function template specialization).
+ }
+
+ if (DetectedOdrViolation)
+ Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition);
+}
+
+void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
+ struct CXXRecordDecl::DefinitionData *DD;
+ ASTContext &C = Reader.getContext();
+
+ // Determine whether this is a lambda closure type, so that we can
+ // allocate the appropriate DefinitionData structure.
+ bool IsLambda = Record[Idx++];
+ if (IsLambda)
+ DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false,
+ LCD_None);
+ else
+ DD = new (C) struct CXXRecordDecl::DefinitionData(D);
+
+ ReadCXXDefinitionData(*DD, Record, Idx);
+
+ // If we're reading an update record, we might already have a definition for
+ // this record. If so, just merge into it.
+ if (D->DefinitionData.getNotUpdated()) {
+ MergeDefinitionData(D, *DD);
+ return;
+ }
+
+ // Propagate the DefinitionData pointer to the canonical declaration, so
+ // that all other deserialized declarations will see it.
+ CXXRecordDecl *Canon = D->getCanonicalDecl();
+ if (Canon == D) {
+ D->DefinitionData = DD;
+ D->IsCompleteDefinition = true;
+ } else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) {
+ // We have already deserialized a definition of this record. This
+ // definition is no longer really a definition. Note that the pre-existing
+ // definition is the *real* definition.
+ Reader.MergedDeclContexts.insert(
+ std::make_pair(D, CanonDD->Definition));
+ D->DefinitionData = Canon->DefinitionData;
+ D->IsCompleteDefinition = false;
+ MergeDefinitionData(D, *DD);
+ } else {
+ Canon->DefinitionData = DD;
+ D->DefinitionData = Canon->DefinitionData;
+ D->IsCompleteDefinition = true;
+
+ // Note that we have deserialized a definition. Any declarations
+ // deserialized before this one will be be given the DefinitionData
+ // pointer at the end.
+ Reader.PendingDefinitions.insert(D);
+ }
+}
+
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
RedeclarableResult Redecl = VisitRecordDeclImpl(D);
ASTContext &C = Reader.getContext();
- bool WasDefinition = Record[Idx++];
- if (WasDefinition) {
- // Determine whether this is a lambda closure type, so that we can
- // allocate the appropriate DefinitionData structure.
- bool IsLambda = Record[Idx++];
- if (IsLambda)
- D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0,
- false,
- false, LCD_None);
- else
- D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
-
- ReadCXXDefinitionData(*D->DefinitionData, Record, Idx);
-
- // Propagate the DefinitionData pointer to the canonical declaration, so
- // that all other deserialized declarations will see it.
- CXXRecordDecl *Canon = D->getCanonicalDecl();
- if (Canon == D) {
- // Nothing to do.
- } else if (!Canon->DefinitionData) {
- Canon->DefinitionData = D->DefinitionData;
-
- // Note that we have deserialized a definition. Any declarations
- // deserialized before this one will be be given the DefinitionData
- // pointer at the end.
- Reader.PendingDefinitions.insert(D);
- } else {
- // We have already deserialized a definition of this record. This
- // definition is no longer really a definition. Note that the pre-existing
- // definition is the *real* definition.
- // FIXME: Check DefinitionData for consistency with prior definition.
- Reader.MergedDeclContexts.insert(
- std::make_pair(D, D->getCanonicalDecl()->DefinitionData->Definition));
- D->IsCompleteDefinition = false;
- D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
- }
- } else {
- // Propagate DefinitionData pointer from the canonical declaration.
- D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
- }
enum CXXRecKind {
CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
};
switch ((CXXRecKind)Record[Idx++]) {
case CXXRecNotTemplate:
+ mergeRedeclarable(D, Redecl);
break;
- case CXXRecTemplate:
- D->TemplateOrInstantiation = ReadDeclAs<ClassTemplateDecl>(Record, Idx);
+ case CXXRecTemplate: {
+ // Merged when we merge the template.
+ ClassTemplateDecl *Template = ReadDeclAs<ClassTemplateDecl>(Record, Idx);
+ D->TemplateOrInstantiation = Template;
+ if (!Template->getTemplatedDecl()) {
+ // We've not actually loaded the ClassTemplateDecl yet, because we're
+ // currently being loaded as its pattern. Rely on it to set up our
+ // TypeForDecl (see VisitClassTemplateDecl).
+ //
+ // Beware: we do not yet know our canonical declaration, and may still
+ // get merged once the surrounding class template has got off the ground.
+ TypeIDForTypeDecl = 0;
+ }
break;
+ }
case CXXRecMemberSpecialization: {
CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(Record, Idx);
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
@@ -1320,10 +1463,18 @@
MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK);
MSI->setPointOfInstantiation(POI);
D->TemplateOrInstantiation = MSI;
+ mergeRedeclarable(D, Redecl);
break;
}
}
+ bool WasDefinition = Record[Idx++];
+ if (WasDefinition)
+ ReadCXXRecordDefinition(D);
+ else
+ // Propagate DefinitionData pointer from the canonical declaration.
+ D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
+
// Lazily load the key function to avoid deserializing every method so we can
// compute it.
if (WasDefinition) {
@@ -1352,6 +1503,7 @@
if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx))
D->setInheritedConstructor(CD);
D->IsExplicitSpecified = Record[Idx++];
+ // FIXME: We should defer loading this until we need the constructor's body.
std::tie(D->CtorInitializers, D->NumCtorInitializers) =
Reader.ReadCXXCtorInitializers(F, Record, Idx);
}
@@ -1409,16 +1561,19 @@
D->FriendLoc = ReadSourceLocation(Record, Idx);
}
-void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
+DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D);
- NamedDecl *TemplatedDecl = ReadDeclAs<NamedDecl>(Record, Idx);
+ DeclID PatternID = ReadDeclID(Record, Idx);
+ NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
TemplateParameterList* TemplateParams
= Reader.ReadTemplateParameterList(F, Record, Idx);
D->init(TemplatedDecl, TemplateParams);
// FIXME: If this is a redeclaration of a template from another module, handle
// inheritance of default template arguments.
+
+ return PatternID;
}
ASTDeclReader::RedeclarableResult
@@ -1447,10 +1602,10 @@
}
}
- VisitTemplateDecl(D);
+ DeclID PatternID = VisitTemplateDecl(D);
D->IdentifierNamespace = Record[Idx++];
- mergeRedeclarable(D, Redecl);
+ mergeRedeclarable(D, Redecl, PatternID);
// If we merged the template with a prior declaration chain, merge the common
// pointer.
@@ -1491,8 +1646,14 @@
memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
SpecIDs.size() * sizeof(DeclID));
}
-
- CommonPtr->InjectedClassNameType = Reader.readType(F, Record, Idx);
+ }
+
+ if (D->getTemplatedDecl()->TemplateOrInstantiation) {
+ // We were loaded before our templated declaration was. We've not set up
+ // its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct
+ // it now.
+ Reader.Context.getInjectedClassNameType(
+ D->getTemplatedDecl(), D->getInjectedClassNameSpecialization());
}
}
@@ -1585,16 +1746,16 @@
// This declaration might be a definition. Merge with any existing
// definition.
- if (D->DefinitionData) {
- if (!CanonSpec->DefinitionData) {
- CanonSpec->DefinitionData = D->DefinitionData;
- } else {
- // FIXME: Check DefinitionData for consistency with prior definition
+ if (auto *DDD = D->DefinitionData.getNotUpdated()) {
+ if (auto *CanonDD = CanonSpec->DefinitionData.getNotUpdated()) {
+ MergeDefinitionData(CanonSpec, *DDD);
Reader.PendingDefinitions.erase(D);
Reader.MergedDeclContexts.insert(
- std::make_pair(D, CanonSpec->DefinitionData->Definition));
+ std::make_pair(D, CanonDD->Definition));
D->IsCompleteDefinition = false;
D->DefinitionData = CanonSpec->DefinitionData;
+ } else {
+ CanonSpec->DefinitionData = D->DefinitionData;
}
}
}
@@ -1844,23 +2005,54 @@
/// of the same entity.
template<typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,
- RedeclarableResult &Redecl) {
+ RedeclarableResult &Redecl,
+ DeclID TemplatePatternID) {
// If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules)
return;
if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
if (T *Existing = ExistingRes)
- mergeRedeclarable(D, Existing, Redecl);
+ mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
+}
+
+/// \brief "Cast" to type T, asserting if we don't have an implicit conversion.
+/// We use this to put code in a template that will only be valid for certain
+/// instantiations.
+template<typename T> static T assert_cast(T t) { return t; }
+template<typename T> static T assert_cast(...) {
+ llvm_unreachable("bad assert_cast");
+}
+
+/// \brief Merge together the pattern declarations from two template
+/// declarations.
+void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
+ RedeclarableTemplateDecl *Existing,
+ DeclID DsID) {
+ auto *DPattern = D->getTemplatedDecl();
+ auto *ExistingPattern = Existing->getTemplatedDecl();
+ RedeclarableResult Result(Reader, DsID, DPattern->getKind());
+ if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern))
+ // FIXME: Merge definitions here, if both declarations had definitions.
+ return mergeRedeclarable(DClass, cast<TagDecl>(ExistingPattern),
+ Result);
+ if (auto *DFunction = dyn_cast<FunctionDecl>(DPattern))
+ return mergeRedeclarable(DFunction, cast<FunctionDecl>(ExistingPattern),
+ Result);
+ if (auto *DVar = dyn_cast<VarDecl>(DPattern))
+ return mergeRedeclarable(DVar, cast<VarDecl>(ExistingPattern), Result);
+ llvm_unreachable("merged an unknown kind of redeclarable template");
}
/// \brief Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
-void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing,
- RedeclarableResult &Redecl) {
+void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
+ RedeclarableResult &Redecl,
+ DeclID TemplatePatternID) {
+ T *D = static_cast<T*>(DBase);
T *ExistingCanon = Existing->getCanonicalDecl();
- T *DCanon = static_cast<T*>(D)->getCanonicalDecl();
+ T *DCanon = D->getCanonicalDecl();
if (ExistingCanon != DCanon) {
// Have our redeclaration link point back at the canonical declaration
// of the existing declaration, so that this declaration has the
@@ -1868,11 +2060,15 @@
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
// When we merge a namespace, update its pointer to the first namespace.
- if (NamespaceDecl *Namespace
- = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) {
+ if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
- static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon)));
- }
+ assert_cast<NamespaceDecl*>(ExistingCanon));
+
+ // When we merge a template, merge its pattern.
+ if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
+ mergeTemplatePattern(
+ DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
+ TemplatePatternID);
// Don't introduce DCanon into the set of pending declaration chains.
Redecl.suppress();
@@ -1889,7 +2085,7 @@
// If this declaration was the canonical declaration, make a note of
// that. We accept the linear algorithm here because the number of
// unique canonical declarations of an entity should always be tiny.
- if (DCanon == static_cast<T*>(D)) {
+ if (DCanon == D) {
SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
== Merged.end())
@@ -1947,7 +2143,7 @@
void ASTReader::ReadAttributes(ModuleFile &F, AttrVec &Attrs,
const RecordData &Record, unsigned &Idx) {
for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) {
- Attr *New = 0;
+ Attr *New = nullptr;
attr::Kind Kind = (attr::Kind)Record[Idx++];
SourceRange Range = ReadSourceRange(F, Record, Idx);
@@ -2149,9 +2345,7 @@
// Fields with the same name and the same type match.
if (FieldDecl *FDX = dyn_cast<FieldDecl>(X)) {
FieldDecl *FDY = cast<FieldDecl>(Y);
- // FIXME: Diagnose if the types don't match. More generally, diagnose if we
- // get a declaration in a class definition that isn't in the canonical class
- // definition.
+ // FIXME: Diagnose if the types don't match.
// FIXME: Also check the bitwidth is odr-equivalent, if any.
return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
}
@@ -2181,9 +2375,10 @@
return RD->getDefinition();
if (EnumDecl *ED = dyn_cast<EnumDecl>(DC))
- return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() : 0;
+ return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
+ : nullptr;
- return 0;
+ return nullptr;
}
ASTDeclReader::FindExistingResult::~FindExistingResult() {
@@ -2204,7 +2399,7 @@
DeclarationName Name = D->getDeclName();
if (!Name) {
// Don't bother trying to find unnamed declarations.
- FindExistingResult Result(Reader, D, /*Existing=*/0);
+ FindExistingResult Result(Reader, D, /*Existing=*/nullptr);
Result.suppress();
return Result;
}
@@ -2258,33 +2453,34 @@
// If this declaration is from a merged context, make a note that we need to
// check that the canonical definition of that context contains the decl.
+ //
+ // FIXME: We should do something similar if we merge two definitions of the
+ // same template specialization into the same CXXRecordDecl.
if (Reader.MergedDeclContexts.count(D->getLexicalDeclContext()))
Reader.PendingOdrMergeChecks.push_back(D);
- return FindExistingResult(Reader, D, /*Existing=*/0);
+ return FindExistingResult(Reader, D, /*Existing=*/nullptr);
}
-void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
- assert(D && previous);
- if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- TD->RedeclLink.setNext(cast<TagDecl>(previous));
- } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- FD->RedeclLink.setNext(cast<FunctionDecl>(previous));
- } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- VD->RedeclLink.setNext(cast<VarDecl>(previous));
- } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
- TD->RedeclLink.setNext(cast<TypedefNameDecl>(previous));
- } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
- USD->RedeclLink.setNext(cast<UsingShadowDecl>(previous));
- } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
- ID->RedeclLink.setNext(cast<ObjCInterfaceDecl>(previous));
- } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
- PD->RedeclLink.setNext(cast<ObjCProtocolDecl>(previous));
- } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
- ND->RedeclLink.setNext(cast<NamespaceDecl>(previous));
- } else {
- RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
- TD->RedeclLink.setNext(cast<RedeclarableTemplateDecl>(previous));
+template<typename DeclT>
+void ASTDeclReader::attachPreviousDeclImpl(Redeclarable<DeclT> *D,
+ Decl *Previous) {
+ D->RedeclLink.setPrevious(cast<DeclT>(Previous));
+}
+void ASTDeclReader::attachPreviousDeclImpl(...) {
+ llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
+}
+
+void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *Previous) {
+ assert(D && Previous);
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(TYPE)
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ attachPreviousDeclImpl(cast<TYPE##Decl>(D), Previous); \
+ break;
+#include "clang/AST/DeclNodes.inc"
}
// If the declaration was visible in one module, a redeclaration of it in
@@ -2293,46 +2489,47 @@
// FIXME: In this case, the declaration should only be visible if a module
// that makes it visible has been imported.
D->IdentifierNamespace |=
- previous->IdentifierNamespace &
+ Previous->IdentifierNamespace &
(Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
}
+template<typename DeclT>
+void ASTDeclReader::attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest) {
+ D->RedeclLink.setLatest(cast<DeclT>(Latest));
+}
+void ASTDeclReader::attachLatestDeclImpl(...) {
+ llvm_unreachable("attachLatestDecl on non-redeclarable declaration");
+}
+
void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
assert(D && Latest);
- if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- TD->RedeclLink
- = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest));
- } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- FD->RedeclLink
- = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest));
- } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- VD->RedeclLink
- = Redeclarable<VarDecl>::LatestDeclLink(cast<VarDecl>(Latest));
- } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
- TD->RedeclLink
- = Redeclarable<TypedefNameDecl>::LatestDeclLink(
- cast<TypedefNameDecl>(Latest));
- } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
- USD->RedeclLink
- = Redeclarable<UsingShadowDecl>::LatestDeclLink(
- cast<UsingShadowDecl>(Latest));
- } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
- ID->RedeclLink
- = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink(
- cast<ObjCInterfaceDecl>(Latest));
- } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
- PD->RedeclLink
- = Redeclarable<ObjCProtocolDecl>::LatestDeclLink(
- cast<ObjCProtocolDecl>(Latest));
- } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
- ND->RedeclLink
- = Redeclarable<NamespaceDecl>::LatestDeclLink(
- cast<NamespaceDecl>(Latest));
- } else {
- RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
- TD->RedeclLink
- = Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink(
- cast<RedeclarableTemplateDecl>(Latest));
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(TYPE)
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ attachLatestDeclImpl(cast<TYPE##Decl>(D), Latest); \
+ break;
+#include "clang/AST/DeclNodes.inc"
+ }
+}
+
+template<typename DeclT>
+void ASTDeclReader::markIncompleteDeclChainImpl(Redeclarable<DeclT> *D) {
+ D->RedeclLink.markIncomplete();
+}
+void ASTDeclReader::markIncompleteDeclChainImpl(...) {
+ llvm_unreachable("markIncompleteDeclChain on non-redeclarable declaration");
+}
+
+void ASTReader::markIncompleteDeclChain(Decl *D) {
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(TYPE)
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ ASTDeclReader::markIncompleteDeclChainImpl(cast<TYPE##Decl>(D)); \
+ break;
+#include "clang/AST/DeclNodes.inc"
}
}
@@ -2380,7 +2577,7 @@
unsigned Idx = 0;
ASTDeclReader Reader(*this, *Loc.F, ID, RawLocation, Record,Idx);
- Decl *D = 0;
+ Decl *D = nullptr;
switch ((DeclCode)DeclsCursor.readRecord(Code, Record)) {
case DECL_CONTEXT_LEXICAL:
case DECL_CONTEXT_VISIBLE:
@@ -2562,7 +2759,7 @@
break;
case DECL_CXX_BASE_SPECIFIERS:
Error("attempt to read a C++ base-specifier record as a declaration");
- return 0;
+ return nullptr;
case DECL_IMPORT:
// Note: last entry of the ImportDecl record is the number of stored source
// locations.
@@ -2601,7 +2798,7 @@
LookupDC->setHasExternalVisibleStorage(true);
if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets,
Loc.F->DeclContextInfos[DC]))
- return 0;
+ return nullptr;
}
// Now add the pending visible updates for this decl context, if it has any.
@@ -2622,7 +2819,7 @@
assert(Idx == Record.size());
// Load any relevant update records.
- loadDeclUpdateRecords(ID, D);
+ PendingUpdateRecords.push_back(std::make_pair(ID, D));
// Load the categories after recursive loading is finished.
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
@@ -2856,7 +3053,7 @@
unsigned PreviousGeneration)
: Reader(Reader), InterfaceID(InterfaceID), Interface(Interface),
Deserialized(Deserialized), PreviousGeneration(PreviousGeneration),
- Tail(0)
+ Tail(nullptr)
{
// Populate the name -> category map with the set of known categories.
for (auto *Cat : Interface->known_categories()) {
@@ -2922,12 +3119,14 @@
void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
const RecordData &Record) {
- unsigned Idx = 0;
while (Idx < Record.size()) {
switch ((DeclUpdateKind)Record[Idx++]) {
- case UPD_CXX_ADDED_IMPLICIT_MEMBER:
- cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(ModuleFile, Record, Idx));
+ case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
+ Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
+ assert(MD && "couldn't read decl from update record");
+ cast<CXXRecordDecl>(D)->addedMember(MD);
break;
+ }
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
// It will be added to the template's specializations set when loaded.
@@ -2957,9 +3156,11 @@
case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: {
FunctionDecl *FD = cast<FunctionDecl>(D);
- if (Reader.PendingBodies[FD])
+ if (Reader.PendingBodies[FD]) {
// FIXME: Maybe check for ODR violations.
- break;
+ // It's safe to stop now because this update record is always last.
+ return;
+ }
if (Record[Idx++])
FD->setImplicitlyInline();
@@ -2974,6 +3175,55 @@
break;
}
+ case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
+ auto *RD = cast<CXXRecordDecl>(D);
+ bool HadDefinition = RD->getDefinition();
+ ReadCXXRecordDefinition(RD);
+ // Visible update is handled separately.
+ uint64_t LexicalOffset = Record[Idx++];
+ if (!HadDefinition && LexicalOffset) {
+ RD->setHasExternalLexicalStorage(true);
+ Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
+ std::make_pair(LexicalOffset, 0),
+ ModuleFile.DeclContextInfos[RD]);
+ }
+
+ auto TSK = (TemplateSpecializationKind)Record[Idx++];
+ SourceLocation POI = Reader.ReadSourceLocation(ModuleFile, Record, Idx);
+ if (MemberSpecializationInfo *MSInfo =
+ RD->getMemberSpecializationInfo()) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(POI);
+ } else {
+ ClassTemplateSpecializationDecl *Spec =
+ cast<ClassTemplateSpecializationDecl>(RD);
+ Spec->setTemplateSpecializationKind(TSK);
+ Spec->setPointOfInstantiation(POI);
+
+ if (Record[Idx++]) {
+ auto PartialSpec =
+ ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx);
+ SmallVector<TemplateArgument, 8> TemplArgs;
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ auto *TemplArgList = TemplateArgumentList::CreateCopy(
+ Reader.getContext(), TemplArgs.data(), TemplArgs.size());
+ Spec->setInstantiationOf(PartialSpec, TemplArgList);
+ }
+ }
+
+ RD->setTagKind((TagTypeKind)Record[Idx++]);
+ RD->setLocation(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ RD->setLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ RD->setRBraceLoc(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+
+ if (Record[Idx++]) {
+ AttrVec Attrs;
+ Reader.ReadAttributes(F, Attrs, Record, Idx);
+ D->setAttrsImpl(Attrs, Reader.getContext());
+ }
+ break;
+ }
+
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
auto *FD = cast<FunctionDecl>(D);
auto *FPT = FD->getType()->castAs<FunctionProtoType>();
diff --git a/lib/Serialization/ASTReaderInternals.h b/lib/Serialization/ASTReaderInternals.h
index 9149b18..9f2065e 100644
--- a/lib/Serialization/ASTReaderInternals.h
+++ b/lib/Serialization/ASTReaderInternals.h
@@ -14,9 +14,9 @@
#define LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H
#include "clang/AST/DeclarationName.h"
-#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/OnDiskHashTable.h"
#include <sys/stat.h>
#include <utility>
@@ -46,6 +46,8 @@
/// particular lookup t
typedef llvm::support::ulittle32_t LE32DeclID;
typedef std::pair<LE32DeclID *, LE32DeclID *> data_type;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
/// \brief Special internal key for declaration names.
/// The hash table creates keys for comparison; we do not create
@@ -67,7 +69,7 @@
return a.Kind == b.Kind && a.Data == b.Data;
}
- unsigned ComputeHash(const DeclNameKey &Key) const;
+ hash_value_type ComputeHash(const DeclNameKey &Key) const;
internal_key_type GetInternalKey(const external_key_type& Name) const;
static std::pair<unsigned, unsigned>
@@ -92,13 +94,14 @@
public:
typedef StringRef external_key_type;
typedef StringRef internal_key_type;
-
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
static bool EqualKey(const internal_key_type& a, const internal_key_type& b) {
return a == b;
}
- static unsigned ComputeHash(const internal_key_type& a);
+ static hash_value_type ComputeHash(const internal_key_type& a);
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
@@ -126,11 +129,11 @@
public:
typedef IdentifierInfo * data_type;
-
+
ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F,
- IdentifierInfo *II = 0)
+ IdentifierInfo *II = nullptr)
: Reader(Reader), F(F), KnownII(II) { }
-
+
data_type ReadData(const internal_key_type& k,
const unsigned char* d,
unsigned DataLen);
@@ -140,7 +143,7 @@
/// \brief The on-disk hash table used to contain information about
/// all of the identifiers in the program.
-typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
+typedef llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>
ASTIdentifierLookupTable;
/// \brief Class that performs lookup for a selector's entries in the global
@@ -160,6 +163,8 @@
typedef Selector external_key_type;
typedef external_key_type internal_key_type;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F)
: Reader(Reader), F(F) { }
@@ -169,7 +174,7 @@
return a == b;
}
- static unsigned ComputeHash(Selector Sel);
+ static hash_value_type ComputeHash(Selector Sel);
static const internal_key_type&
GetInternalKey(const external_key_type& x) { return x; }
@@ -182,7 +187,7 @@
};
/// \brief The on-disk hash table used for the global method pool.
-typedef OnDiskChainedHashTable<ASTSelectorLookupTrait>
+typedef llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>
ASTSelectorLookupTable;
/// \brief Trait class used to search the on-disk hash table containing all of
@@ -211,12 +216,14 @@
typedef const internal_key_type &internal_key_ref;
typedef HeaderFileInfo data_type;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS,
const char *FrameworkStrings)
: Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) { }
- static unsigned ComputeHash(internal_key_ref ikey);
+ static hash_value_type ComputeHash(internal_key_ref ikey);
static internal_key_type GetInternalKey(const FileEntry *FE);
bool EqualKey(internal_key_ref a, internal_key_ref b);
@@ -229,7 +236,7 @@
};
/// \brief The on-disk hash table used for known header files.
-typedef OnDiskChainedHashTable<HeaderFileInfoTrait>
+typedef llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>
HeaderFileInfoLookupTable;
} // end namespace clang::serialization::reader
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 9a201d0..89bc7fe 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -176,7 +176,7 @@
(void)NumAttrs;
assert(NumAttrs == S->NumAttrs);
assert(NumAttrs == Attrs.size());
- std::copy(Attrs.begin(), Attrs.end(), S->Attrs);
+ std::copy(Attrs.begin(), Attrs.end(), S->getAttrArrayPtr());
S->SubStmt = Reader.ReadSubStmt();
S->AttrLoc = ReadSourceLocation(Record, Idx);
}
@@ -202,7 +202,7 @@
if (Record[Idx++])
S->setAllEnumCasesCovered();
- SwitchCase *PrevSC = 0;
+ SwitchCase *PrevSC = nullptr;
for (unsigned N = Record.size(); Idx != N; ++Idx) {
SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]);
if (PrevSC)
@@ -716,7 +716,7 @@
E->setLBraceLoc(ReadSourceLocation(Record, Idx));
E->setRBraceLoc(ReadSourceLocation(Record, Idx));
bool isArrayFiller = Record[Idx++];
- Expr *filler = 0;
+ Expr *filler = nullptr;
if (isArrayFiller) {
filler = Reader.ReadSubExpr();
E->ArrayFillerOrUnionFieldInit = filler;
@@ -1572,8 +1572,10 @@
void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
VisitExpr(E);
- E->Temporary = Reader.ReadSubExpr();
- E->ExtendingDecl = ReadDeclAs<ValueDecl>(Record, Idx);
+ E->State = Reader.ReadSubExpr();
+ auto VD = ReadDeclAs<ValueDecl>(Record, Idx);
+ unsigned ManglingNumber = Record[Idx++];
+ E->setExtendingDecl(VD, ManglingNumber);
}
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
@@ -1680,9 +1682,15 @@
case OMPC_safelen:
C = new (Context) OMPSafelenClause();
break;
+ case OMPC_collapse:
+ C = new (Context) OMPCollapseClause();
+ break;
case OMPC_default:
C = new (Context) OMPDefaultClause();
break;
+ case OMPC_proc_bind:
+ C = new (Context) OMPProcBindClause();
+ break;
case OMPC_private:
C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
break;
@@ -1692,6 +1700,9 @@
case OMPC_shared:
C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]);
break;
+ case OMPC_linear:
+ C = OMPLinearClause::CreateEmpty(Context, Record[Idx++]);
+ break;
case OMPC_copyin:
C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
break;
@@ -1718,6 +1729,11 @@
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
+void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) {
+ C->setNumForLoops(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
C->setDefaultKind(
static_cast<OpenMPDefaultClauseKind>(Record[Idx++]));
@@ -1725,6 +1741,13 @@
C->setDefaultKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
}
+void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
+ C->setProcBindKind(
+ static_cast<OpenMPProcBindClauseKind>(Record[Idx++]));
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setProcBindKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
@@ -1755,6 +1778,18 @@
C->setVarRefs(Vars);
}
+void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Vars);
+ C->setStep(Reader->Reader.ReadSubExpr());
+}
+
void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
@@ -1851,7 +1886,7 @@
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
Error("malformed block record in AST file");
- return 0;
+ return nullptr;
case llvm::BitstreamEntry::EndBlock:
goto Done;
case llvm::BitstreamEntry::Record:
@@ -1859,8 +1894,7 @@
break;
}
-
- Stmt *S = 0;
+ Stmt *S = nullptr;
Idx = 0;
Record.clear();
bool Finished = false;
@@ -1878,7 +1912,7 @@
break;
case STMT_NULL_PTR:
- S = 0;
+ S = nullptr;
break;
case STMT_NULL:
@@ -2069,7 +2103,7 @@
S = MemberExpr::Create(Context, Base, IsArrow, QualifierLoc,
TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo,
- HasTemplateKWAndArgsInfo ? &ArgInfo : 0,
+ HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr,
T, VK, OK);
ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc,
MemberD->getDeclName(), Record, Idx);
@@ -2263,7 +2297,7 @@
S = new (Context) MSDependentExistsStmt(SourceLocation(), true,
NestedNameSpecifierLoc(),
DeclarationNameInfo(),
- 0);
+ nullptr);
break;
case STMT_OMP_PARALLEL_DIRECTIVE:
@@ -2361,7 +2395,8 @@
bool HasOtherExprStored = Record[ASTStmtReader::NumExprFields];
if (HasOtherExprStored) {
Expr *SubExpr = ReadSubExpr();
- S = CXXDefaultArgExpr::Create(Context, SourceLocation(), 0, SubExpr);
+ S = CXXDefaultArgExpr::Create(Context, SourceLocation(), nullptr,
+ SubExpr);
} else
S = new (Context) CXXDefaultArgExpr(Empty);
break;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index e4b5cdb..35da82c 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -23,9 +23,9 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
-#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/TargetInfo.h"
@@ -49,6 +49,7 @@
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
#include <algorithm>
#include <cstdio>
@@ -660,7 +661,8 @@
Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
// Emit the block name if present.
- if (Name == 0 || Name[0] == 0) return;
+ if (!Name || Name[0] == 0)
+ return;
Record.clear();
while (*Name)
Record.push_back(*Name++);
@@ -798,6 +800,8 @@
// Control Block.
BLOCK(CONTROL_BLOCK);
RECORD(METADATA);
+ RECORD(MODULE_NAME);
+ RECORD(MODULE_MAP_FILE);
RECORD(IMPORTS);
RECORD(LANGUAGE_OPTIONS);
RECORD(TARGET_OPTIONS);
@@ -862,6 +866,7 @@
RECORD(MACRO_OFFSET);
RECORD(MACRO_TABLE);
RECORD(LATE_PARSED_TEMPLATE);
+ RECORD(OPTIMIZE_PRAGMA_OPTIONS);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -1050,6 +1055,32 @@
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
getClangFullRepositoryVersion());
+ // Module name
+ if (WritingModule) {
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
+ unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+ RecordData Record;
+ Record.push_back(MODULE_NAME);
+ Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name);
+ }
+
+ // Module map file
+ if (WritingModule) {
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(MODULE_MAP_FILE));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename
+ unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+
+ assert(WritingModule->ModuleMap && "missing module map");
+ SmallString<128> ModuleMap(WritingModule->ModuleMap->getName());
+ llvm::sys::fs::make_absolute(ModuleMap);
+ RecordData Record;
+ Record.push_back(MODULE_MAP_FILE);
+ Stream.EmitRecordWithBlob(AbbrevCode, Record, ModuleMap.str());
+ }
+
// Imports
if (Chain) {
serialization::ModuleManager &Mgr = Chain->getModuleManager();
@@ -1065,7 +1096,6 @@
AddSourceLocation((*M)->ImportLoc, Record);
Record.push_back((*M)->File->getSize());
Record.push_back((*M)->File->getModificationTime());
- // FIXME: This writes the absolute path for AST files we depend on.
const std::string &FileName = (*M)->FileName;
Record.push_back(FileName.size());
Record.append(FileName.begin(), FileName.end());
@@ -1109,7 +1139,6 @@
AddString(TargetOpts.Triple, Record);
AddString(TargetOpts.CPU, Record);
AddString(TargetOpts.ABI, Record);
- AddString(TargetOpts.LinkerVersion, Record);
Record.push_back(TargetOpts.FeaturesAsWritten.size());
for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) {
AddString(TargetOpts.FeaturesAsWritten[I], Record);
@@ -1455,8 +1484,10 @@
typedef HeaderFileInfo data_type;
typedef const data_type &data_type_ref;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
- static unsigned ComputeHash(key_type_ref key) {
+ static hash_value_type ComputeHash(key_type_ref key) {
// The hash is based only on size/time of the file, so that the reader can
// match even when symlinking or excess path elements ("foo/../", "../")
// change the form of the name. However, complete path is still the key.
@@ -1548,7 +1579,7 @@
FilesByUID.resize(HS.header_file_size());
HeaderFileInfoTrait GeneratorTrait(*this, HS);
- OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator;
+ llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator;
SmallVector<const char *, 4> SavedStrings;
unsigned NumHeaderSearchEntries = 0;
for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {
@@ -1828,8 +1859,10 @@
typedef Data data_type;
typedef const data_type &data_type_ref;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
- static unsigned ComputeHash(IdentID IdID) {
+ static hash_value_type ComputeHash(IdentID IdID) {
return llvm::hash_value(IdID);
}
@@ -1921,7 +1954,7 @@
llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(),
&compareMacroDirectives);
- OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator;
+ llvm::OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator;
// Emit the macro directives as a list and associate the offset with the
// identifier they belong to.
@@ -2003,6 +2036,7 @@
AddSourceLocation(MI->getDefinitionLoc(), Record);
AddSourceLocation(MI->getDefinitionEndLoc(), Record);
Record.push_back(MI->isUsed());
+ Record.push_back(MI->isUsedForHeaderGuard());
unsigned Code;
if (MI->isObjectLike()) {
Code = PP_MACRO_OBJECT_LIKE;
@@ -2710,9 +2744,12 @@
};
typedef const data_type& data_type_ref;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
+
explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) { }
- static unsigned ComputeHash(Selector Sel) {
+ static hash_value_type ComputeHash(Selector Sel) {
return serialization::ComputeHash(Sel);
}
@@ -2806,7 +2843,7 @@
unsigned NumTableEntries = 0;
// Create and write out the blob that contains selectors and the method pool.
{
- OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;
+ llvm::OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;
ASTMethodPoolTrait Trait(*this);
// Create the on-disk hash table representation. We walk through every
@@ -2966,7 +3003,7 @@
if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, ModID, Overridden))
if (!shouldIgnoreMacro(NextMD, IsModule, PP))
return NextMD;
- return 0;
+ return nullptr;
}
MacroDirective *
@@ -2976,7 +3013,7 @@
getPublicSubmoduleMacro(MD->getPrevious(), ModID, Overridden))
if (!shouldIgnoreMacro(NextMD, IsModule, PP))
return NextMD;
- return 0;
+ return nullptr;
}
/// \brief Traverses the macro directives history and returns the latest
@@ -2992,7 +3029,7 @@
SubmoduleID &ModID,
OverriddenList &Overridden) {
if (!MD)
- return 0;
+ return nullptr;
Overridden.clear();
SubmoduleID OrigModID = ModID;
@@ -3048,7 +3085,7 @@
}
}
- return 0;
+ return nullptr;
}
SubmoduleID getSubmoduleID(MacroDirective *MD) {
@@ -3062,11 +3099,14 @@
typedef IdentID data_type;
typedef data_type data_type_ref;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
+
ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,
IdentifierResolver &IdResolver, bool IsModule)
: Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule) { }
- static unsigned ComputeHash(const IdentifierInfo* II) {
+ static hash_value_type ComputeHash(const IdentifierInfo* II) {
return llvm::HashString(II->getName());
}
@@ -3074,7 +3114,7 @@
EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) {
unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
- MacroDirective *Macro = 0;
+ MacroDirective *Macro = nullptr;
if (isInterestingIdentifier(II, Macro)) {
DataLen += 2; // 2 bytes for builtin ID
DataLen += 2; // 2 bytes for flags
@@ -3137,7 +3177,7 @@
IdentID ID, unsigned) {
using namespace llvm::support;
endian::Writer<little> LE(Out);
- MacroDirective *Macro = 0;
+ MacroDirective *Macro = nullptr;
if (!isInterestingIdentifier(II, Macro)) {
LE.write<uint32_t>(ID << 1);
return;
@@ -3232,7 +3272,7 @@
// Create and write out the blob that contains the identifier
// strings.
{
- OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
+ llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule);
// Look for any identifiers that were named while processing the
@@ -3321,9 +3361,12 @@
typedef DeclContext::lookup_result data_type;
typedef const data_type& data_type_ref;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
+
explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { }
- unsigned ComputeHash(DeclarationName Name) {
+ hash_value_type ComputeHash(DeclarationName Name) {
llvm::FoldingSetNodeID ID;
ID.AddInteger(Name.getNameKind());
@@ -3430,54 +3473,18 @@
};
} // end anonymous namespace
-uint32_t
-ASTWriter::GenerateNameLookupTable(const DeclContext *DC,
- llvm::SmallVectorImpl<char> &LookupTable) {
- assert(!DC->LookupPtr.getInt() && "must call buildLookups first");
+template<typename Visitor>
+static void visitLocalLookupResults(const DeclContext *ConstDC,
+ bool NeedToReconcileExternalVisibleStorage,
+ Visitor AddLookupResult) {
+ // FIXME: We need to build the lookups table, which is logically const.
+ DeclContext *DC = const_cast<DeclContext*>(ConstDC);
assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");
- OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
- ASTDeclContextNameLookupTrait Trait(*this);
-
- // Create the on-disk hash table representation.
- DeclarationName ConstructorName;
- DeclarationName ConversionName;
- SmallVector<NamedDecl *, 8> ConstructorDecls;
- SmallVector<NamedDecl *, 4> ConversionDecls;
-
- auto AddLookupResult = [&](DeclarationName Name,
- DeclContext::lookup_result Result) {
- if (Result.empty())
- return;
-
- // Different DeclarationName values of certain kinds are mapped to
- // identical serialized keys, because we don't want to use type
- // identifiers in the keys (since type ids are local to the module).
- switch (Name.getNameKind()) {
- case DeclarationName::CXXConstructorName:
- // There may be different CXXConstructorName DeclarationName values
- // in a DeclContext because a UsingDecl that inherits constructors
- // has the DeclarationName of the inherited constructors.
- if (!ConstructorName)
- ConstructorName = Name;
- ConstructorDecls.append(Result.begin(), Result.end());
- return;
- case DeclarationName::CXXConversionFunctionName:
- if (!ConversionName)
- ConversionName = Name;
- ConversionDecls.append(Result.begin(), Result.end());
- return;
- default:
- break;
- }
-
- Generator.insert(Name, Result, Trait);
- };
-
SmallVector<DeclarationName, 16> ExternalNames;
- for (auto &Lookup : *DC->getLookupPtr()) {
+ for (auto &Lookup : *DC->buildLookup()) {
if (Lookup.second.hasExternalDecls() ||
- DC->NeedToReconcileExternalVisibleStorage) {
+ NeedToReconcileExternalVisibleStorage) {
// We don't know for sure what declarations are found by this name,
// because the external source might have a different set from the set
// that are in the lookup map, and we can't update it now without
@@ -3495,8 +3502,67 @@
// be imported from an external source.
// FIXME: What if the external source isn't an ASTReader?
for (const auto &Name : ExternalNames)
- // FIXME: const_cast since OnDiskHashTable wants a non-const lookup result.
- AddLookupResult(Name, const_cast<DeclContext*>(DC)->lookup(Name));
+ AddLookupResult(Name, DC->lookup(Name));
+}
+
+void ASTWriter::AddUpdatedDeclContext(const DeclContext *DC) {
+ if (UpdatedDeclContexts.insert(DC) && WritingAST) {
+ // Ensure we emit all the visible declarations.
+ visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage,
+ [&](DeclarationName Name,
+ DeclContext::lookup_const_result Result) {
+ for (auto *Decl : Result)
+ GetDeclRef(Decl);
+ });
+ }
+}
+
+uint32_t
+ASTWriter::GenerateNameLookupTable(const DeclContext *DC,
+ llvm::SmallVectorImpl<char> &LookupTable) {
+ assert(!DC->LookupPtr.getInt() && "must call buildLookups first");
+
+ llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait>
+ Generator;
+ ASTDeclContextNameLookupTrait Trait(*this);
+
+ // Create the on-disk hash table representation.
+ DeclarationName ConstructorName;
+ DeclarationName ConversionName;
+ SmallVector<NamedDecl *, 8> ConstructorDecls;
+ SmallVector<NamedDecl *, 4> ConversionDecls;
+
+ visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage,
+ [&](DeclarationName Name,
+ DeclContext::lookup_result Result) {
+ if (Result.empty())
+ return;
+
+ // Different DeclarationName values of certain kinds are mapped to
+ // identical serialized keys, because we don't want to use type
+ // identifiers in the keys (since type ids are local to the module).
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ // There may be different CXXConstructorName DeclarationName values
+ // in a DeclContext because a UsingDecl that inherits constructors
+ // has the DeclarationName of the inherited constructors.
+ if (!ConstructorName)
+ ConstructorName = Name;
+ ConstructorDecls.append(Result.begin(), Result.end());
+ return;
+
+ case DeclarationName::CXXConversionFunctionName:
+ if (!ConversionName)
+ ConversionName = Name;
+ ConversionDecls.append(Result.begin(), Result.end());
+ return;
+
+ default:
+ break;
+ }
+
+ Generator.insert(Name, Result, Trait);
+ });
// Add the constructors.
if (!ConstructorDecls.empty()) {
@@ -3505,6 +3571,7 @@
ConstructorDecls.end()),
Trait);
}
+
// Add the conversion functions.
if (!ConversionDecls.empty()) {
Generator.insert(ConversionName,
@@ -3750,7 +3817,7 @@
IEnd = Chain->MergedDecls.end();
I != IEnd; ++I) {
DeclID CanonID = I->first->isFromASTFile()? I->first->getGlobalID()
- : getDeclID(I->first);
+ : GetDeclRef(I->first);
assert(CanonID && "Merged declaration not known?");
Record.push_back(CanonID);
@@ -3784,6 +3851,14 @@
Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);
}
+/// \brief Write the state of 'pragma clang optimize' at the end of the module.
+void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
+ RecordData Record;
+ SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation();
+ AddSourceLocation(PragmaLoc, Record);
+ Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record);
+}
+
//===----------------------------------------------------------------------===//
// General Serialization Routines
//===----------------------------------------------------------------------===//
@@ -3857,8 +3932,8 @@
}
ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
- : Stream(Stream), Context(0), PP(0), Chain(0), WritingModule(0),
- WritingAST(false), DoneWritingDeclsAndTypes(false),
+ : Stream(Stream), Context(nullptr), PP(nullptr), Chain(nullptr),
+ WritingModule(nullptr), WritingAST(false), DoneWritingDeclsAndTypes(false),
ASTHasCompilerErrors(false),
FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID),
FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
@@ -3905,18 +3980,18 @@
PP = &SemaRef.PP;
this->WritingModule = WritingModule;
WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule);
- Context = 0;
- PP = 0;
- this->WritingModule = 0;
-
+ Context = nullptr;
+ PP = nullptr;
+ this->WritingModule = nullptr;
+
WritingAST = false;
}
template<typename Vector>
static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec,
ASTWriter::RecordData &Record) {
- for (typename Vector::iterator I = Vec.begin(0, true), E = Vec.end();
- I != E; ++I) {
+ for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end();
+ I != E; ++I) {
Writer.AddDeclRef(*I, Record);
}
}
@@ -3927,7 +4002,7 @@
Module *WritingModule) {
using namespace llvm;
- bool isModule = WritingModule != 0;
+ bool isModule = WritingModule != nullptr;
// Make sure that the AST reader knows to finalize itself.
if (Chain)
@@ -3987,6 +4062,15 @@
}
}
+ // If we saw any DeclContext updates before we started writing the AST file,
+ // make sure all visible decls in those DeclContexts are written out.
+ if (!UpdatedDeclContexts.empty()) {
+ auto OldUpdatedDeclContexts = std::move(UpdatedDeclContexts);
+ UpdatedDeclContexts.clear();
+ for (auto *DC : OldUpdatedDeclContexts)
+ AddUpdatedDeclContext(DC);
+ }
+
// Build a record containing all of the tentative definitions in this file, in
// TentativeDefinitions order. Generally, this record will be empty for
// headers.
@@ -4346,11 +4430,8 @@
Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed);
// Write the visible updates to DeclContexts.
- for (llvm::SmallPtrSet<const DeclContext *, 16>::iterator
- I = UpdatedDeclContexts.begin(),
- E = UpdatedDeclContexts.end();
- I != E; ++I)
- WriteDeclContextVisibleUpdate(*I);
+ for (auto *DC : UpdatedDeclContexts)
+ WriteDeclContextVisibleUpdate(DC);
if (!WritingModule) {
// Write the submodules that were imported, if any.
@@ -4394,6 +4475,8 @@
WriteMergedDecls();
WriteObjCCategories();
WriteLateParsedTemplates(SemaRef);
+ if(!WritingModule)
+ WriteOptimizePragmaOptions(SemaRef);
// Some simple statistics
Record.clear();
@@ -4417,9 +4500,6 @@
if (isRewritten(D))
continue; // The decl will be written completely,no need to store updates.
- OffsetsRecord.push_back(GetDeclRef(D));
- OffsetsRecord.push_back(Stream.GetCurrentBitNo());
-
bool HasUpdatedBody = false;
RecordData Record;
for (auto &Update : DeclUpdate.second) {
@@ -4430,6 +4510,7 @@
case UPD_CXX_ADDED_IMPLICIT_MEMBER:
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
+ assert(Update.getDecl() && "no decl to add?");
Record.push_back(GetDeclRef(Update.getDecl()));
break;
@@ -4444,6 +4525,52 @@
HasUpdatedBody = true;
break;
+ case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
+ auto *RD = cast<CXXRecordDecl>(D);
+ AddUpdatedDeclContext(RD->getPrimaryContext());
+ AddCXXDefinitionData(RD, Record);
+ Record.push_back(WriteDeclContextLexicalBlock(
+ *Context, const_cast<CXXRecordDecl *>(RD)));
+
+ // This state is sometimes updated by template instantiation, when we
+ // switch from the specialization referring to the template declaration
+ // to it referring to the template definition.
+ if (auto *MSInfo = RD->getMemberSpecializationInfo()) {
+ Record.push_back(MSInfo->getTemplateSpecializationKind());
+ AddSourceLocation(MSInfo->getPointOfInstantiation(), Record);
+ } else {
+ auto *Spec = cast<ClassTemplateSpecializationDecl>(RD);
+ Record.push_back(Spec->getTemplateSpecializationKind());
+ AddSourceLocation(Spec->getPointOfInstantiation(), Record);
+
+ // The instantiation might have been resolved to a partial
+ // specialization. If so, record which one.
+ auto From = Spec->getInstantiatedFrom();
+ if (auto PartialSpec =
+ From.dyn_cast<ClassTemplatePartialSpecializationDecl*>()) {
+ Record.push_back(true);
+ AddDeclRef(PartialSpec, Record);
+ AddTemplateArgumentList(&Spec->getTemplateInstantiationArgs(),
+ Record);
+ } else {
+ Record.push_back(false);
+ }
+ }
+ Record.push_back(RD->getTagKind());
+ AddSourceLocation(RD->getLocation(), Record);
+ AddSourceLocation(RD->getLocStart(), Record);
+ AddSourceLocation(RD->getRBraceLoc(), Record);
+
+ // Instantiation may change attributes; write them all out afresh.
+ Record.push_back(D->hasAttrs());
+ if (Record.back())
+ WriteAttributes(ArrayRef<const Attr*>(D->getAttrs().begin(),
+ D->getAttrs().size()), Record);
+
+ // FIXME: Ensure we don't get here for explicit instantiations.
+ break;
+ }
+
case UPD_CXX_RESOLVED_EXCEPTION_SPEC:
addExceptionSpec(
*this,
@@ -4473,10 +4600,16 @@
AddFunctionDefinition(Def, Record);
}
+ OffsetsRecord.push_back(GetDeclRef(D));
+ OffsetsRecord.push_back(Stream.GetCurrentBitNo());
+
Stream.EmitRecord(DECL_UPDATES, Record);
// Flush any statements that were written as part of this update record.
FlushStmts();
+
+ // Flush C++ base specifiers, if there are any.
+ FlushCXXBaseSpecifiers();
}
}
@@ -4523,7 +4656,7 @@
}
IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) {
- if (II == 0)
+ if (!II)
return 0;
IdentID &ID = IdentifierIDs[II];
@@ -4536,7 +4669,7 @@
// Don't emit builtin macros like __LINE__ to the AST file unless they
// have been redefined by the header (in which case they are not
// isBuiltinMacro).
- if (MI == 0 || MI->isBuiltinMacro())
+ if (!MI || MI->isBuiltinMacro())
return 0;
MacroID &ID = MacroIDs[MI];
@@ -4549,7 +4682,7 @@
}
MacroID ASTWriter::getMacroID(MacroInfo *MI) {
- if (MI == 0 || MI->isBuiltinMacro())
+ if (!MI || MI->isBuiltinMacro())
return 0;
assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!");
@@ -4566,7 +4699,7 @@
}
SelectorID ASTWriter::getSelectorRef(Selector Sel) {
- if (Sel.getAsOpaquePtr() == 0) {
+ if (Sel.getAsOpaquePtr() == nullptr) {
return 0;
}
@@ -4644,7 +4777,7 @@
void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo,
RecordDataImpl &Record) {
- if (TInfo == 0) {
+ if (!TInfo) {
AddTypeRef(QualType(), Record);
return;
}
@@ -4712,8 +4845,8 @@
DeclID ASTWriter::GetDeclRef(const Decl *D) {
assert(WritingAST && "Cannot request a declaration ID before AST writing");
-
- if (D == 0) {
+
+ if (!D) {
return 0;
}
@@ -4740,7 +4873,7 @@
}
DeclID ASTWriter::getDeclID(const Decl *D) {
- if (D == 0)
+ if (!D)
return 0;
// If D comes from an AST file, its declaration ID is already known and
@@ -5193,8 +5326,7 @@
}
void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) {
- assert(D->DefinitionData);
- struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData;
+ auto &Data = D->data();
Record.push_back(Data.IsLambda);
Record.push_back(Data.UserDeclaredConstructor);
Record.push_back(Data.UserDeclaredSpecialMembers);
@@ -5220,6 +5352,7 @@
Record.push_back(Data.DefaultedMoveAssignmentIsDeleted);
Record.push_back(Data.DefaultedDestructorIsDeleted);
Record.push_back(Data.HasTrivialSpecialMembers);
+ Record.push_back(Data.DeclaredNonTrivialSpecialMembers);
Record.push_back(Data.HasIrrelevantDestructor);
Record.push_back(Data.HasConstexprNonCopyMoveConstructor);
Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr);
@@ -5252,7 +5385,7 @@
// Add lambda-specific data.
if (Data.IsLambda) {
- CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData();
+ auto &Lambda = D->getLambdaData();
Record.push_back(Lambda.Dependent);
Record.push_back(Lambda.IsGenericLambda);
Record.push_back(Lambda.CaptureDefault);
@@ -5262,7 +5395,7 @@
AddDeclRef(Lambda.ContextDecl, Record);
AddTypeSourceInfo(Lambda.MethodTyInfo, Record);
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
- LambdaExpr::Capture &Capture = Lambda.Captures[I];
+ const LambdaCapture &Capture = Lambda.Captures[I];
AddSourceLocation(Capture.getLocation(), Record);
Record.push_back(Capture.isImplicit());
Record.push_back(Capture.getCaptureKind());
@@ -5272,7 +5405,7 @@
case LCK_ByCopy:
case LCK_ByRef:
VarDecl *Var =
- Capture.capturesVariable() ? Capture.getCapturedVar() : 0;
+ Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr;
AddDeclRef(Var, Record);
AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc()
: SourceLocation(),
@@ -5362,7 +5495,10 @@
// A forward reference was mutated into a definition. Rewrite it.
// FIXME: This happens during template instantiation, should we
// have created a new definition decl instead ?
- RewriteDecl(RD);
+ assert(isTemplateInstantiation(RD->getTemplateSpecializationKind()) &&
+ "completed a tag from another module but not by instantiation?");
+ DeclUpdates[RD].push_back(
+ DeclUpdate(UPD_CXX_INSTANTIATED_CLASS_DEFINITION));
}
}
}
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 14304ab..347473c 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -277,7 +277,7 @@
Record.push_back(MemberInfo->getTemplateSpecializationKind());
Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record);
} else {
- Writer.AddDeclRef(0, Record);
+ Writer.AddDeclRef(nullptr, Record);
}
if (!D->hasAttrs() &&
@@ -398,7 +398,7 @@
Writer.AddTemplateArgumentList(FTSInfo->TemplateArguments, Record);
// Template args as written.
- Record.push_back(FTSInfo->TemplateArgumentsAsWritten != 0);
+ Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr);
if (FTSInfo->TemplateArgumentsAsWritten) {
Record.push_back(FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs);
for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs;
@@ -449,8 +449,8 @@
VisitNamedDecl(D);
// FIXME: convert to LazyStmtPtr?
// Unlike C/C++, method bodies will never be in header files.
- bool HasBodyStuff = D->getBody() != 0 ||
- D->getSelfDecl() != 0 || D->getCmdDecl() != 0;
+ bool HasBodyStuff = D->getBody() != nullptr ||
+ D->getSelfDecl() != nullptr || D->getCmdDecl() != nullptr;
Record.push_back(HasBodyStuff);
if (HasBodyStuff) {
Writer.AddStmt(D->getBody());
@@ -757,7 +757,7 @@
!D->hasExtInfo() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
D->getInitStyle() == VarDecl::CInit &&
- D->getInit() == 0 &&
+ D->getInit() == nullptr &&
!isa<ParmVarDecl>(D) &&
!isa<VarTemplateSpecializationDecl>(D) &&
!D->isConstexpr() &&
@@ -806,7 +806,7 @@
D->getObjCDeclQualifier() == 0 &&
!D->isKNRPromoted() &&
!D->hasInheritedDefaultArg() &&
- D->getInit() == 0 &&
+ D->getInit() == nullptr &&
!D->hasUninstantiatedDefaultArg()) // No default expr.
AbbrevToUse = Writer.getDeclParmVarAbbrev();
@@ -815,7 +815,7 @@
assert(!D->getTSCSpec() && "PARM_VAR_DECL can't use TLS");
assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
- assert(D->getPreviousDecl() == 0 && "PARM_VAR_DECL can't be redecl");
+ assert(D->getPreviousDecl() == nullptr && "PARM_VAR_DECL can't be redecl");
assert(!D->isStaticDataMember() &&
"PARM_VAR_DECL can't be static data member");
}
@@ -863,9 +863,11 @@
void ASTDeclWriter::VisitCapturedDecl(CapturedDecl *CD) {
Record.push_back(CD->getNumParams());
VisitDecl(CD);
+ Record.push_back(CD->getContextParamPosition());
+ Record.push_back(CD->isNothrow() ? 1 : 0);
// Body is stored by VisitCapturedStmt.
- for (unsigned i = 0; i < CD->getNumParams(); ++i)
- Writer.AddDeclRef(CD->getParam(i), Record);
+ for (unsigned I = 0; I < CD->getNumParams(); ++I)
+ Writer.AddDeclRef(CD->getParam(I), Record);
Code = serialization::DECL_CAPTURED;
}
@@ -984,9 +986,6 @@
void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
VisitRecordDecl(D);
- Record.push_back(D->isThisDeclarationADefinition());
- if (D->isThisDeclarationADefinition())
- Writer.AddCXXDefinitionData(D, Record);
enum {
CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
@@ -1004,6 +1003,10 @@
Record.push_back(CXXRecNotTemplate);
}
+ Record.push_back(D->isThisDeclarationADefinition());
+ if (D->isThisDeclarationADefinition())
+ Writer.AddCXXDefinitionData(D, Record);
+
// Store (what we currently believe to be) the key function to avoid
// deserializing every method so we can compute it.
if (D->IsCompleteDefinition)
@@ -1101,7 +1104,7 @@
Record.push_back(D->getNumTemplateParameters());
for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i)
Writer.AddTemplateParameterList(D->getTemplateParameterList(i), Record);
- Record.push_back(D->getFriendDecl() != 0);
+ Record.push_back(D->getFriendDecl() != nullptr);
if (D->getFriendDecl())
Writer.AddDeclRef(D->getFriendDecl(), Record);
else
@@ -1153,8 +1156,6 @@
assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
Writer.AddDeclRef(&*I, Record);
}
-
- Writer.AddTypeRef(D->getCommonPtr()->InjectedClassNameType, Record);
}
Code = serialization::DECL_CLASS_TEMPLATE;
}
@@ -1202,7 +1203,7 @@
Writer.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten(), Record);
// These are read/set from/to the first declaration.
- if (D->getPreviousDecl() == 0) {
+ if (D->getPreviousDecl() == nullptr) {
Writer.AddDeclRef(D->getInstantiatedFromMember(), Record);
Record.push_back(D->isMemberSpecialization());
}
@@ -1278,7 +1279,7 @@
Writer.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten(), Record);
// These are read/set from/to the first declaration.
- if (D->getPreviousDecl() == 0) {
+ if (D->getPreviousDecl() == nullptr) {
Writer.AddDeclRef(D->getInstantiatedFromMember(), Record);
Record.push_back(D->isMemberSpecialization());
}
@@ -1345,7 +1346,7 @@
} else {
// Rest of NonTypeTemplateParmDecl.
Record.push_back(D->isParameterPack());
- Record.push_back(D->getDefaultArgument() != 0);
+ Record.push_back(D->getDefaultArgument() != nullptr);
if (D->getDefaultArgument()) {
Writer.AddStmt(D->getDefaultArgument());
Record.push_back(D->defaultArgumentWasInherited());
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index dd44a69..a79772a 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -308,7 +308,7 @@
// Captures
for (const auto &I : S->captures()) {
if (I.capturesThis())
- Writer.AddDeclRef(0, Record);
+ Writer.AddDeclRef(nullptr, Record);
else
Writer.AddDeclRef(I.getCapturedVar(), Record);
Record.push_back(I.getCaptureKind());
@@ -687,7 +687,7 @@
// Replace them by 0 to indicate that the filler goes in that place.
Expr *filler = E->getArrayFiller();
for (unsigned I = 0, N = E->getNumInits(); I != N; ++I)
- Writer.AddStmt(E->getInit(I) != filler ? E->getInit(I) : 0);
+ Writer.AddStmt(E->getInit(I) != filler ? E->getInit(I) : nullptr);
} else {
for (unsigned I = 0, N = E->getNumInits(); I != N; ++I)
Writer.AddStmt(E->getInit(I));
@@ -1051,7 +1051,7 @@
void ASTStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
Record.push_back(S->getNumCatchStmts());
- Record.push_back(S->getFinallyStmt() != 0);
+ Record.push_back(S->getFinallyStmt() != nullptr);
Writer.AddStmt(S->getTryBody());
for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I)
Writer.AddStmt(S->getCatchStmt(I));
@@ -1397,7 +1397,7 @@
if (!E->isImplicitAccess())
Writer.AddStmt(E->getBase());
else
- Writer.AddStmt(0);
+ Writer.AddStmt(nullptr);
Writer.AddTypeRef(E->getBaseType(), Record);
Record.push_back(E->isArrow());
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
@@ -1467,7 +1467,7 @@
VisitOverloadExpr(E);
Record.push_back(E->isArrow());
Record.push_back(E->hasUnresolvedUsing());
- Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : 0);
+ Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : nullptr);
Writer.AddTypeRef(E->getBaseType(), Record);
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
Code = serialization::EXPR_CXX_UNRESOLVED_MEMBER;
@@ -1567,8 +1567,9 @@
void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
VisitExpr(E);
- Writer.AddStmt(E->Temporary);
- Writer.AddDeclRef(E->ExtendingDecl, Record);
+ Writer.AddStmt(E->getTemporary());
+ Writer.AddDeclRef(E->getExtendingDecl(), Record);
+ Record.push_back(E->getManglingNumber());
Code = serialization::EXPR_MATERIALIZE_TEMPORARY;
}
@@ -1689,38 +1690,58 @@
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
+void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {
+ Writer->Writer.AddStmt(C->getNumForLoops());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
Record.push_back(C->getDefaultKind());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getDefaultKindKwLoc(), Record);
}
+void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
+ Record.push_back(C->getProcBindKind());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ Writer->Writer.AddSourceLocation(C->getProcBindKindKwLoc(), Record);
+}
+
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (auto *I : C->varlists())
- Writer->Writer.AddStmt(I);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
}
void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (auto *I : C->varlists())
- Writer->Writer.AddStmt(I);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
}
void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (auto *I : C->varlists())
- Writer->Writer.AddStmt(I);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
+}
+
+void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
+ Record.push_back(C->varlist_size());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
+ Writer->Writer.AddStmt(C->getStep());
}
void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (auto *I : C->varlists())
- Writer->Writer.AddStmt(I);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Serialization/GeneratePCH.cpp b/lib/Serialization/GeneratePCH.cpp
index 7e8baa2..b5031fd 100644
--- a/lib/Serialization/GeneratePCH.cpp
+++ b/lib/Serialization/GeneratePCH.cpp
@@ -31,7 +31,7 @@
raw_ostream *OS, bool AllowASTWithErrors)
: PP(PP), OutputFile(OutputFile), Module(Module),
isysroot(isysroot.str()), Out(OS),
- SemaPtr(0), Stream(Buffer), Writer(Stream),
+ SemaPtr(nullptr), Stream(Buffer), Writer(Stream),
AllowASTWithErrors(AllowASTWithErrors),
HasEmittedPCH(false) {
}
diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp
index 14b149f..69c331b 100644
--- a/lib/Serialization/GlobalModuleIndex.cpp
+++ b/lib/Serialization/GlobalModuleIndex.cpp
@@ -13,7 +13,7 @@
#include "ASTReaderInternals.h"
#include "clang/Basic/FileManager.h"
-#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/Module.h"
@@ -26,6 +26,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
#include <cstdio>
using namespace clang;
@@ -71,12 +72,14 @@
typedef StringRef external_key_type;
typedef StringRef internal_key_type;
typedef SmallVector<unsigned, 2> data_type;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
static bool EqualKey(const internal_key_type& a, const internal_key_type& b) {
return a == b;
}
- static unsigned ComputeHash(const internal_key_type& a) {
+ static hash_value_type ComputeHash(const internal_key_type& a) {
return llvm::HashString(a);
}
@@ -114,7 +117,8 @@
}
};
-typedef OnDiskChainedHashTable<IdentifierIndexReaderTrait> IdentifierIndexTable;
+typedef llvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait>
+ IdentifierIndexTable;
}
@@ -202,7 +206,12 @@
assert(Idx == Record.size() && "More module info?");
// Record this module as an unresolved module.
- UnresolvedModules[llvm::sys::path::stem(Modules[ID].FileName)] = ID;
+ // FIXME: this doesn't work correctly for module names containing path
+ // separators.
+ StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName);
+ // Remove the -<hash of ModuleMapPath>
+ ModuleName = ModuleName.rsplit('-').first;
+ UnresolvedModules[ModuleName] = ID;
break;
}
@@ -210,16 +219,18 @@
// Wire up the identifier index.
if (Record[0]) {
IdentifierIndex = IdentifierIndexTable::Create(
- (const unsigned char *)Blob.data() + Record[0],
- (const unsigned char *)Blob.data(),
- IdentifierIndexReaderTrait());
+ (const unsigned char *)Blob.data() + Record[0],
+ (const unsigned char *)Blob.data() + sizeof(uint32_t),
+ (const unsigned char *)Blob.data(), IdentifierIndexReaderTrait());
}
break;
}
}
}
-GlobalModuleIndex::~GlobalModuleIndex() { }
+GlobalModuleIndex::~GlobalModuleIndex() {
+ delete static_cast<IdentifierIndexTable *>(IdentifierIndex);
+}
std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode>
GlobalModuleIndex::readIndex(StringRef Path) {
@@ -231,7 +242,7 @@
std::unique_ptr<llvm::MemoryBuffer> Buffer;
if (llvm::MemoryBuffer::getFile(IndexPath.c_str(), Buffer) !=
llvm::errc::success)
- return std::make_pair((GlobalModuleIndex *)0, EC_NotFound);
+ return std::make_pair(nullptr, EC_NotFound);
/// \brief The bitstream reader from which we'll read the AST file.
llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(),
@@ -245,7 +256,7 @@
Cursor.Read(8) != 'C' ||
Cursor.Read(8) != 'G' ||
Cursor.Read(8) != 'I') {
- return std::make_pair((GlobalModuleIndex *)0, EC_IOError);
+ return std::make_pair(nullptr, EC_IOError);
}
return std::make_pair(new GlobalModuleIndex(Buffer.release(), Cursor),
@@ -307,7 +318,7 @@
bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) {
// Look for the module in the global module index based on the module name.
- StringRef Name = llvm::sys::path::stem(File->FileName);
+ StringRef Name = File->ModuleName;
llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name);
if (Known == UnresolvedModules.end()) {
return true;
@@ -342,6 +353,19 @@
std::fprintf(stderr, "\n");
}
+void GlobalModuleIndex::dump() {
+ llvm::errs() << "*** Global Module Index Dump:\n";
+ llvm::errs() << "Module files:\n";
+ for (auto &MI : Modules) {
+ llvm::errs() << "** " << MI.FileName << "\n";
+ if (MI.File)
+ MI.File->dump();
+ else
+ llvm::errs() << "\n";
+ }
+ llvm::errs() << "\n";
+}
+
//----------------------------------------------------------------------------//
// Global module index writer.
//----------------------------------------------------------------------------//
@@ -412,7 +436,7 @@
Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
// Emit the block name if present.
- if (Name == 0 || Name[0] == 0) return;
+ if (!Name || Name[0] == 0) return;
Record.clear();
while (*Name)
Record.push_back(*Name++);
@@ -591,11 +615,12 @@
// Handle the identifier table
if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) {
- typedef OnDiskChainedHashTable<InterestingASTIdentifierLookupTrait>
- InterestingIdentifierTable;
+ typedef llvm::OnDiskIterableChainedHashTable<
+ InterestingASTIdentifierLookupTrait> InterestingIdentifierTable;
std::unique_ptr<InterestingIdentifierTable> Table(
InterestingIdentifierTable::Create(
(const unsigned char *)Blob.data() + Record[0],
+ (const unsigned char *)Blob.data() + sizeof(uint32_t),
(const unsigned char *)Blob.data()));
for (InterestingIdentifierTable::data_iterator D = Table->data_begin(),
DEnd = Table->data_end();
@@ -624,8 +649,10 @@
typedef StringRef key_type_ref;
typedef SmallVector<unsigned, 2> data_type;
typedef const SmallVector<unsigned, 2> &data_type_ref;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
- static unsigned ComputeHash(key_type_ref Key) {
+ static hash_value_type ComputeHash(key_type_ref Key) {
return llvm::HashString(Key);
}
@@ -696,7 +723,7 @@
// Write the identifier -> module file mapping.
{
- OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator;
+ llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator;
IdentifierIndexWriterTrait Trait;
// Populate the hash table.
diff --git a/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp
index 2eb3971..6f2a3c2 100644
--- a/lib/Serialization/Module.cpp
+++ b/lib/Serialization/Module.cpp
@@ -21,27 +21,27 @@
using namespace reader;
ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
- : Kind(Kind), File(0), DirectlyImported(false),
+ : Kind(Kind), File(nullptr), DirectlyImported(false),
Generation(Generation), SizeInBits(0),
LocalNumSLocEntries(0), SLocEntryBaseID(0),
- SLocEntryBaseOffset(0), SLocEntryOffsets(0),
+ SLocEntryBaseOffset(0), SLocEntryOffsets(nullptr),
LocalNumIdentifiers(0),
- IdentifierOffsets(0), BaseIdentifierID(0), IdentifierTableData(0),
- IdentifierLookupTable(0),
- LocalNumMacros(0), MacroOffsets(0),
+ IdentifierOffsets(nullptr), BaseIdentifierID(0),
+ IdentifierTableData(nullptr), IdentifierLookupTable(nullptr),
+ LocalNumMacros(0), MacroOffsets(nullptr),
BasePreprocessedEntityID(0),
- PreprocessedEntityOffsets(0), NumPreprocessedEntities(0),
+ PreprocessedEntityOffsets(nullptr), NumPreprocessedEntities(0),
LocalNumHeaderFileInfos(0),
- HeaderFileInfoTableData(0), HeaderFileInfoTable(0),
+ HeaderFileInfoTableData(nullptr), HeaderFileInfoTable(nullptr),
LocalNumSubmodules(0), BaseSubmoduleID(0),
- LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0),
- SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0),
- DeclOffsets(0), BaseDeclID(0),
- LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0),
- FileSortedDecls(0), NumFileSortedDecls(0),
- RedeclarationsMap(0), LocalNumRedeclarationsInMap(0),
- ObjCCategoriesMap(0), LocalNumObjCCategoriesInMap(0),
- LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0)
+ LocalNumSelectors(0), SelectorOffsets(nullptr), BaseSelectorID(0),
+ SelectorLookupTableData(nullptr), SelectorLookupTable(nullptr),
+ LocalNumDecls(0), DeclOffsets(nullptr), BaseDeclID(0),
+ LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr),
+ FileSortedDecls(nullptr), NumFileSortedDecls(0),
+ RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0),
+ ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0),
+ LocalNumTypes(0), TypeOffsets(nullptr), BaseTypeIndex(0)
{}
ModuleFile::~ModuleFile() {
diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp
index 3513eba..5613d37 100644
--- a/lib/Serialization/ModuleManager.cpp
+++ b/lib/Serialization/ModuleManager.cpp
@@ -11,6 +11,7 @@
// modules for the ASTReader.
//
//===----------------------------------------------------------------------===//
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/ModuleManager.h"
@@ -32,14 +33,14 @@
if (Entry)
return lookup(Entry);
- return 0;
+ return nullptr;
}
ModuleFile *ModuleManager::lookup(const FileEntry *File) {
llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known
= Modules.find(File);
if (Known == Modules.end())
- return 0;
+ return nullptr;
return Known->second;
}
@@ -57,7 +58,7 @@
off_t ExpectedSize, time_t ExpectedModTime,
ModuleFile *&Module,
std::string &ErrorStr) {
- Module = 0;
+ Module = nullptr;
// Look for the file entry. This only fails if the expected size or
// modification time differ.
@@ -139,6 +140,11 @@
if (first == last)
return;
+ // The first file entry is about to be rebuilt (or there was an error), so
+ // there should be no references to it. Remove it from the cache to close it,
+ // as Windows doesn't seem to allow renaming over an open file.
+ FileMgr.invalidateCache((*first)->File);
+
// Collect the set of module file pointers that we'll be removing.
llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
@@ -153,11 +159,10 @@
for (ModuleIterator victim = first; victim != last; ++victim) {
Modules.erase((*victim)->File);
- FileMgr.invalidateCache((*victim)->File);
if (modMap) {
- StringRef ModuleName = llvm::sys::path::stem((*victim)->FileName);
+ StringRef ModuleName = (*victim)->ModuleName;
if (Module *mod = modMap->findModule(ModuleName)) {
- mod->setASTFile(0);
+ mod->setASTFile(nullptr);
}
}
delete *victim;
@@ -180,7 +185,7 @@
if (FirstVisitState) {
VisitState *Result = FirstVisitState;
FirstVisitState = FirstVisitState->NextState;
- Result->NextState = 0;
+ Result->NextState = nullptr;
return Result;
}
@@ -189,7 +194,7 @@
}
void ModuleManager::returnVisitState(VisitState *State) {
- assert(State->NextState == 0 && "Visited state is in list?");
+ assert(State->NextState == nullptr && "Visited state is in list?");
State->NextState = FirstVisitState;
FirstVisitState = State;
}
@@ -218,7 +223,7 @@
}
ModuleManager::ModuleManager(FileManager &FileMgr)
- : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(0) { }
+ : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(nullptr) {}
ModuleManager::~ModuleManager() {
for (unsigned i = 0, e = Chain.size(); i != e; ++i)
@@ -278,7 +283,7 @@
assert(VisitOrder.size() == N && "Visitation order is wrong?");
delete FirstVisitState;
- FirstVisitState = 0;
+ FirstVisitState = nullptr;
}
VisitState *State = allocateVisitState();
@@ -380,16 +385,19 @@
off_t ExpectedSize,
time_t ExpectedModTime,
const FileEntry *&File) {
- File = FileMgr.getFile(FileName, /*openFile=*/false, /*cacheFailure=*/false);
+ // Open the file immediately to ensure there is no race between stat'ing and
+ // opening the file.
+ File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false);
if (!File && FileName != "-") {
return false;
}
if ((ExpectedSize && ExpectedSize != File->getSize()) ||
- (ExpectedModTime && ExpectedModTime != File->getModificationTime())) {
+ (ExpectedModTime && ExpectedModTime != File->getModificationTime()))
+ // Do not destroy File, as it may be referenced. If we need to rebuild it,
+ // it will be destroyed by removeModules.
return true;
- }
return false;
}
@@ -429,7 +437,7 @@
}
std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
- return llvm::sys::path::stem(M->FileName);
+ return M->ModuleName;
}
};
}
diff --git a/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
index 3becdca..166471a 100644
--- a/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
@@ -8,8 +8,6 @@
//===----------------------------------------------------------------------===//
// This file reports various statistics about analyzer visitation.
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "StatsChecker"
-
#include "ClangSACheckers.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
@@ -26,6 +24,8 @@
using namespace clang;
using namespace ento;
+#define DEBUG_TYPE "StatsChecker"
+
STATISTIC(NumBlocks,
"The # of blocks in top level functions");
STATISTIC(NumBlocksUnreachable,
@@ -41,7 +41,7 @@
void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
BugReporter &B,
ExprEngine &Eng) const {
- const CFG *C = 0;
+ const CFG *C = nullptr;
const SourceManager &SM = B.getSourceManager();
llvm::SmallPtrSet<const CFGBlock*, 256> reachable;
diff --git a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index a8d7b3a..20360ef 100644
--- a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -45,9 +45,9 @@
private:
const SubRegion *baseRegion;
SVal byteOffset;
-
+
RegionRawOffsetV2()
- : baseRegion(0), byteOffset(UnknownVal()) {}
+ : baseRegion(nullptr), byteOffset(UnknownVal()) {}
public:
RegionRawOffsetV2(const SubRegion* base, SVal offset)
diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 4b2ccd4..d36679d 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "SelectorExtras.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -97,6 +98,18 @@
check::PostStmt<ObjCArrayLiteral> > {
mutable std::unique_ptr<APIMisuse> BT;
+ mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
+ mutable Selector ArrayWithObjectSel;
+ mutable Selector AddObjectSel;
+ mutable Selector InsertObjectAtIndexSel;
+ mutable Selector ReplaceObjectAtIndexWithObjectSel;
+ mutable Selector SetObjectAtIndexedSubscriptSel;
+ mutable Selector ArrayByAddingObjectSel;
+ mutable Selector DictionaryWithObjectForKeySel;
+ mutable Selector SetObjectForKeySel;
+ mutable Selector SetObjectForKeyedSubscriptSel;
+ mutable Selector RemoveObjectForKeySel;
+
void warnIfNilExpr(const Expr *E,
const char *Msg,
CheckerContext &C) const;
@@ -214,50 +227,62 @@
if (Class == FC_NSString) {
Selector S = msg.getSelector();
-
+
if (S.isUnarySelector())
return;
-
- // FIXME: This is going to be really slow doing these checks with
- // lexical comparisons.
-
- std::string NameStr = S.getAsString();
- StringRef Name(NameStr);
- assert(!Name.empty());
-
- // FIXME: Checking for initWithFormat: will not work in most cases
- // yet because [NSString alloc] returns id, not NSString*. We will
- // need support for tracking expected-type information in the analyzer
- // to find these errors.
- if (Name == "caseInsensitiveCompare:" ||
- Name == "compare:" ||
- Name == "compare:options:" ||
- Name == "compare:options:range:" ||
- Name == "compare:options:range:locale:" ||
- Name == "componentsSeparatedByCharactersInSet:" ||
- Name == "initWithFormat:") {
- Arg = 0;
+
+ if (StringSelectors.empty()) {
+ ASTContext &Ctx = C.getASTContext();
+ Selector Sels[] = {
+ getKeywordSelector(Ctx, "caseInsensitiveCompare", nullptr),
+ getKeywordSelector(Ctx, "compare", nullptr),
+ getKeywordSelector(Ctx, "compare", "options", nullptr),
+ getKeywordSelector(Ctx, "compare", "options", "range", nullptr),
+ getKeywordSelector(Ctx, "compare", "options", "range", "locale",
+ nullptr),
+ getKeywordSelector(Ctx, "componentsSeparatedByCharactersInSet",
+ nullptr),
+ getKeywordSelector(Ctx, "initWithFormat",
+ nullptr),
+ getKeywordSelector(Ctx, "localizedCaseInsensitiveCompare", nullptr),
+ getKeywordSelector(Ctx, "localizedCompare", nullptr),
+ getKeywordSelector(Ctx, "localizedStandardCompare", nullptr),
+ };
+ for (Selector KnownSel : Sels)
+ StringSelectors[KnownSel] = 0;
}
+ auto I = StringSelectors.find(S);
+ if (I == StringSelectors.end())
+ return;
+ Arg = I->second;
} else if (Class == FC_NSArray) {
Selector S = msg.getSelector();
if (S.isUnarySelector())
return;
- if (S.getNameForSlot(0).equals("addObject")) {
+ if (ArrayWithObjectSel.isNull()) {
+ ASTContext &Ctx = C.getASTContext();
+ ArrayWithObjectSel = getKeywordSelector(Ctx, "arrayWithObject", nullptr);
+ AddObjectSel = getKeywordSelector(Ctx, "addObject", nullptr);
+ InsertObjectAtIndexSel =
+ getKeywordSelector(Ctx, "insertObject", "atIndex", nullptr);
+ ReplaceObjectAtIndexWithObjectSel =
+ getKeywordSelector(Ctx, "replaceObjectAtIndex", "withObject", nullptr);
+ SetObjectAtIndexedSubscriptSel =
+ getKeywordSelector(Ctx, "setObject", "atIndexedSubscript", nullptr);
+ ArrayByAddingObjectSel =
+ getKeywordSelector(Ctx, "arrayByAddingObject", nullptr);
+ }
+
+ if (S == ArrayWithObjectSel || S == AddObjectSel ||
+ S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
Arg = 0;
- } else if (S.getNameForSlot(0).equals("insertObject") &&
- S.getNameForSlot(1).equals("atIndex")) {
- Arg = 0;
- } else if (S.getNameForSlot(0).equals("replaceObjectAtIndex") &&
- S.getNameForSlot(1).equals("withObject")) {
- Arg = 1;
- } else if (S.getNameForSlot(0).equals("setObject") &&
- S.getNameForSlot(1).equals("atIndexedSubscript")) {
+ } else if (S == SetObjectAtIndexedSubscriptSel) {
Arg = 0;
CanBeSubscript = true;
- } else if (S.getNameForSlot(0).equals("arrayByAddingObject")) {
- Arg = 0;
+ } else if (S == ReplaceObjectAtIndexWithObjectSel) {
+ Arg = 1;
}
} else if (Class == FC_NSDictionary) {
Selector S = msg.getSelector();
@@ -265,20 +290,26 @@
if (S.isUnarySelector())
return;
- if (S.getNameForSlot(0).equals("dictionaryWithObject") &&
- S.getNameForSlot(1).equals("forKey")) {
+ if (DictionaryWithObjectForKeySel.isNull()) {
+ ASTContext &Ctx = C.getASTContext();
+ DictionaryWithObjectForKeySel =
+ getKeywordSelector(Ctx, "dictionaryWithObject", "forKey", nullptr);
+ SetObjectForKeySel =
+ getKeywordSelector(Ctx, "setObject", "forKey", nullptr);
+ SetObjectForKeyedSubscriptSel =
+ getKeywordSelector(Ctx, "setObject", "forKeyedSubscript", nullptr);
+ RemoveObjectForKeySel =
+ getKeywordSelector(Ctx, "removeObjectForKey", nullptr);
+ }
+
+ if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
Arg = 0;
warnIfNilArg(C, msg, /* Arg */1, Class);
- } else if (S.getNameForSlot(0).equals("setObject") &&
- S.getNameForSlot(1).equals("forKey")) {
- Arg = 0;
- warnIfNilArg(C, msg, /* Arg */1, Class);
- } else if (S.getNameForSlot(0).equals("setObject") &&
- S.getNameForSlot(1).equals("forKeyedSubscript")) {
+ } else if (S == SetObjectForKeyedSubscriptSel) {
CanBeSubscript = true;
Arg = 0;
warnIfNilArg(C, msg, /* Arg */1, Class, CanBeSubscript);
- } else if (S.getNameForSlot(0).equals("removeObjectForKey")) {
+ } else if (S == RemoveObjectForKeySel) {
Arg = 0;
}
}
@@ -286,7 +317,6 @@
// If argument is '0', report a warning.
if ((Arg != InvalidArgIndex))
warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
-
}
void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
@@ -316,7 +346,7 @@
mutable std::unique_ptr<APIMisuse> BT;
mutable IdentifierInfo* II;
public:
- CFNumberCreateChecker() : II(0) {}
+ CFNumberCreateChecker() : II(nullptr) {}
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
@@ -501,7 +531,8 @@
mutable std::unique_ptr<APIMisuse> BT;
mutable IdentifierInfo *Retain, *Release, *MakeCollectable;
public:
- CFRetainReleaseChecker(): Retain(0), Release(0), MakeCollectable(0) {}
+ CFRetainReleaseChecker()
+ : Retain(nullptr), Release(nullptr), MakeCollectable(nullptr) {}
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
};
} // end anonymous namespace
@@ -810,7 +841,7 @@
CheckerContext &C) const;
public:
- ObjCLoopChecker() : CountSelectorII(0) {}
+ ObjCLoopChecker() : CountSelectorII(nullptr) {}
void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
@@ -850,7 +881,7 @@
ProgramStateRef State,
const ObjCForCollectionStmt *FCS) {
if (!State)
- return NULL;
+ return nullptr;
SVal CollectionVal = C.getSVal(FCS->getCollection());
Optional<DefinedSVal> KnownCollection = CollectionVal.getAs<DefinedSVal>();
@@ -861,7 +892,7 @@
std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
if (StNil && !StNonNil) {
// The collection is nil. This path is infeasible.
- return NULL;
+ return nullptr;
}
return StNonNil;
@@ -875,7 +906,7 @@
ProgramStateRef State,
const ObjCForCollectionStmt *FCS) {
if (!State)
- return NULL;
+ return nullptr;
// See if the collection is one where we /know/ the elements are non-nil.
if (!isKnownNonNilCollectionType(FCS->getCollection()->getType()))
@@ -888,7 +919,7 @@
Optional<Loc> ElementLoc;
if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
- assert(ElemDecl->getInit() == 0);
+ assert(ElemDecl->getInit() == nullptr);
ElementLoc = State->getLValue(ElemDecl, LCtx);
} else {
ElementLoc = State->getSVal(Element, LCtx).getAs<Loc>();
@@ -915,7 +946,7 @@
const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
if (!KnownNonEmpty)
return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
- return (Assumption == *KnownNonEmpty) ? State : NULL;
+ return (Assumption == *KnownNonEmpty) ? State : nullptr;
}
SValBuilder &SvalBuilder = C.getSValBuilder();
@@ -940,7 +971,7 @@
const ObjCForCollectionStmt *FCS,
bool Assumption) {
if (!State)
- return NULL;
+ return nullptr;
SymbolRef CollectionS =
State->getSVal(FCS->getCollection(), C.getLocationContext()).getAsSymbol();
@@ -1055,11 +1086,11 @@
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call) {
const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
if (!Message)
- return 0;
+ return nullptr;
const ObjCMethodDecl *MD = Message->getDecl();
if (!MD)
- return 0;
+ return nullptr;
const ObjCInterfaceDecl *StaticClass;
if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
@@ -1072,11 +1103,11 @@
}
if (!StaticClass)
- return 0;
+ return nullptr;
switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
case FC_None:
- return 0;
+ return nullptr;
case FC_NSArray:
case FC_NSDictionary:
case FC_NSEnumerator:
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index d7c1d94..0693bd6 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -159,24 +159,24 @@
ProgramStateRef state,
const Expr *S,
SVal l,
- const char *message = NULL) const;
+ const char *message = nullptr) const;
ProgramStateRef CheckBufferAccess(CheckerContext &C,
ProgramStateRef state,
const Expr *Size,
const Expr *FirstBuf,
const Expr *SecondBuf,
- const char *firstMessage = NULL,
- const char *secondMessage = NULL,
+ const char *firstMessage = nullptr,
+ const char *secondMessage = nullptr,
bool WarnAboutSize = false) const;
ProgramStateRef CheckBufferAccess(CheckerContext &C,
ProgramStateRef state,
const Expr *Size,
const Expr *Buf,
- const char *message = NULL,
+ const char *message = nullptr,
bool WarnAboutSize = false) const {
// This is a convenience override.
- return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL,
+ return CheckBufferAccess(C, state, Size, Buf, nullptr, message, nullptr,
WarnAboutSize);
}
ProgramStateRef CheckOverlap(CheckerContext &C,
@@ -220,18 +220,18 @@
const Expr *S, SVal l) const {
// If a previous check has failed, propagate the failure.
if (!state)
- return NULL;
+ return nullptr;
ProgramStateRef stateNull, stateNonNull;
std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType());
if (stateNull && !stateNonNull) {
if (!Filter.CheckCStringNullArg)
- return NULL;
+ return nullptr;
ExplodedNode *N = C.generateSink(stateNull);
if (!N)
- return NULL;
+ return nullptr;
if (!BT_Null)
BT_Null.reset(new BuiltinBug(
@@ -250,7 +250,7 @@
report->addRange(S->getSourceRange());
bugreporter::trackNullOrUndefValue(N, S, *report);
C.emitReport(report);
- return NULL;
+ return nullptr;
}
// From here on, assume that the value is non-null.
@@ -265,7 +265,7 @@
const char *warningMsg) const {
// If a previous check has failed, propagate the failure.
if (!state)
- return NULL;
+ return nullptr;
// Check for out of bound array element access.
const MemRegion *R = l.getAsRegion();
@@ -294,7 +294,7 @@
if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateSink(StOutBound);
if (!N)
- return NULL;
+ return nullptr;
if (!BT_Bounds) {
BT_Bounds.reset(new BuiltinBug(
@@ -325,7 +325,7 @@
report->addRange(S->getSourceRange());
C.emitReport(report);
- return NULL;
+ return nullptr;
}
// Array bound check succeeded. From this point forward the array bound
@@ -343,7 +343,7 @@
bool WarnAboutSize) const {
// If a previous check has failed, propagate the failure.
if (!state)
- return NULL;
+ return nullptr;
SValBuilder &svalBuilder = C.getSValBuilder();
ASTContext &Ctx = svalBuilder.getContext();
@@ -356,7 +356,7 @@
SVal BufVal = state->getSVal(FirstBuf, LCtx);
state = checkNonNull(C, state, FirstBuf, BufVal);
if (!state)
- return NULL;
+ return nullptr;
// If out-of-bounds checking is turned off, skip the rest.
if (!Filter.CheckCStringOutOfBounds)
@@ -386,7 +386,7 @@
// If the buffer isn't large enough, abort.
if (!state)
- return NULL;
+ return nullptr;
}
// If there's a second buffer, check it as well.
@@ -394,7 +394,7 @@
BufVal = state->getSVal(SecondBuf, LCtx);
state = checkNonNull(C, state, SecondBuf, BufVal);
if (!state)
- return NULL;
+ return nullptr;
BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType());
if (Optional<Loc> BufLoc = BufStart.getAs<Loc>()) {
@@ -424,7 +424,7 @@
// If a previous check has failed, propagate the failure.
if (!state)
- return NULL;
+ return nullptr;
ProgramStateRef stateTrue, stateFalse;
@@ -449,7 +449,7 @@
if (stateTrue && !stateFalse) {
// If the values are known to be equal, that's automatically an overlap.
emitOverlapBug(C, stateTrue, First, Second);
- return NULL;
+ return nullptr;
}
// assume the two expressions are not equal.
@@ -515,7 +515,7 @@
if (stateTrue && !stateFalse) {
// Overlap!
emitOverlapBug(C, stateTrue, First, Second);
- return NULL;
+ return nullptr;
}
// assume the two expressions don't overlap.
@@ -553,7 +553,7 @@
// If a previous check has failed, propagate the failure.
if (!state)
- return NULL;
+ return nullptr;
SValBuilder &svalBuilder = C.getSValBuilder();
BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
@@ -588,7 +588,7 @@
// We have an overflow. Emit a bug report.
ExplodedNode *N = C.generateSink(stateOverflow);
if (!N)
- return NULL;
+ return nullptr;
if (!BT_AdditionOverflow)
BT_AdditionOverflow.reset(
@@ -606,7 +606,7 @@
BugReport *report = new BugReport(*BT_AdditionOverflow, warning, N);
C.emitReport(report);
- return NULL;
+ return nullptr;
}
// From now on, assume an overflow didn't occur.
@@ -802,7 +802,7 @@
// Get the memory region pointed to by the val.
const MemRegion *bufRegion = val.getAsRegion();
if (!bufRegion)
- return NULL;
+ return nullptr;
// Strip casts off the memory region.
bufRegion = bufRegion->StripCasts();
@@ -810,7 +810,7 @@
// Cast the memory region to a string region.
const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion);
if (!strRegion)
- return NULL;
+ return nullptr;
// Return the actual string in the string region.
return strRegion->getStringLiteral();
@@ -852,7 +852,8 @@
}
return state->invalidateRegions(R, E, C.blockCount(), LCtx,
- CausesPointerEscape, 0, 0, &ITraits);
+ CausesPointerEscape, nullptr, nullptr,
+ &ITraits);
}
// If we have a non-region value by chance, just remove the binding.
@@ -953,7 +954,7 @@
const char * const writeWarning =
"Memory copy function overflows destination buffer";
state = CheckBufferAccess(C, state, Size, Dest, Source,
- writeWarning, /* sourceWarning = */ NULL);
+ writeWarning, /* sourceWarning = */ nullptr);
if (Restricted)
state = CheckOverlap(C, state, Size, Dest, Source);
@@ -978,7 +979,7 @@
} else {
// If we don't know how much we copied, we can at least
// conjure a return value for later.
- SVal result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx,
+ SVal result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx,
C.blockCount());
state = state->BindExpr(CE, LCtx, result);
}
@@ -1120,7 +1121,8 @@
state = CheckBufferAccess(C, state, Size, Left, Right);
if (state) {
// The return value is the comparison result, which we don't know.
- SVal CmpV = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount());
+ SVal CmpV = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx,
+ C.blockCount());
state = state->BindExpr(CE, LCtx, CmpV);
C.addTransition(state);
}
@@ -1230,7 +1232,8 @@
// no guarantee the full string length will actually be returned.
// All we know is the return value is the min of the string length
// and the limit. This is better than nothing.
- result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount());
+ result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx,
+ C.blockCount());
NonLoc resultNL = result.castAs<NonLoc>();
if (strLengthNL) {
@@ -1253,7 +1256,8 @@
// If we don't know the length of the string, conjure a return
// value, so it can be used in constraints, at least.
if (result.isUnknown()) {
- result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount());
+ result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx,
+ C.blockCount());
}
}
@@ -1356,7 +1360,7 @@
// - potential overflows caused by a bound that could exceed the destination
SVal amountCopied = UnknownVal();
SVal maxLastElementIndex = UnknownVal();
- const char *boundWarning = NULL;
+ const char *boundWarning = nullptr;
// If the function is strncpy, strncat, etc... it is bounded.
if (isBounded) {
@@ -1636,7 +1640,7 @@
// If this is a stpcpy-style copy, but we were unable to check for a buffer
// overflow, we still need a result. Conjure a return value.
if (returnEnd && Result.isUnknown()) {
- Result = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount());
+ Result = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());
}
// Set the return value.
@@ -1793,7 +1797,8 @@
if (!canComputeResult) {
// Conjure a symbolic value. It's the best we can do.
- SVal resultVal = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount());
+ SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx,
+ C.blockCount());
state = state->BindExpr(CE, LCtx, resultVal);
}
@@ -1850,7 +1855,7 @@
} else {
assert(SearchStrVal.isUnknown());
// Conjure a symbolic value. It's the best we can do.
- Result = SVB.conjureSymbolVal(0, CE, LCtx, C.blockCount());
+ Result = SVB.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());
}
// Set the return value, and finish.
@@ -1870,7 +1875,7 @@
return false;
// FIXME: Poorly-factored string switches are slow.
- FnCheck evalFunction = 0;
+ FnCheck evalFunction = nullptr;
if (C.isCLibraryFunction(FDecl, "memcpy"))
evalFunction = &CStringChecker::evalMemcpy;
else if (C.isCLibraryFunction(FDecl, "mempcpy"))
@@ -1914,7 +1919,7 @@
// Make sure each function sets its own description.
// (But don't bother in a release build.)
- assert(!(CurrentFunctionDescription = NULL));
+ assert(!(CurrentFunctionDescription = nullptr));
// Check and evaluate the call.
(this->*evalFunction)(C, CE);
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 907f516..adb7a54 100644
--- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -419,7 +419,7 @@
BT = &BT_call_arg;
for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
- const ParmVarDecl *ParamDecl = NULL;
+ const ParmVarDecl *ParamDecl = nullptr;
if(FD && i < FD->getNumParams())
ParamDecl = FD->getParamDecl(i);
if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
@@ -437,7 +437,7 @@
SVal recVal = msg.getReceiverSVal();
if (recVal.isUndef()) {
if (ExplodedNode *N = C.generateSink()) {
- BugType *BT = 0;
+ BugType *BT = nullptr;
switch (msg.getMessageKind()) {
case OCM_Message:
if (!BT_msg_undef)
@@ -560,7 +560,7 @@
Ctx.LongDoubleTy == CanRetTy ||
Ctx.LongLongTy == CanRetTy ||
Ctx.UnsignedLongLongTy == CanRetTy)))) {
- if (ExplodedNode *N = C.generateSink(state, 0 , &Tag))
+ if (ExplodedNode *N = C.generateSink(state, nullptr, &Tag))
emitNilReceiverBug(C, Msg, N);
return;
}
diff --git a/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index e9adf30..3ba063d 100644
--- a/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -55,7 +55,7 @@
const RecordDecl *RD = RT->getDecl();
RecordDecl::field_iterator Iter(RD->field_begin());
RecordDecl::field_iterator End(RD->field_end());
- const FieldDecl *Last = 0;
+ const FieldDecl *Last = nullptr;
for (; Iter != End; ++Iter)
Last = *Iter;
assert(Last && "empty structs should already be handled");
@@ -105,11 +105,11 @@
ProgramStateRef state = C.getState();
const MemRegion *R = state->getSVal(E, C.getLocationContext()).getAsRegion();
- if (R == 0)
+ if (!R)
return;
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
- if (SR == 0)
+ if (!SR)
return;
SValBuilder &svalBuilder = C.getSValBuilder();
diff --git a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index 827a10a..d186144 100644
--- a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -153,7 +153,7 @@
// Get the "dealloc" selector.
IdentifierInfo* II = &Ctx.Idents.get("dealloc");
Selector S = Ctx.Selectors.getSelector(0, &II);
- const ObjCMethodDecl *MD = 0;
+ const ObjCMethodDecl *MD = nullptr;
// Scan the instance methods for "dealloc".
for (const auto *I : D->instance_methods()) {
@@ -233,7 +233,7 @@
bool requiresRelease = PD->getSetterKind() != ObjCPropertyDecl::Assign;
if (scan_ivar_release(MD->getBody(), ID, PD, RS, SelfII, Ctx)
!= requiresRelease) {
- const char *name = 0;
+ const char *name = nullptr;
std::string buf;
llvm::raw_string_ostream os(buf);
diff --git a/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp b/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
index dc53602..cc4c0c3 100644
--- a/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
@@ -106,12 +106,12 @@
MapTy::iterator MI = IMeths.find(S);
- if (MI == IMeths.end() || MI->second == 0)
+ if (MI == IMeths.end() || MI->second == nullptr)
continue;
--NumMethods;
ObjCMethodDecl *MethDerived = MI->second;
- MI->second = 0;
+ MI->second = nullptr;
CompareReturnTypes(MethDerived, M, BR, Ctx, ID, Checker);
}
diff --git a/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
index 5706364..45768b2 100644
--- a/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -149,7 +149,7 @@
.Case("rand_r", &WalkAST::checkCall_rand)
.Case("random", &WalkAST::checkCall_random)
.Case("vfork", &WalkAST::checkCall_vfork)
- .Default(NULL);
+ .Default(nullptr);
// If the callee isn't defined, it is not of security concern.
// Check and evaluate the call.
@@ -189,7 +189,7 @@
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
B->getOpcode() == BO_Comma))
- return NULL;
+ return nullptr;
if (const DeclRefExpr *lhs = getIncrementedVar(B->getLHS(), x, y))
return lhs;
@@ -197,19 +197,19 @@
if (const DeclRefExpr *rhs = getIncrementedVar(B->getRHS(), x, y))
return rhs;
- return NULL;
+ return nullptr;
}
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
const NamedDecl *ND = DR->getDecl();
- return ND == x || ND == y ? DR : NULL;
+ return ND == x || ND == y ? DR : nullptr;
}
if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
return U->isIncrementDecrementOp()
- ? getIncrementedVar(U->getSubExpr(), x, y) : NULL;
+ ? getIncrementedVar(U->getSubExpr(), x, y) : nullptr;
- return NULL;
+ return nullptr;
}
/// CheckLoopConditionForFloat - This check looks for 'for' statements that
@@ -253,14 +253,14 @@
dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParenLValueCasts());
// Does at least one of the variables have a floating point type?
- drLHS = drLHS && drLHS->getType()->isRealFloatingType() ? drLHS : NULL;
- drRHS = drRHS && drRHS->getType()->isRealFloatingType() ? drRHS : NULL;
+ drLHS = drLHS && drLHS->getType()->isRealFloatingType() ? drLHS : nullptr;
+ drRHS = drRHS && drRHS->getType()->isRealFloatingType() ? drRHS : nullptr;
if (!drLHS && !drRHS)
return;
- const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : NULL;
- const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : NULL;
+ const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : nullptr;
+ const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : nullptr;
if (!vdLHS && !vdRHS)
return;
@@ -404,7 +404,7 @@
if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
return;
- // Issue a waring.
+ // Issue a warning.
PathDiagnosticLocation CELoc =
PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
BR.EmitBasicReport(AC->getDecl(), filter.checkName_mktemp,
@@ -688,7 +688,7 @@
if (!FD)
return;
- if (II_setid[0] == NULL) {
+ if (II_setid[0] == nullptr) {
static const char * const identifiers[num_setids] = {
"setuid", "setgid", "seteuid", "setegid",
"setreuid", "setregid"
diff --git a/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp b/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
index 5106b06..a61e658 100644
--- a/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
@@ -47,7 +47,7 @@
if (E->getKind() != UETT_SizeOf)
return;
- // If an explicit type is used in the code, usually the coder knows what he is
+ // If an explicit type is used in the code, usually the coder knows what they are
// doing.
if (E->isArgumentType())
return;
diff --git a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 628cf2c..ad41577 100644
--- a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -44,8 +44,8 @@
mutable std::unique_ptr<BuiltinBug> BT_BreakJail;
public:
- ChrootChecker() : II_chroot(0), II_chdir(0) {}
-
+ ChrootChecker() : II_chroot(nullptr), II_chdir(nullptr) {}
+
static void *getTag() {
static int x;
return &x;
diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index 6001a3c..c1ea767 100644
--- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -140,7 +140,7 @@
ParentMap &parents,
llvm::SmallPtrSet<const VarDecl *, 20> &escaped)
: cfg(cfg), Ctx(ctx), BR(br), Checker(checker), AC(ac), Parents(parents),
- Escaped(escaped), currentBlock(0) {}
+ Escaped(escaped), currentBlock(nullptr) {}
virtual ~DeadStoreObs() {}
@@ -178,7 +178,7 @@
SmallString<64> buf;
llvm::raw_svector_ostream os(buf);
- const char *BugType = 0;
+ const char *BugType = nullptr;
switch (dsk) {
case DeadInit:
diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index 7116e4d..43a2812 100644
--- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -223,7 +223,7 @@
const Expr *RecE = MsgE->getInstanceReceiver();
if (!RecE)
- return 0;
+ return nullptr;
RecE= RecE->IgnoreParenImpCasts();
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) {
@@ -237,7 +237,7 @@
return ObjTy;
}
}
- return 0;
+ return nullptr;
}
// Return a better dynamic type if one can be derived from the cast.
@@ -253,7 +253,7 @@
const ObjCObjectPointerType *NewTy =
CastE->getType()->getAs<ObjCObjectPointerType>();
if (!NewTy)
- return 0;
+ return nullptr;
QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType();
if (OldDTy.isNull()) {
return NewTy;
@@ -261,7 +261,7 @@
const ObjCObjectPointerType *OldTy =
OldDTy->getAs<ObjCObjectPointerType>();
if (!OldTy)
- return 0;
+ return nullptr;
// Id the old type is 'id', the new one is more precise.
if (OldTy->isObjCIdType() && !NewTy->isObjCIdType())
@@ -273,7 +273,7 @@
if (ToI && FromI && FromI->isSuperClassOf(ToI))
return NewTy;
- return 0;
+ return nullptr;
}
void ento::registerDynamicTypePropagation(CheckerManager &mgr) {
diff --git a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 9a0fa09..f36ec2c 100644
--- a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -43,7 +43,7 @@
&ExprInspectionChecker::analyzerCheckInlined)
.Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
.Case("clang_analyzer_warnIfReached", &ExprInspectionChecker::analyzerWarnIfReached)
- .Default(0);
+ .Default(nullptr);
if (!Handler)
return false;
@@ -91,7 +91,7 @@
// A specific instantiation of an inlined function may have more constrained
// values than can generally be assumed. Skip the check.
- if (LC->getCurrentStackFrame()->getParent() != 0)
+ if (LC->getCurrentStackFrame()->getParent() != nullptr)
return;
if (!BT)
@@ -122,7 +122,7 @@
// when we are analyzing it as an inlined function. This means that
// clang_analyzer_checkInlined(true) should always print TRUE, but
// clang_analyzer_checkInlined(false) should never actually print anything.
- if (LC->getCurrentStackFrame()->getParent() == 0)
+ if (LC->getCurrentStackFrame()->getParent() == nullptr)
return;
if (!BT)
diff --git a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 93bc12c..08ba26a 100644
--- a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -291,7 +291,7 @@
void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
CheckerContext &C) const {
- ProgramStateRef State = 0;
+ ProgramStateRef State = nullptr;
const FunctionDecl *FDecl = C.getCalleeDecl(CE);
if (!FDecl || FDecl->getKind() != Decl::Function)
return;
@@ -314,7 +314,7 @@
// Otherwise, check if we have custom pre-processing implemented.
FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
.Case("fscanf", &GenericTaintChecker::preFscanf)
- .Default(0);
+ .Default(nullptr);
// Check and evaluate the call.
if (evalFunction)
State = (this->*evalFunction)(CE, C);
@@ -388,11 +388,11 @@
.Case("getch", &GenericTaintChecker::postRetTaint)
.Case("wgetch", &GenericTaintChecker::postRetTaint)
.Case("socket", &GenericTaintChecker::postSocket)
- .Default(0);
+ .Default(nullptr);
// If the callee isn't defined, it is not of security concern.
// Check and evaluate the call.
- ProgramStateRef State = 0;
+ ProgramStateRef State = nullptr;
if (evalFunction)
State = (this->*evalFunction)(CE, C);
if (!State)
@@ -428,11 +428,11 @@
ProgramStateRef State = C.getState();
SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
if (AddrVal.isUnknownOrUndef())
- return 0;
+ return nullptr;
Optional<Loc> AddrLoc = AddrVal.getAs<Loc>();
if (!AddrLoc)
- return 0;
+ return nullptr;
const PointerType *ArgTy =
dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
@@ -526,7 +526,7 @@
return State;
}
- return 0;
+ return nullptr;
}
diff --git a/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp b/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
index fdd1fdc..1926600 100644
--- a/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
@@ -157,7 +157,7 @@
PropertySetterToIvarMap(InPropertySetterToIvarMap),
PropertyGetterToIvarMap(InPropertyGetterToIvarMap),
PropertyToIvarMap(InPropertyToIvarMap),
- InvalidationMethod(0),
+ InvalidationMethod(nullptr),
Ctx(InCtx) {}
void VisitStmt(const Stmt *S) { VisitChildren(S); }
@@ -306,7 +306,7 @@
const ObjCInterfaceDecl *InterfaceD,
IvarSet &TrackedIvars,
const ObjCIvarDecl **FirstIvarDecl) {
- const ObjCIvarDecl *IvarD = 0;
+ const ObjCIvarDecl *IvarD = nullptr;
// Lookup for the synthesized case.
IvarD = Prop->getPropertyIvarDecl();
@@ -343,7 +343,7 @@
// Note, this is a possible source of false positives. We could look at the
// getter implementation to find the ivar when its name is not derived from
// the property name.
- return 0;
+ return nullptr;
}
void IvarInvalidationCheckerImpl::printIvar(llvm::raw_svector_ostream &os,
@@ -367,7 +367,7 @@
// Record the first Ivar needing invalidation; used in reporting when only
// one ivar is sufficient. Cannot grab the first on the Ivars set to ensure
// deterministic output.
- const ObjCIvarDecl *FirstIvarDecl = 0;
+ const ObjCIvarDecl *FirstIvarDecl = nullptr;
const ObjCInterfaceDecl *InterfaceD = ImplD->getClassInterface();
// Collect ivars declared in this class, its extensions and its implementation
@@ -518,7 +518,7 @@
// invalidation methods.
for (IvarSet::const_iterator
I = Ivars.begin(), E = Ivars.end(); I != E; ++I)
- reportIvarNeedsInvalidation(I->first, IvarToPopertyMap, 0);
+ reportIvarNeedsInvalidation(I->first, IvarToPopertyMap, nullptr);
} else {
// Otherwise, no invalidation methods were implemented.
reportNoInvalidationMethod(Filter.checkName_InstanceVariableInvalidation,
@@ -717,7 +717,7 @@
if (Receiver) {
InvalidationMethod = MD;
check(Receiver->IgnoreParenCasts());
- InvalidationMethod = 0;
+ InvalidationMethod = nullptr;
}
VisitStmt(ME);
diff --git a/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
index 17ebf9e..0b7375a 100644
--- a/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
@@ -58,7 +58,7 @@
const TypedefNameDecl *TD = TT->getDecl();
- if (!InNamespace(TD, "std"))
+ if (!TD->isInStdNamespace())
return false;
return TD->getName() == "string";
diff --git a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index 4a293c4..0f227bb 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -224,7 +224,7 @@
if (sym)
return sym;
}
- return 0;
+ return nullptr;
}
// When checking for error code, we need to consider the following cases:
@@ -458,7 +458,7 @@
// If the argument entered as an enclosing function parameter, skip it to
// avoid false positives.
if (isEnclosingFunctionParam(ArgExpr) &&
- C.getLocationContext()->getParent() == 0)
+ C.getLocationContext()->getParent() == nullptr)
return;
if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C)) {
@@ -503,7 +503,7 @@
// symbol was tracked.
if (N->getLocationContext() == LeakContext)
AllocNode = N;
- N = N->pred_empty() ? NULL : *(N->pred_begin());
+ N = N->pred_empty() ? nullptr : *(N->pred_begin());
}
return AllocNode;
@@ -525,7 +525,7 @@
// allocated, and only report a single path.
PathDiagnosticLocation LocUsedForUniqueing;
const ExplodedNode *AllocNode = getAllocationNode(N, AP.first, C);
- const Stmt *AllocStmt = 0;
+ const Stmt *AllocStmt = nullptr;
ProgramPoint P = AllocNode->getLocation();
if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
AllocStmt = Exit->getCalleeContext()->getCallSite();
@@ -596,10 +596,10 @@
BugReport &BR) {
const AllocationState *AS = N->getState()->get<AllocatedData>(Sym);
if (!AS)
- return 0;
+ return nullptr;
const AllocationState *ASPrev = PrevN->getState()->get<AllocatedData>(Sym);
if (ASPrev)
- return 0;
+ return nullptr;
// (!ASPrev && AS) ~ We started tracking symbol in node N, it must be the
// allocation site.
diff --git a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
index d9e4699..13a401d 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -113,7 +113,7 @@
"_dispatch_once",
"dispatch_once_f",
&MacOSXAPIChecker::CheckDispatchOnce)
- .Default(NULL);
+ .Default(nullptr);
if (SC)
(this->*SC)(C, CE, Name);
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index f0d1924..a03fa25 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -157,9 +157,10 @@
eval::Assume>
{
public:
- MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0),
- II_valloc(0), II_reallocf(0), II_strndup(0), II_strdup(0),
- II_kmalloc(0) {}
+ MallocChecker()
+ : II_malloc(nullptr), II_free(nullptr), II_realloc(nullptr),
+ II_calloc(nullptr), II_valloc(nullptr), II_reallocf(nullptr),
+ II_strndup(nullptr), II_strdup(nullptr), II_kmalloc(nullptr) {}
/// In pessimistic mode, the checker assumes that it does not know which
/// functions might free the memory.
@@ -332,7 +333,7 @@
SymbolRef Sym, bool OwnershipTransferred) const;
void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
const Expr *DeallocExpr,
- const Expr *AllocExpr = 0) const;
+ const Expr *AllocExpr = nullptr) const;
void ReportUseAfterFree(CheckerContext &C, SourceRange Range,
SymbolRef Sym) const;
void ReportDoubleFree(CheckerContext &C, SourceRange Range, bool Released,
@@ -370,7 +371,7 @@
public:
MallocBugVisitor(SymbolRef S, bool isLeak = false)
- : Sym(S), Mode(Normal), FailedReallocSymbol(0), IsLeak(isLeak) {}
+ : Sym(S), Mode(Normal), FailedReallocSymbol(nullptr), IsLeak(isLeak) {}
virtual ~MallocBugVisitor() {}
@@ -422,7 +423,7 @@
const ExplodedNode *EndPathNode,
BugReport &BR) override {
if (!IsLeak)
- return 0;
+ return nullptr;
PathDiagnosticLocation L =
PathDiagnosticLocation::createEndOfPath(EndPathNode,
@@ -843,7 +844,7 @@
MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
const OwnershipAttr *Att) const {
if (Att->getModule() != II_malloc)
- return 0;
+ return nullptr;
OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
if (I != E) {
@@ -870,7 +871,7 @@
// We expect the malloc functions to return a pointer.
if (!RetVal.getAs<Loc>())
- return 0;
+ return nullptr;
// Fill the region with the initialization value.
State = State->bindDefault(RetVal, Init);
@@ -879,7 +880,7 @@
const SymbolicRegion *R =
dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion());
if (!R)
- return 0;
+ return nullptr;
if (Optional<DefinedOrUnknownSVal> DefinedSize =
Size.getAs<DefinedOrUnknownSVal>()) {
SValBuilder &svalBuilder = C.getSValBuilder();
@@ -903,7 +904,7 @@
// We expect the malloc functions to return a pointer.
if (!retVal.getAs<Loc>())
- return 0;
+ return nullptr;
SymbolRef Sym = retVal.getAsLocSymbol();
assert(Sym);
@@ -916,14 +917,13 @@
const CallExpr *CE,
const OwnershipAttr *Att) const {
if (Att->getModule() != II_malloc)
- return 0;
+ return nullptr;
ProgramStateRef State = C.getState();
bool ReleasedAllocated = false;
- for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
- I != E; ++I) {
- ProgramStateRef StateI = FreeMemAux(C, CE, State, *I,
+ for (const auto &Arg : Att->args()) {
+ ProgramStateRef StateI = FreeMemAux(C, CE, State, Arg,
Att->getOwnKind() == OwnershipAttr::Holds,
ReleasedAllocated);
if (StateI)
@@ -940,7 +940,7 @@
bool &ReleasedAllocated,
bool ReturnsNullOnFailure) const {
if (CE->getNumArgs() < (Num + 1))
- return 0;
+ return nullptr;
return FreeMemAux(C, CE->getArg(Num), CE, state, Hold,
ReleasedAllocated, ReturnsNullOnFailure);
@@ -1072,23 +1072,23 @@
SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext());
if (!ArgVal.getAs<DefinedOrUnknownSVal>())
- return 0;
+ return nullptr;
DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>();
// Check for null dereferences.
if (!location.getAs<Loc>())
- return 0;
+ return nullptr;
// The explicit NULL case, no operation is performed.
ProgramStateRef notNullState, nullState;
std::tie(notNullState, nullState) = State->assume(location);
if (nullState && !notNullState)
- return 0;
+ return nullptr;
// Unknown values could easily be okay
// Undefined values are handled elsewhere
if (ArgVal.isUnknownOrUndef())
- return 0;
+ return nullptr;
const MemRegion *R = ArgVal.getAsRegion();
@@ -1096,7 +1096,7 @@
// Non-region locations (labels and fixed addresses) also shouldn't be freed.
if (!R) {
ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
- return 0;
+ return nullptr;
}
R = R->StripCasts();
@@ -1104,7 +1104,7 @@
// Blocks might show up as heap data, but should not be free()d
if (isa<BlockDataRegion>(R)) {
ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
- return 0;
+ return nullptr;
}
const MemSpaceRegion *MS = R->getMemorySpace();
@@ -1121,18 +1121,18 @@
// False negatives are better than false positives.
ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
- return 0;
+ return nullptr;
}
const SymbolicRegion *SrBase = dyn_cast<SymbolicRegion>(R->getBaseRegion());
// Various cases could lead to non-symbol values here.
// For now, ignore them.
if (!SrBase)
- return 0;
+ return nullptr;
SymbolRef SymBase = SrBase->getSymbol();
const RefState *RsBase = State->get<RegionState>(SymBase);
- SymbolRef PreviousRetStatusSymbol = 0;
+ SymbolRef PreviousRetStatusSymbol = nullptr;
if (RsBase) {
@@ -1141,7 +1141,7 @@
!didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
SymBase, PreviousRetStatusSymbol);
- return 0;
+ return nullptr;
// If the pointer is allocated or escaped, but we are now trying to free it,
// check that the call to free is proper.
@@ -1153,7 +1153,7 @@
if (!DeallocMatchesAlloc) {
ReportMismatchedDealloc(C, ArgExpr->getSourceRange(),
ParentExpr, RsBase, SymBase, Hold);
- return 0;
+ return nullptr;
}
// Check if the memory location being freed is the actual location
@@ -1165,12 +1165,12 @@
const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
AllocExpr);
- return 0;
+ return nullptr;
}
}
}
- ReleasedAllocated = (RsBase != 0) && RsBase->isAllocated();
+ ReleasedAllocated = (RsBase != nullptr) && RsBase->isAllocated();
// Clean out the info on previous call to free return info.
State = State->remove<FreeReturnValue>(SymBase);
@@ -1277,8 +1277,8 @@
if (VR)
VD = VR->getDecl();
else
- VD = NULL;
-
+ VD = nullptr;
+
if (VD)
os << "the address of the local variable '" << VD->getName() << "'";
else
@@ -1292,8 +1292,8 @@
if (VR)
VD = VR->getDecl();
else
- VD = NULL;
-
+ VD = nullptr;
+
if (VD)
os << "the address of the parameter '" << VD->getName() << "'";
else
@@ -1307,8 +1307,8 @@
if (VR)
VD = VR->getDecl();
else
- VD = NULL;
-
+ VD = nullptr;
+
if (VD) {
if (VD->isStaticLocal())
os << "the address of the static variable '" << VD->getName() << "'";
@@ -1445,7 +1445,7 @@
return;
ExplodedNode *N = C.generateSink();
- if (N == NULL)
+ if (!N)
return;
if (!BT_OffsetFree[*CheckKind])
@@ -1574,14 +1574,14 @@
const CallExpr *CE,
bool FreesOnFail) const {
if (CE->getNumArgs() < 2)
- return 0;
+ return nullptr;
ProgramStateRef state = C.getState();
const Expr *arg0Expr = CE->getArg(0);
const LocationContext *LCtx = C.getLocationContext();
SVal Arg0Val = state->getSVal(arg0Expr, LCtx);
if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
- return 0;
+ return nullptr;
DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
SValBuilder &svalBuilder = C.getSValBuilder();
@@ -1592,12 +1592,12 @@
// Get the size argument. If there is no size arg then give up.
const Expr *Arg1 = CE->getArg(1);
if (!Arg1)
- return 0;
+ return nullptr;
// Get the value of the size argument.
SVal Arg1ValG = state->getSVal(Arg1, LCtx);
if (!Arg1ValG.getAs<DefinedOrUnknownSVal>())
- return 0;
+ return nullptr;
DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>();
// Compare the size argument to 0.
@@ -1623,7 +1623,7 @@
}
if (PrtIsNull && SizeIsZero)
- return 0;
+ return nullptr;
// Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
assert(!PrtIsNull);
@@ -1631,7 +1631,7 @@
SVal RetVal = state->getSVal(CE, LCtx);
SymbolRef ToPtr = RetVal.getAsSymbol();
if (!FromPtr || !ToPtr)
- return 0;
+ return nullptr;
bool ReleasedAllocated = false;
@@ -1653,7 +1653,7 @@
ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
UnknownVal(), stateFree);
if (!stateRealloc)
- return 0;
+ return nullptr;
ReallocPairKind Kind = RPToBeFreedAfterFailure;
if (FreesOnFail)
@@ -1669,12 +1669,12 @@
C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
return stateRealloc;
}
- return 0;
+ return nullptr;
}
ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){
if (CE->getNumArgs() < 2)
- return 0;
+ return nullptr;
ProgramStateRef state = C.getState();
SValBuilder &svalBuilder = C.getSValBuilder();
@@ -1695,7 +1695,7 @@
// Walk the ExplodedGraph backwards and find the first node that referred to
// the tracked symbol.
const ExplodedNode *AllocNode = N;
- const MemRegion *ReferenceRegion = 0;
+ const MemRegion *ReferenceRegion = nullptr;
while (N) {
ProgramStateRef State = N->getState();
@@ -1722,7 +1722,7 @@
// symbol was tracked.
if (N->getLocationContext() == LeakContext)
AllocNode = N;
- N = N->pred_empty() ? NULL : *(N->pred_begin());
+ N = N->pred_empty() ? nullptr : *(N->pred_begin());
}
return LeakInfo(AllocNode, ReferenceRegion);
@@ -1765,12 +1765,12 @@
// With leaks, we want to unique them by the location where they were
// allocated, and only report a single path.
PathDiagnosticLocation LocUsedForUniqueing;
- const ExplodedNode *AllocNode = 0;
- const MemRegion *Region = 0;
+ const ExplodedNode *AllocNode = nullptr;
+ const MemRegion *Region = nullptr;
std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
ProgramPoint P = AllocNode->getLocation();
- const Stmt *AllocationStmt = 0;
+ const Stmt *AllocationStmt = nullptr;
if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
AllocationStmt = Exit->getCalleeContext()->getCallSite();
else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
@@ -2040,8 +2040,8 @@
ProgramStateRef State,
SymbolRef &EscapingSymbol) const {
assert(Call);
- EscapingSymbol = 0;
-
+ EscapingSymbol = nullptr;
+
// For now, assume that any C++ or block call can free memory.
// TODO: If we want to be more optimistic here, we'll need to make sure that
// regions escape to C++ containers. They seem to do that even now, but for
@@ -2217,7 +2217,7 @@
bool(*CheckRefState)(const RefState*)) const {
// If we know that the call does not free memory, or we want to process the
// call later, keep tracking the top level arguments.
- SymbolRef EscapingSymbol = 0;
+ SymbolRef EscapingSymbol = nullptr;
if (Kind == PSK_DirectEscapeOnCall &&
!mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State,
EscapingSymbol) &&
@@ -2255,7 +2255,7 @@
return sym;
}
- return NULL;
+ return nullptr;
}
PathDiagnosticPiece *
@@ -2269,11 +2269,11 @@
const RefState *RS = state->get<RegionState>(Sym);
const RefState *RSPrev = statePrev->get<RegionState>(Sym);
if (!RS)
- return 0;
+ return nullptr;
- const Stmt *S = 0;
- const char *Msg = 0;
- StackHintGeneratorForSymbol *StackHint = 0;
+ const Stmt *S = nullptr;
+ const char *Msg = nullptr;
+ StackHintGeneratorForSymbol *StackHint = nullptr;
// Retrieve the associated statement.
ProgramPoint ProgLoc = N->getLocation();
@@ -2288,7 +2288,7 @@
}
if (!S)
- return 0;
+ return nullptr;
// FIXME: We will eventually need to handle non-statement-based events
// (__attribute__((cleanup))).
@@ -2331,13 +2331,13 @@
Msg = "Attempt to reallocate memory";
StackHint = new StackHintGeneratorForSymbol(Sym,
"Returned reallocated memory");
- FailedReallocSymbol = NULL;
+ FailedReallocSymbol = nullptr;
Mode = Normal;
}
}
if (!Msg)
- return 0;
+ return nullptr;
assert(StackHint);
// Generate the extra diagnostic.
diff --git a/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
index 8097727..f38ce77 100644
--- a/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
@@ -65,7 +65,7 @@
conditional expression, an operation that could reduce the range
of the result, or anything too complicated :-). */
const Expr * e = TheArgument;
- const BinaryOperator * mulop = NULL;
+ const BinaryOperator * mulop = nullptr;
for (;;) {
e = e->IgnoreParenImpCasts();
@@ -73,7 +73,7 @@
const BinaryOperator * binop = dyn_cast<BinaryOperator>(e);
BinaryOperatorKind opc = binop->getOpcode();
// TODO: ignore multiplications by 1, reject if multiplied by 0.
- if (mulop == NULL && opc == BO_Mul)
+ if (mulop == nullptr && opc == BO_Mul)
mulop = binop;
if (opc != BO_Mul && opc != BO_Add && opc != BO_Sub && opc != BO_Shl)
return;
@@ -94,7 +94,7 @@
return;
}
- if (mulop == NULL)
+ if (mulop == nullptr)
return;
// We've found the right structure of malloc argument, now save
diff --git a/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
index 5b068c8..4a50d93 100644
--- a/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
@@ -95,7 +95,7 @@
if (FD) {
IdentifierInfo *II = FD->getIdentifier();
if (II == II_malloc || II == II_calloc || II == II_realloc)
- return TypeCallPair((const TypeSourceInfo *)0, E);
+ return TypeCallPair((const TypeSourceInfo *)nullptr, E);
}
return TypeCallPair();
}
@@ -205,7 +205,7 @@
if (compatibleWithArrayType(BR.getContext(), PointeeType, SizeofType))
continue;
- const TypeSourceInfo *TSI = 0;
+ const TypeSourceInfo *TSI = nullptr;
if (i->CastedExprParent.is<const VarDecl *>()) {
TSI =
i->CastedExprParent.get<const VarDecl *>()->getTypeSourceInfo();
diff --git a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
index 5a505fc..2be7f1d 100644
--- a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -42,7 +42,7 @@
mutable IdentifierInfo *II;
public:
- NSErrorMethodChecker() : II(0) { }
+ NSErrorMethodChecker() : II(nullptr) {}
void checkASTDecl(const ObjCMethodDecl *D,
AnalysisManager &mgr, BugReporter &BR) const;
@@ -89,7 +89,7 @@
mutable IdentifierInfo *II;
public:
- CFErrorFunctionChecker() : II(0) { }
+ CFErrorFunctionChecker() : II(nullptr) {}
void checkASTDecl(const FunctionDecl *D,
AnalysisManager &mgr, BugReporter &BR) const;
@@ -153,9 +153,11 @@
: public Checker< check::Location,
check::Event<ImplicitNullDerefEvent> > {
mutable IdentifierInfo *NSErrorII, *CFErrorII;
+ mutable std::unique_ptr<NSErrorDerefBug> NSBT;
+ mutable std::unique_ptr<CFErrorDerefBug> CFBT;
public:
bool ShouldCheckNSError, ShouldCheckCFError;
- NSOrCFErrorDerefChecker() : NSErrorII(0), CFErrorII(0),
+ NSOrCFErrorDerefChecker() : NSErrorII(nullptr), CFErrorII(nullptr),
ShouldCheckNSError(0), ShouldCheckCFError(0) { }
void checkLocation(SVal loc, bool isLoad, const Stmt *S,
@@ -262,11 +264,17 @@
os << " may be null";
- BugType *bug = 0;
- if (isNSError)
- bug = new NSErrorDerefBug(this);
- else
- bug = new CFErrorDerefBug(this);
+ BugType *bug = nullptr;
+ if (isNSError) {
+ if (!NSBT)
+ NSBT.reset(new NSErrorDerefBug(this));
+ bug = NSBT.get();
+ }
+ else {
+ if (!CFBT)
+ CFBT.reset(new CFErrorDerefBug(this));
+ bug = CFBT.get();
+ }
BugReport *report = new BugReport(*bug, os.str(), event.SinkNode);
BR.emitReport(report);
}
diff --git a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
index 0e9cbba..ba82d1d 100644
--- a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "SelectorExtras.h"
#include "clang/AST/Attr.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -28,6 +29,8 @@
class NoReturnFunctionChecker : public Checker< check::PostCall,
check::PostObjCMessage > {
+ mutable Selector HandleFailureInFunctionSel;
+ mutable Selector HandleFailureInMethodSel;
public:
void checkPostCall(const CallEvent &CE, CheckerContext &C) const;
void checkPostObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
@@ -81,24 +84,6 @@
C.generateSink();
}
-static bool END_WITH_NULL isMultiArgSelector(const Selector *Sel, ...) {
- va_list argp;
- va_start(argp, Sel);
-
- unsigned Slot = 0;
- const char *Arg;
- while ((Arg = va_arg(argp, const char *))) {
- if (!Sel->getNameForSlot(Slot).equals(Arg))
- break; // still need to va_end!
- ++Slot;
- }
-
- va_end(argp);
-
- // We only succeeded if we made it to the end of the argument list.
- return (Arg == NULL);
-}
-
void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
CheckerContext &C) const {
// Check if the method is annotated with analyzer_noreturn.
@@ -135,13 +120,17 @@
default:
return;
case 4:
- if (!isMultiArgSelector(&Sel, "handleFailureInFunction", "file",
- "lineNumber", "description", NULL))
+ lazyInitKeywordSelector(HandleFailureInFunctionSel, C.getASTContext(),
+ "handleFailureInFunction", "file", "lineNumber",
+ "description", nullptr);
+ if (Sel != HandleFailureInFunctionSel)
return;
break;
case 5:
- if (!isMultiArgSelector(&Sel, "handleFailureInMethod", "object", "file",
- "lineNumber", "description", NULL))
+ lazyInitKeywordSelector(HandleFailureInMethodSel, C.getASTContext(),
+ "handleFailureInMethod", "object", "file",
+ "lineNumber", "description", nullptr);
+ if (Sel != HandleFailureInMethodSel)
return;
break;
}
diff --git a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 293114f..61d2b87 100644
--- a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -130,7 +130,7 @@
// we cache out.
if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
- BugReport *R = 0;
+ BugReport *R = nullptr;
if (haveAttrNonNull)
R = genReportNullAttrNonNull(errorNode, ArgE);
else if (haveRefTypeParam)
@@ -186,7 +186,7 @@
ErrorNode);
if (ArgE) {
const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
- if (ArgEDeref == 0)
+ if (!ArgEDeref)
ArgEDeref = ArgE;
bugreporter::trackNullOrUndefValue(ErrorNode,
ArgEDeref,
diff --git a/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
index 239860d..e3fc611 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
@@ -100,7 +100,7 @@
if (Name.empty())
return;
- const Expr *Arg = 0;
+ const Expr *Arg = nullptr;
unsigned ArgNum;
if (Name.equals("CFArrayCreate") || Name.equals("CFSetCreate")) {
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 6c33084..51bc7e6 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -62,7 +62,13 @@
check::PostCall,
check::Location,
check::Bind > {
+ mutable std::unique_ptr<BugType> BT;
+
+ void checkForInvalidSelf(const Expr *E, CheckerContext &C,
+ const char *errorStr) const;
+
public:
+ ObjCSelfInitChecker() {}
void checkPostObjCMessage(const ObjCMethodCall &Msg, CheckerContext &C) const;
void checkPostStmt(const ObjCIvarRefExpr *E, CheckerContext &C) const;
void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
@@ -79,17 +85,6 @@
} // end anonymous namespace
namespace {
-
-class InitSelfBug : public BugType {
-public:
- InitSelfBug(const CheckerBase *Checker)
- : BugType(Checker, "Missing \"self = [(super or self) init...]\"",
- categories::CoreFoundationObjectiveC) {}
-};
-
-} // end anonymous namespace
-
-namespace {
enum SelfFlagEnum {
/// \brief No flag set.
SelfFlag_None = 0x0,
@@ -146,9 +141,8 @@
return true;
}
-static void checkForInvalidSelf(const Expr *E, CheckerContext &C,
- const char *errorStr,
- const CheckerBase *Checker) {
+void ObjCSelfInitChecker::checkForInvalidSelf(const Expr *E, CheckerContext &C,
+ const char *errorStr) const {
if (!E)
return;
@@ -163,7 +157,10 @@
if (!N)
return;
- BugReport *report = new BugReport(*new InitSelfBug(Checker), errorStr, N);
+ if (!BT)
+ BT.reset(new BugType(this, "Missing \"self = [(super or self) init...]\"",
+ categories::CoreFoundationObjectiveC));
+ BugReport *report = new BugReport(*BT, errorStr, N);
C.emitReport(report);
}
@@ -208,8 +205,7 @@
checkForInvalidSelf(
E->getBase(), C,
"Instance variable used while 'self' is not set to the result of "
- "'[(super or self) init...]'",
- this);
+ "'[(super or self) init...]'");
}
void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S,
@@ -221,8 +217,7 @@
checkForInvalidSelf(S->getRetValue(), C,
"Returning 'self' while it is not set to the result of "
- "'[(super or self) init...]'",
- this);
+ "'[(super or self) init...]'");
}
// When a call receives a reference to 'self', [Pre/Post]Call pass
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 9ac9931..0c130fe 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -14,6 +14,7 @@
#include "ClangSACheckers.h"
#include "AllocationDiagnostics.h"
+#include "SelectorExtras.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -450,10 +451,10 @@
: II(ii), S(s) {}
ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
- : II(d ? d->getIdentifier() : 0), S(s) {}
+ : II(d ? d->getIdentifier() : nullptr), S(s) {}
ObjCSummaryKey(Selector s)
- : II(0), S(s) {}
+ : II(nullptr), S(s) {}
IdentifierInfo *getIdentifier() const { return II; }
Selector getSelector() const { return S; }
@@ -502,7 +503,7 @@
if (I != M.end())
return I->second;
if (!D)
- return NULL;
+ return nullptr;
// Walk the super chain. If we find a hit with a parent, we'll end
// up returning that summary. We actually allow that key (null,S), as
@@ -515,7 +516,7 @@
break;
if (!C)
- return NULL;
+ return nullptr;
}
// Cache the summary with original key to make the next lookup faster
@@ -533,7 +534,7 @@
if (I == M.end())
I = M.find(ObjCSummaryKey(S));
- return I == M.end() ? NULL : I->second;
+ return I == M.end() ? nullptr : I->second;
}
const RetainSummary *& operator[](ObjCSummaryKey K) {
@@ -675,18 +676,9 @@
ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
}
- Selector generateSelector(va_list argp) {
- SmallVector<IdentifierInfo*, 10> II;
-
- while (const char* s = va_arg(argp, const char*))
- II.push_back(&Ctx.Idents.get(s));
-
- return Ctx.Selectors.getSelector(II.size(), &II[0]);
- }
-
- void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries,
- const RetainSummary * Summ, va_list argp) {
- Selector S = generateSelector(argp);
+ void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
+ const RetainSummary *Summ, va_list argp) {
+ Selector S = getKeywordSelector(Ctx, argp);
Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
}
@@ -731,7 +723,7 @@
}
const RetainSummary *getSummary(const CallEvent &Call,
- ProgramStateRef State = 0);
+ ProgramStateRef State = nullptr);
const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
@@ -1014,7 +1006,7 @@
return I->second;
// No summary? Generate one.
- const RetainSummary *S = 0;
+ const RetainSummary *S = nullptr;
bool AllowAnnotations = true;
do {
@@ -1455,7 +1447,7 @@
const RetainSummary *
RetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg,
ProgramStateRef State) {
- const ObjCInterfaceDecl *ReceiverClass = 0;
+ const ObjCInterfaceDecl *ReceiverClass = nullptr;
// We do better tracking of the type of the object than the core ExprEngine.
// See if we have its type in our private state.
@@ -1796,7 +1788,7 @@
void CFRefReport::addGCModeDescription(const LangOptions &LOpts,
bool GCEnabled) {
- const char *GCModeDescription = 0;
+ const char *GCModeDescription = nullptr;
switch (LOpts.getGC()) {
case LangOptions::GCOnly:
@@ -1843,7 +1835,7 @@
// FIXME: We will eventually need to handle non-statement-based events
// (__attribute__((cleanup))).
if (!N->getLocation().getAs<StmtPoint>())
- return NULL;
+ return nullptr;
// Check if the type state has changed.
ProgramStateRef PrevSt = PrevN->getState();
@@ -1851,7 +1843,7 @@
const LocationContext *LCtx = N->getLocationContext();
const RefVal* CurrT = getRefBinding(CurrSt, Sym);
- if (!CurrT) return NULL;
+ if (!CurrT) return nullptr;
const RefVal &CurrV = *CurrT;
const RefVal *PrevT = getRefBinding(PrevSt, Sym);
@@ -1876,7 +1868,7 @@
if (isNumericLiteralExpression(BL->getSubExpr()))
os << "NSNumber literal is an object with a +0 retain count";
else {
- const ObjCInterfaceDecl *BoxClass = 0;
+ const ObjCInterfaceDecl *BoxClass = nullptr;
if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
BoxClass = Method->getClassInterface();
@@ -2045,7 +2037,7 @@
if (PrevV.getCount() == CurrV.getCount()) {
// Did an autorelease message get sent?
if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
- return 0;
+ return nullptr;
assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
os << "Object autoreleased";
@@ -2075,7 +2067,7 @@
case RefVal::ReturnedOwned:
// Autoreleases can be applied after marking a node ReturnedOwned.
if (CurrV.getAutoreleaseCount())
- return NULL;
+ return nullptr;
os << "Object returned to caller as an owning reference (single "
"retain count transferred to caller)";
@@ -2086,7 +2078,7 @@
break;
default:
- return NULL;
+ return nullptr;
}
// Emit any remaining diagnostics for the argument effects (if any).
@@ -2111,7 +2103,7 @@
} while (0);
if (os.str().empty())
- return 0; // We have nothing to say!
+ return nullptr; // We have nothing to say!
const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
@@ -2151,12 +2143,12 @@
SymbolRef Sym) {
const ExplodedNode *AllocationNode = N;
const ExplodedNode *AllocationNodeInCurrentContext = N;
- const MemRegion* FirstBinding = 0;
+ const MemRegion *FirstBinding = nullptr;
const LocationContext *LeakContext = N->getLocationContext();
// The location context of the init method called on the leaked object, if
// available.
- const LocationContext *InitMethodContext = 0;
+ const LocationContext *InitMethodContext = nullptr;
while (N) {
ProgramStateRef St = N->getState();
@@ -2200,12 +2192,12 @@
}
}
- N = N->pred_empty() ? NULL : *(N->pred_begin());
+ N = N->pred_empty() ? nullptr : *(N->pred_begin());
}
// If we are reporting a leak of the object that was allocated with alloc,
// mark its init method as interesting.
- const LocationContext *InterestingMethodContext = 0;
+ const LocationContext *InterestingMethodContext = nullptr;
if (InitMethodContext) {
const ProgramPoint AllocPP = AllocationNode->getLocation();
if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
@@ -2218,7 +2210,7 @@
// do not report the binding.
assert(N && "Could not find allocation node");
if (N->getLocationContext() != LeakContext) {
- FirstBinding = 0;
+ FirstBinding = nullptr;
}
return AllocationInfo(AllocationNodeInCurrentContext,
@@ -2335,7 +2327,7 @@
// Note that this is *not* the trimmed graph; we are guaranteed, however,
// that all ancestor nodes that represent the allocation site have the
// same SourceLocation.
- const ExplodedNode *AllocNode = 0;
+ const ExplodedNode *AllocNode = nullptr;
const SourceManager& SMgr = Ctx.getSourceManager();
@@ -2610,7 +2602,7 @@
ExplodedNode *processLeaks(ProgramStateRef state,
SmallVectorImpl<SymbolRef> &Leaked,
CheckerContext &Ctx,
- ExplodedNode *Pred = 0) const;
+ ExplodedNode *Pred = nullptr) const;
};
} // end anonymous namespace
@@ -2894,7 +2886,7 @@
// Evaluate the effect of the arguments.
RefVal::Kind hasErr = (RefVal::Kind) 0;
SourceRange ErrorRange;
- SymbolRef ErrorSym = 0;
+ SymbolRef ErrorSym = nullptr;
for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
SVal V = CallOrMsg.getArgSVal(idx);
@@ -3250,7 +3242,7 @@
if (RetVal.isUnknown()) {
// If the receiver is unknown, conjure a return value.
SValBuilder &SVB = C.getSValBuilder();
- RetVal = SVB.conjureSymbolVal(0, CE, LCtx, ResultTy, C.blockCount());
+ RetVal = SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
}
state = state->BindExpr(CE, LCtx, RetVal, false);
@@ -3259,7 +3251,7 @@
if (const MemRegion *ArgRegion = RetVal.getAsRegion()) {
// Save the refcount status of the argument.
SymbolRef Sym = RetVal.getAsLocSymbol();
- const RefVal *Binding = 0;
+ const RefVal *Binding = nullptr;
if (Sym)
Binding = getRefBinding(state, Sym);
@@ -3630,7 +3622,7 @@
Ctx.emitReport(report);
}
- return 0;
+ return nullptr;
}
ProgramStateRef
@@ -3691,7 +3683,7 @@
}
for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- state = handleAutoreleaseCounts(state, Pred, /*Tag=*/0, Ctx,
+ state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
I->first, I->second);
if (!state)
return;
diff --git a/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
index b4d92d6..6622313 100644
--- a/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -79,7 +79,7 @@
}
static void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
- const Expr *TrackingE = 0) {
+ const Expr *TrackingE = nullptr) {
ExplodedNode *N = C.generateSink();
if (!N)
return;
diff --git a/lib/StaticAnalyzer/Checkers/SelectorExtras.h b/lib/StaticAnalyzer/Checkers/SelectorExtras.h
new file mode 100644
index 0000000..48d96eb
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/SelectorExtras.h
@@ -0,0 +1,68 @@
+//=== SelectorExtras.h - Helpers for checkers using selectors -----*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CHECKERS_SELECTOREXTRAS
+#define LLVM_CLANG_SA_CHECKERS_SELECTOREXTRAS
+
+#include "clang/AST/ASTContext.h"
+#include <cstdarg>
+
+namespace clang {
+namespace ento {
+
+static inline Selector getKeywordSelectorImpl(ASTContext &Ctx,
+ const char *First,
+ va_list argp) {
+ SmallVector<IdentifierInfo*, 10> II;
+ II.push_back(&Ctx.Idents.get(First));
+
+ while (const char *s = va_arg(argp, const char *))
+ II.push_back(&Ctx.Idents.get(s));
+
+ return Ctx.Selectors.getSelector(II.size(), &II[0]);
+}
+
+static inline Selector getKeywordSelector(ASTContext &Ctx, va_list argp) {
+ const char *First = va_arg(argp, const char *);
+ assert(First && "keyword selectors must have at least one argument");
+ return getKeywordSelectorImpl(Ctx, First, argp);
+}
+
+END_WITH_NULL
+static inline Selector getKeywordSelector(ASTContext &Ctx,
+ const char *First, ...) {
+ va_list argp;
+ va_start(argp, First);
+ Selector result = getKeywordSelectorImpl(Ctx, First, argp);
+ va_end(argp);
+ return result;
+}
+
+END_WITH_NULL
+static inline void lazyInitKeywordSelector(Selector &Sel, ASTContext &Ctx,
+ const char *First, ...) {
+ if (!Sel.isNull())
+ return;
+ va_list argp;
+ va_start(argp, First);
+ Sel = getKeywordSelectorImpl(Ctx, First, argp);
+ va_end(argp);
+}
+
+static inline void lazyInitNullarySelector(Selector &Sel, ASTContext &Ctx,
+ const char *Name) {
+ if (!Sel.isNull())
+ return;
+ Sel = GetNullarySelector(Name, Ctx);
+}
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp b/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
index 83b15ec..3e9b57b 100644
--- a/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
@@ -106,8 +106,8 @@
};
} // end anonymous namespace
-
-SimpleStreamChecker::SimpleStreamChecker() : IIfopen(0), IIfclose(0) {
+SimpleStreamChecker::SimpleStreamChecker()
+ : IIfopen(nullptr), IIfclose(nullptr) {
// Initialize the bug types.
DoubleCloseBugType.reset(
new BugType(this, "Double fclose", "Unix Stream API Error"));
diff --git a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 6000942..894765a 100644
--- a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -67,9 +67,11 @@
public:
StreamChecker()
- : II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0),
- II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0),
- II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0) {}
+ : II_fopen(nullptr), II_tmpfile(nullptr), II_fclose(nullptr),
+ II_fread(nullptr), II_fwrite(nullptr), II_fseek(nullptr),
+ II_ftell(nullptr), II_rewind(nullptr), II_fgetpos(nullptr),
+ II_fsetpos(nullptr), II_clearerr(nullptr), II_feof(nullptr),
+ II_ferror(nullptr), II_fileno(nullptr) {}
bool evalCall(const CallExpr *CE, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
@@ -210,7 +212,8 @@
ProgramStateRef state = C.getState();
SValBuilder &svalBuilder = C.getSValBuilder();
const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
- DefinedSVal RetVal = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount())
+ DefinedSVal RetVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx,
+ C.blockCount())
.castAs<DefinedSVal>();
state = state->BindExpr(CE, C.getLocationContext(), RetVal);
@@ -340,7 +343,7 @@
CheckerContext &C) const {
Optional<DefinedSVal> DV = SV.getAs<DefinedSVal>();
if (!DV)
- return 0;
+ return nullptr;
ConstraintManager &CM = C.getConstraintManager();
ProgramStateRef stateNotNull, stateNull;
@@ -354,7 +357,7 @@
BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
C.emitReport(R);
}
- return 0;
+ return nullptr;
}
return stateNotNull;
}
@@ -386,7 +389,7 @@
BT_doubleclose->getDescription(), N);
C.emitReport(R);
}
- return NULL;
+ return nullptr;
}
// Close the File Descriptor.
diff --git a/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp b/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
index 57c9ed4..d02d2df 100644
--- a/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
@@ -72,7 +72,7 @@
void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
unsigned Indentation = 0;
for (const LocationContext *LC = C.getLocationContext()->getParent();
- LC != 0; LC = LC->getParent())
+ LC != nullptr; LC = LC->getParent())
++Indentation;
// It is mildly evil to print directly to llvm::outs() rather than emitting
@@ -89,7 +89,7 @@
unsigned Indentation = 0;
for (const LocationContext *LC = C.getLocationContext()->getParent();
- LC != 0; LC = LC->getParent())
+ LC != nullptr; LC = LC->getParent())
++Indentation;
// It is mildly evil to print directly to llvm::outs() rather than emitting
diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index 22e2155..fc49a46 100644
--- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -35,7 +35,7 @@
const Expr *FindExpr(const Expr *Ex) {
if (!MatchesCriteria(Ex))
- return 0;
+ return nullptr;
for (Stmt::const_child_iterator I = Ex->child_begin(),
E = Ex->child_end();I!=E;++I)
diff --git a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 93fe7d4..93687db 100644
--- a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -48,7 +48,7 @@
return BR;
}
- return NULL;
+ return nullptr;
}
void
diff --git a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index 00fd971..f3f4dce 100644
--- a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -60,7 +60,7 @@
SmallString<256> sbuf;
llvm::raw_svector_ostream OS(sbuf);
- const Expr *Ex = NULL;
+ const Expr *Ex = nullptr;
bool isLeft = true;
if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
diff --git a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index 30775d5..bd4493d 100644
--- a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -57,7 +57,7 @@
BT.reset(new BuiltinBug(this, str));
// Generate a report for this bug.
- const Expr *ex = 0;
+ const Expr *ex = nullptr;
while (StoreE) {
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index aa7e25bc..4887d80 100644
--- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -239,7 +239,7 @@
// Check if the allocation size is 0.
ProgramStateRef state = C.getState();
- ProgramStateRef trueState = NULL, falseState = NULL;
+ ProgramStateRef trueState = nullptr, falseState = nullptr;
const Expr *arg = CE->getArg(sizeArg);
SVal argVal = state->getSVal(arg, C.getLocationContext());
@@ -264,7 +264,7 @@
return;
ProgramStateRef state = C.getState();
- ProgramStateRef trueState = NULL, falseState = NULL;
+ ProgramStateRef trueState = nullptr, falseState = nullptr;
unsigned int i;
for (i = 0; i < nArgs; i++) {
@@ -343,7 +343,7 @@
.Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
.Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
.Case("valloc", &UnixAPIChecker::CheckVallocZero)
- .Default(NULL);
+ .Default(nullptr);
if (SC)
(this->*SC)(C, CE);
diff --git a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index 66c1acd..d78de3c 100644
--- a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -58,10 +58,10 @@
if (Eng.hasWorkRemaining())
return;
- const Decl *D = 0;
- CFG *C = 0;
- ParentMap *PM = 0;
- const LocationContext *LC = 0;
+ const Decl *D = nullptr;
+ CFG *C = nullptr;
+ ParentMap *PM = nullptr;
+ const LocationContext *LC = nullptr;
// Iterate over ExplodedGraph
for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
I != E; ++I) {
@@ -201,7 +201,7 @@
if (const Stmt *S = CB->getTerminator())
return S;
else
- return 0;
+ return nullptr;
}
// Determines if the path to this CFGBlock contained an element that infers this
@@ -245,7 +245,7 @@
// Returns true if the given CFGBlock is empty
bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
- return CB->getLabel() == 0 // No labels
+ return CB->getLabel() == nullptr // No labels
&& CB->size() == 0 // No statements
&& !CB->getTerminator(); // No terminator
}
diff --git a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index c7b2024..198a628 100644
--- a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -106,7 +106,7 @@
// Check if the size is tainted.
if (state->isTainted(sizeV)) {
- reportBug(VLA_Tainted, SE, 0, C);
+ reportBug(VLA_Tainted, SE, nullptr, C);
return;
}
diff --git a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index 9b5c852..f8f5cf9 100644
--- a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -61,7 +61,7 @@
public:
WalkAST(const CheckerBase *checker, BugReporter &br,
AnalysisDeclContext *ac)
- : Checker(checker), BR(br), AC(ac), visitingCallExpr(0) {}
+ : Checker(checker), BR(br), AC(ac), visitingCallExpr(nullptr) {}
bool hasWork() const { return !WList.empty(); }
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 1bea96e..38aac28 100644
--- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -39,7 +39,7 @@
// Use the User Mode to set the default IPA value.
// Note, we have to add the string to the Config map for the ConfigDumper
// checker to function properly.
- const char *DefaultIPA = 0;
+ const char *DefaultIPA = nullptr;
UserModeKind HighLevelMode = getUserMode();
if (HighLevelMode == UMK_Shallow)
DefaultIPA = "inlining";
diff --git a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index 8f93cee..0e90566 100644
--- a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -173,12 +173,12 @@
// FIXME: Expand these checks to include all undefined behavior.
if (V2.isSigned() && V2.isNegative())
- return NULL;
+ return nullptr;
uint64_t Amt = V2.getZExtValue();
if (Amt >= V1.getBitWidth())
- return NULL;
+ return nullptr;
return &getValue( V1.operator<<( (unsigned) Amt ));
}
@@ -191,12 +191,12 @@
// FIXME: Expand these checks to include all undefined behavior.
if (V2.isSigned() && V2.isNegative())
- return NULL;
+ return nullptr;
uint64_t Amt = V2.getZExtValue();
if (Amt >= V1.getBitWidth())
- return NULL;
+ return nullptr;
return &getValue( V1.operator>>( (unsigned) Amt ));
}
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index a08a226..6c7cb23 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -12,8 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "BugReporter"
-
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -40,6 +38,8 @@
using namespace clang;
using namespace ento;
+#define DEBUG_TYPE "BugReporter"
+
STATISTIC(MaxBugClassSize,
"The maximum number of bug reports in the same equivalence class");
STATISTIC(MaxValidBugClassSize,
@@ -59,7 +59,7 @@
if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
return S;
- return 0;
+ return nullptr;
}
static inline const Stmt*
@@ -83,15 +83,15 @@
const void *tagLesser = TrackConstraintBRVisitor::getTag();
if (X->getLocation() != Y->getLocation())
- return 0;
-
+ return nullptr;
+
if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
return X;
if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
return Y;
-
- return 0;
+
+ return nullptr;
}
/// An optimization pass over PathPieces that removes redundant diagnostics
@@ -214,8 +214,9 @@
/// Recursively scan through a path and make sure that all call pieces have
/// valid locations.
-static void adjustCallLocations(PathPieces &Pieces,
- PathDiagnosticLocation *LastCallLocation = 0) {
+static void
+adjustCallLocations(PathPieces &Pieces,
+ PathDiagnosticLocation *LastCallLocation = nullptr) {
for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I);
@@ -405,7 +406,7 @@
const Stmt *Parent = PM.getParentIgnoreParens(S);
if (!Parent)
- return 0;
+ return nullptr;
switch (Parent->getStmtClass()) {
case Stmt::ForStmtClass:
@@ -418,7 +419,7 @@
break;
}
- return 0;
+ return nullptr;
}
static PathDiagnosticLocation
@@ -564,7 +565,7 @@
SourceManager& SMgr = PDB.getSourceManager();
const LocationContext *LC = PDB.LC;
const ExplodedNode *NextNode = N->pred_empty()
- ? NULL : *(N->pred_begin());
+ ? nullptr : *(N->pred_begin());
StackDiagVector CallStack;
@@ -1351,11 +1352,11 @@
}
N = N->getFirstPred();
}
- return 0;
+ return nullptr;
}
static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
- const Stmt *LoopBody = 0;
+ const Stmt *LoopBody = nullptr;
switch (Term->getStmtClass()) {
case Stmt::CXXForRangeStmtClass: {
const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term);
@@ -1401,7 +1402,7 @@
StackDiagVector CallStack;
InterestingExprs IE;
- const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
+ const ExplodedNode *NextNode = N->pred_empty() ? nullptr : *(N->pred_begin());
while (NextNode) {
N = NextNode;
NextNode = N->getFirstPred();
@@ -1498,7 +1499,7 @@
// Are we jumping to the head of a loop? Add a special diagnostic.
if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
PathDiagnosticLocation L(Loop, SM, PDB.LC);
- const CompoundStmt *CS = NULL;
+ const CompoundStmt *CS = nullptr;
if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
CS = dyn_cast<CompoundStmt>(FS->getBody());
@@ -1683,11 +1684,11 @@
// reset the mapping from active to location context.
assert(PD.getActivePath().size() == 1 &&
PD.getActivePath().front() == C);
- LCM[&PD.getActivePath()] = 0;
+ LCM[&PD.getActivePath()] = nullptr;
// Record the location context mapping for the path within
// the call.
- assert(LCM[&C->path] == 0 ||
+ assert(LCM[&C->path] == nullptr ||
LCM[&C->path] == CE->getCalleeContext());
LCM[&C->path] = CE->getCalleeContext();
@@ -1786,7 +1787,7 @@
// Are we jumping to the head of a loop? Add a special diagnostic.
if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
PathDiagnosticLocation L(Loop, SM, PDB.LC);
- const Stmt *Body = NULL;
+ const Stmt *Body = nullptr;
if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
Body = FS->getBody();
@@ -1827,7 +1828,7 @@
bool IsInLoopBody =
isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term);
- const char *str = 0;
+ const char *str = nullptr;
if (isJumpToFalseBranch(&*BE)) {
if (!IsInLoopBody) {
@@ -1890,13 +1891,13 @@
static const Stmt *getLocStmt(PathDiagnosticLocation L) {
if (!L.isValid())
- return 0;
+ return nullptr;
return L.asStmt();
}
static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
if (!S)
- return 0;
+ return nullptr;
while (true) {
S = PM.getParentIgnoreParens(S);
@@ -1988,7 +1989,7 @@
SmallVector<PathDiagnosticLocation, 4> SrcContexts;
PathDiagnosticLocation NextSrcContext = SrcLoc;
- const Stmt *InnerStmt = 0;
+ const Stmt *InnerStmt = nullptr;
while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {
SrcContexts.push_back(NextSrcContext);
InnerStmt = NextSrcContext.asStmt();
@@ -2073,7 +2074,7 @@
if (NextI == E)
break;
- PathDiagnosticControlFlowPiece *PieceNextI = 0;
+ PathDiagnosticControlFlowPiece *PieceNextI = nullptr;
while (true) {
if (NextI == E)
@@ -2579,8 +2580,8 @@
const ExplodedNode *N = getErrorNode();
if (!N)
- return 0;
-
+ return nullptr;
+
const LocationContext *LC = N->getLocationContext();
return LC->getCurrentStackFrame()->getDecl();
}
@@ -2703,10 +2704,10 @@
const Stmt *BugReport::getStmt() const {
if (!ErrorNode)
- return 0;
+ return nullptr;
ProgramPoint ProgP = ErrorNode->getLocation();
- const Stmt *S = NULL;
+ const Stmt *S = nullptr;
if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) {
CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
@@ -2943,7 +2944,7 @@
// Now walk from the error node up the BFS path, always taking the
// predeccessor with the lowest number.
- ExplodedNode *Succ = 0;
+ ExplodedNode *Succ = nullptr;
while (true) {
// Create the equivalent node in the new graph with the same state
// and location.
@@ -3091,7 +3092,7 @@
} else {
// Keep the errorNodes list in sync with the bugReports list.
HasInvalid = true;
- errorNodes.push_back(0);
+ errorNodes.push_back(nullptr);
}
}
@@ -3149,21 +3150,21 @@
// Generate the very last diagnostic piece - the piece is visible before
// the trace is expanded.
- PathDiagnosticPiece *LastPiece = 0;
+ std::unique_ptr<PathDiagnosticPiece> LastPiece;
for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end();
I != E; ++I) {
if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) {
assert (!LastPiece &&
"There can only be one final piece in a diagnostic.");
- LastPiece = Piece;
+ LastPiece.reset(Piece);
}
}
if (ActiveScheme != PathDiagnosticConsumer::None) {
if (!LastPiece)
- LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
+ LastPiece.reset(BugReporterVisitor::getDefaultEndPath(PDB, N, *R));
assert(LastPiece);
- PD.setEndOfPath(LastPiece);
+ PD.setEndOfPath(LastPiece.release());
}
// Make sure we get a clean location context map so we don't
@@ -3328,7 +3329,7 @@
// DFS traversal of the ExplodedGraph to find a non-sink node. We could write
// this as a recursive function, but we don't want to risk blowing out the
// stack for very long paths.
- BugReport *exampleReport = 0;
+ BugReport *exampleReport = nullptr;
for (; I != E; ++I) {
const ExplodedNode *errorNode = I->getErrorNode();
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index ffc6ee5..b415d5b 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -45,7 +45,7 @@
// a[0], p->f, *p
const Expr *E = dyn_cast<Expr>(S);
if (!E)
- return 0;
+ return nullptr;
E = E->IgnoreParenCasts();
while (true) {
@@ -79,21 +79,21 @@
break;
}
- return NULL;
+ return nullptr;
}
const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
return BE->getRHS();
- return NULL;
+ return nullptr;
}
const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
return RS->getRetValue();
- return NULL;
+ return nullptr;
}
//===----------------------------------------------------------------------===//
@@ -104,7 +104,7 @@
BugReporterVisitor::getEndPath(BugReporterContext &BRC,
const ExplodedNode *EndPathNode,
BugReport &BR) {
- return 0;
+ return nullptr;
}
PathDiagnosticPiece*
@@ -237,22 +237,22 @@
BugReport &BR) {
// Only print a message at the interesting return statement.
if (N->getLocationContext() != StackFrame)
- return 0;
+ return nullptr;
Optional<StmtPoint> SP = N->getLocationAs<StmtPoint>();
if (!SP)
- return 0;
+ return nullptr;
const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
if (!Ret)
- return 0;
+ return nullptr;
// Okay, we're at the right return statement, but do we have the return
// value available?
ProgramStateRef State = N->getState();
SVal V = State->getSVal(Ret, StackFrame);
if (V.isUnknownOrUndef())
- return 0;
+ return nullptr;
// Don't print any more notes after this one.
Mode = Satisfied;
@@ -273,7 +273,7 @@
// Ignore aggregate rvalues.
if (V.getAs<nonloc::LazyCompoundVal>() ||
V.getAs<nonloc::CompoundVal>())
- return 0;
+ return nullptr;
RetE = RetE->IgnoreParenCasts();
@@ -283,7 +283,7 @@
BR.markInteresting(V);
ReturnVisitor::addVisitorIfNecessary(N, RetE, BR,
EnableNullFPSuppression);
- return 0;
+ return nullptr;
}
// If we're returning 0, we should track where that 0 came from.
@@ -343,10 +343,10 @@
// Are we at the entry node for this call?
Optional<CallEnter> CE = N->getLocationAs<CallEnter>();
if (!CE)
- return 0;
+ return nullptr;
if (CE->getCalleeContext() != StackFrame)
- return 0;
+ return nullptr;
Mode = Satisfied;
@@ -380,7 +380,7 @@
// (We will still look at the other arguments, though.)
}
- return 0;
+ return nullptr;
}
PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
@@ -393,7 +393,7 @@
case MaybeUnsuppress:
return visitNodeMaybeUnsuppress(N, PrevN, BRC, BR);
case Satisfied:
- return 0;
+ return nullptr;
}
llvm_unreachable("Invalid visit mode!");
@@ -404,7 +404,7 @@
BugReport &BR) override {
if (EnableNullFPSuppression)
BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
- return 0;
+ return nullptr;
}
};
} // end anonymous namespace
@@ -453,10 +453,10 @@
BugReport &BR) {
if (Satisfied)
- return NULL;
+ return nullptr;
- const ExplodedNode *StoreSite = 0;
- const Expr *InitE = 0;
+ const ExplodedNode *StoreSite = nullptr;
+ const Expr *InitE = nullptr;
bool IsParam = false;
// First see if we reached the declaration of the region.
@@ -484,12 +484,12 @@
// the same binding was re-assigned here.
if (!StoreSite) {
if (Succ->getState()->getSVal(R) != V)
- return NULL;
+ return nullptr;
if (Pred->getState()->getSVal(R) == V) {
Optional<PostStore> PS = Succ->getLocationAs<PostStore>();
if (!PS || PS->getLocationValue() != R)
- return NULL;
+ return nullptr;
}
StoreSite = Succ;
@@ -526,7 +526,7 @@
}
if (!StoreSite)
- return NULL;
+ return nullptr;
Satisfied = true;
// If we have an expression that provided the value, try to track where it
@@ -550,7 +550,7 @@
if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
const Stmt *S = PS->getStmt();
- const char *action = 0;
+ const char *action = nullptr;
const DeclStmt *DS = dyn_cast<DeclStmt>(S);
const VarRegion *VR = dyn_cast<VarRegion>(R);
@@ -703,7 +703,7 @@
L = PathDiagnosticLocation::create(P, BRC.getSourceManager());
if (!L.isValid() || !L.asLocation().isValid())
- return NULL;
+ return nullptr;
return new PathDiagnosticEventPiece(L, os.str());
}
@@ -733,7 +733,7 @@
BugReporterContext &BRC,
BugReport &BR) {
if (IsSatisfied)
- return NULL;
+ return nullptr;
// Start tracking after we see the first state in which the value is
// constrained.
@@ -741,7 +741,7 @@
if (!isUnderconstrained(N))
IsTrackingTurnedOn = true;
if (!IsTrackingTurnedOn)
- return 0;
+ return nullptr;
// Check if in the previous state it was feasible for this constraint
// to *not* be true.
@@ -765,21 +765,21 @@
}
if (os.str().empty())
- return NULL;
+ return nullptr;
// Construct a new PathDiagnosticPiece.
ProgramPoint P = N->getLocation();
PathDiagnosticLocation L =
PathDiagnosticLocation::create(P, BRC.getSourceManager());
if (!L.isValid())
- return NULL;
-
+ return nullptr;
+
PathDiagnosticEventPiece *X = new PathDiagnosticEventPiece(L, os.str());
X->setTag(getTag());
return X;
}
- return NULL;
+ return nullptr;
}
SuppressInlineDefensiveChecksVisitor::
@@ -813,14 +813,14 @@
BugReporterContext &BRC,
BugReport &BR) {
if (IsSatisfied)
- return 0;
+ return nullptr;
// Start tracking after we see the first state in which the value is null.
if (!IsTrackingTurnedOn)
if (Succ->getState()->isNull(V).isConstrainedTrue())
IsTrackingTurnedOn = true;
if (!IsTrackingTurnedOn)
- return 0;
+ return nullptr;
// Check if in the previous state it was feasible for this value
// to *not* be null.
@@ -835,7 +835,7 @@
if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC))
BR.markInvalid("Suppress IDC", CurLC);
}
- return 0;
+ return nullptr;
}
static const MemRegion *getLocationRegionIfReference(const Expr *E,
@@ -843,7 +843,7 @@
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
if (!VD->getType()->isReferenceType())
- return 0;
+ return nullptr;
ProgramStateManager &StateMgr = N->getState()->getStateManager();
MemRegionManager &MRMgr = StateMgr.getRegionManager();
return MRMgr.getVarRegion(VD, N->getLocationContext());
@@ -856,7 +856,7 @@
// Wrapper w = { *(int *)0 };
// w.ref = 1;
- return 0;
+ return nullptr;
}
static const Expr *peelOffOuterExpr(const Expr *Ex,
@@ -906,7 +906,7 @@
S = PeeledEx;
}
- const Expr *Inner = 0;
+ const Expr *Inner = nullptr;
if (const Expr *Ex = dyn_cast<Expr>(S)) {
Ex = Ex->IgnoreParenCasts();
if (ExplodedGraph::isInterestingLValueExpr(Ex) || CallEvent::isCallStmt(Ex))
@@ -948,7 +948,7 @@
// See if the expression we're interested refers to a variable.
// If so, we can track both its contents and constraints on its value.
if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) {
- const MemRegion *R = 0;
+ const MemRegion *R = nullptr;
// Find the ExplodedNode where the lvalue (the value of 'Ex')
// was computed. We need this for getting the location value.
@@ -1060,14 +1060,14 @@
const ExplodedNode *N) {
const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
if (!ME)
- return 0;
+ return nullptr;
if (const Expr *Receiver = ME->getInstanceReceiver()) {
ProgramStateRef state = N->getState();
SVal V = state->getSVal(Receiver, N->getLocationContext());
if (state->isNull(V).isConstrainedTrue())
return Receiver;
}
- return 0;
+ return nullptr;
}
PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
@@ -1076,12 +1076,12 @@
BugReport &BR) {
Optional<PreStmt> P = N->getLocationAs<PreStmt>();
if (!P)
- return 0;
+ return nullptr;
const Stmt *S = P->getStmt();
const Expr *Receiver = getNilReceiver(S, N);
if (!Receiver)
- return 0;
+ return nullptr;
llvm::SmallString<256> Buf;
llvm::raw_svector_ostream OS(Buf);
@@ -1181,15 +1181,15 @@
// were generated by the analyzer engine proper, not checkers.
if (CurrentState->getGDM().getRoot() ==
PrevState->getGDM().getRoot())
- return 0;
-
+ return nullptr;
+
// If an assumption was made on a branch, it should be caught
// here by looking at the state transition.
if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) {
const CFGBlock *srcBlk = BE->getSrc();
if (const Stmt *term = srcBlk->getTerminator())
return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
- return 0;
+ return nullptr;
}
if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) {
@@ -1206,11 +1206,11 @@
if (tag == tags.second)
return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
BRC, BR, N);
-
- return 0;
+
+ return nullptr;
}
-
- return 0;
+
+ return nullptr;
}
PathDiagnosticPiece *
@@ -1220,11 +1220,11 @@
const CFGBlock *dstBlk,
BugReport &R,
BugReporterContext &BRC) {
- const Expr *Cond = 0;
-
+ const Expr *Cond = nullptr;
+
switch (Term->getStmtClass()) {
default:
- return 0;
+ return nullptr;
case Stmt::IfStmtClass:
Cond = cast<IfStmt>(Term)->getCond();
break;
@@ -1252,7 +1252,7 @@
Ex = Ex->IgnoreParenCasts();
switch (Ex->getStmtClass()) {
default:
- return 0;
+ return nullptr;
case Stmt::BinaryOperatorClass:
return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
R, N);
@@ -1266,7 +1266,7 @@
Ex = UO->getSubExpr();
continue;
}
- return 0;
+ return nullptr;
}
}
}
@@ -1361,8 +1361,8 @@
// both the LHS and RHS.
if (LhsString.empty() || RhsString.empty() ||
!BinaryOperator::isComparisonOp(Op))
- return 0;
-
+ return nullptr;
+
// Should we invert the strings if the LHS is not a variable name?
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
@@ -1387,7 +1387,7 @@
case BO_LE: Op = BO_GT; break;
case BO_GE: Op = BO_LT; break;
default:
- return 0;
+ return nullptr;
}
switch (Op) {
@@ -1437,7 +1437,7 @@
else if (Ty->isIntegralOrEnumerationType())
Out << (tookTrue ? "non-zero" : "zero");
else
- return 0;
+ return nullptr;
const LocationContext *LCtx = N->getLocationContext();
PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
@@ -1467,8 +1467,8 @@
const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
if (!VD)
- return 0;
-
+ return nullptr;
+
SmallString<256> Buf;
llvm::raw_svector_ostream Out(Buf);
@@ -1483,8 +1483,8 @@
else if (VDTy->isScalarType())
Out << (tookTrue ? "not equal to 0" : "0");
else
- return 0;
-
+ return nullptr;
+
const LocationContext *LCtx = N->getLocationContext();
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
PathDiagnosticEventPiece *event =
@@ -1514,7 +1514,7 @@
while (const NamespaceDecl *Parent = dyn_cast<NamespaceDecl>(ND->getParent()))
ND = Parent;
- return ND->getName() == "std";
+ return ND->isStdNamespace();
}
@@ -1534,8 +1534,8 @@
// Note that this will not help for any other data structure libraries, like
// TR1, Boost, or llvm/ADT.
if (Options.shouldSuppressFromCXXStandardLibrary()) {
- BR.markInvalid(getTag(), 0);
- return 0;
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
} else {
// If the the complete 'std' suppression is not enabled, suppress reports
@@ -1547,8 +1547,8 @@
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "list") {
- BR.markInvalid(getTag(), 0);
- return 0;
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
}
}
@@ -1566,8 +1566,8 @@
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "basic_string") {
- BR.markInvalid(getTag(), 0);
- return 0;
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
}
}
}
@@ -1580,12 +1580,12 @@
while (Loc.isMacroID()) {
Loc = Loc.getSpellingLoc();
if (SM.getFilename(Loc).endswith("sys/queue.h")) {
- BR.markInvalid(getTag(), 0);
- return 0;
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
}
}
- return 0;
+ return nullptr;
}
PathDiagnosticPiece *
@@ -1600,7 +1600,7 @@
// We are only interested in visiting CallEnter nodes.
Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
if (!CEnter)
- return 0;
+ return nullptr;
// Check if one of the arguments is the region the visitor is tracking.
CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
@@ -1636,8 +1636,8 @@
SVal BoundVal = State->getSVal(R);
if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
BR.markInteresting(CEnter->getCalleeContext());
- return 0;
+ return nullptr;
}
}
- return 0;
+ return nullptr;
}
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index 84a769f..a02e413 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -139,6 +139,11 @@
ProgramStateRef Orig) const {
ProgramStateRef Result = (Orig ? Orig : getState());
+ // Don't invalidate anything if the callee is marked pure/const.
+ if (const Decl *callee = getDecl())
+ if (callee->hasAttr<PureAttr>() || callee->hasAttr<ConstAttr>())
+ return Result;
+
SmallVector<SVal, 8> ValuesToInvalidate;
RegionAndSymbolInvalidationTraits ETraits;
@@ -167,7 +172,7 @@
return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(),
BlockCount, getLocationContext(),
/*CausedByPointerEscape*/ true,
- /*Symbols=*/0, this, &ETraits);
+ /*Symbols=*/nullptr, this, &ETraits);
}
ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
@@ -213,7 +218,7 @@
void CallEvent::dump(raw_ostream &Out) const {
ASTContext &Ctx = getState()->getStateManager().getContext();
if (const Expr *E = getOriginExpr()) {
- E->printPretty(Out, 0, Ctx.getPrintingPolicy());
+ E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
Out << "\n";
return;
}
@@ -471,7 +476,7 @@
// that ExprEngine can decide what to do with it.
if (DynType.canBeASubClass())
return RuntimeDefinition(Definition, R->StripCasts());
- return RuntimeDefinition(Definition, /*DispatchRegion=*/0);
+ return RuntimeDefinition(Definition, /*DispatchRegion=*/nullptr);
}
void CXXInstanceCall::getInitialStackFrameContents(
@@ -540,7 +545,7 @@
ArrayRef<ParmVarDecl*> BlockCall::parameters() const {
const BlockDecl *D = getDecl();
if (!D)
- return 0;
+ return nullptr;
return D->parameters();
}
@@ -662,13 +667,13 @@
typedef llvm::PointerIntPair<const PseudoObjectExpr *, 2> ObjCMessageDataTy;
const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const {
- assert(Data != 0 && "Lazy lookup not yet performed.");
+ assert(Data && "Lazy lookup not yet performed.");
assert(getMessageKind() != OCM_Message && "Explicit message send.");
return ObjCMessageDataTy::getFromOpaqueValue(Data).getPointer();
}
ObjCMessageKind ObjCMethodCall::getMessageKind() const {
- if (Data == 0) {
+ if (!Data) {
// Find the parent, ignoring implicit casts.
ParentMap &PM = getLocationContext()->getParentMap();
@@ -706,7 +711,7 @@
}
const_cast<ObjCMethodCall *>(this)->Data
- = ObjCMessageDataTy(0, 1).getOpaqueValue();
+ = ObjCMessageDataTy(nullptr, 1).getOpaqueValue();
assert(getMessageKind() == OCM_Message);
return OCM_Message;
}
@@ -742,7 +747,7 @@
// Find the first declaration in the class hierarchy that declares
// the selector.
- ObjCMethodDecl *D = 0;
+ ObjCMethodDecl *D = nullptr;
while (true) {
D = IDecl->lookupMethod(Sel, true);
@@ -781,10 +786,10 @@
if (E->isInstanceMessage()) {
// Find the the receiver type.
- const ObjCObjectPointerType *ReceiverT = 0;
+ const ObjCObjectPointerType *ReceiverT = nullptr;
bool CanBeSubClassed = false;
QualType SupersType = E->getSuperType();
- const MemRegion *Receiver = 0;
+ const MemRegion *Receiver = nullptr;
if (!SupersType.isNull()) {
// Super always means the type of immediate predecessor to the method
@@ -848,7 +853,7 @@
if (CanBeSubClassed)
return RuntimeDefinition(MD, Receiver);
else
- return RuntimeDefinition(MD, 0);
+ return RuntimeDefinition(MD, nullptr);
}
} else {
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index c1ae7e9..2684cc7 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -58,7 +58,7 @@
assert(D);
unsigned DeclKind = D->getKind();
- CachedDeclCheckers *checkers = 0;
+ CachedDeclCheckers *checkers = nullptr;
CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
if (CCI != CachedDeclCheckersMap.end()) {
checkers = &(CCI->second);
@@ -109,7 +109,7 @@
const ExplodedNodeSet *PrevSet = &Src;
for (; I != E; ++I) {
- ExplodedNodeSet *CurrSet = 0;
+ ExplodedNodeSet *CurrSet = nullptr;
if (I+1 == E)
CurrSet = &Dst;
else {
@@ -477,7 +477,7 @@
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
- return NULL;
+ return nullptr;
state = RegionChangesCheckers[i].CheckFn(state, invalidated,
ExplicitRegions, Regions, Call);
}
@@ -491,7 +491,7 @@
const CallEvent *Call,
PointerEscapeKind Kind,
RegionAndSymbolInvalidationTraits *ETraits) {
- assert((Call != NULL ||
+ assert((Call != nullptr ||
(Kind != PSK_DirectEscapeOnCall &&
Kind != PSK_IndirectEscapeOnCall)) &&
"Call must not be NULL when escaping on call");
@@ -499,7 +499,7 @@
// If any checker declares the state infeasible (or if it starts that
// way), bail out.
if (!State)
- return NULL;
+ return nullptr;
State = PointerEscapeCheckers[i](State, Escaped, Call, Kind, ETraits);
}
return State;
@@ -513,7 +513,7 @@
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
- return NULL;
+ return nullptr;
state = EvalAssumeCheckers[i](state, Cond, Assumption);
}
return state;
diff --git a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
index d4afeda..b64e30b 100644
--- a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
@@ -45,7 +45,7 @@
const llvm::StringMap<size_t> &packageSizes,
CheckerOptInfo &opt, CheckerInfoSet &collected) {
// Use a binary search to find the possible start of the package.
- CheckerRegistry::CheckerInfo packageInfo(NULL, opt.getName(), "");
+ CheckerRegistry::CheckerInfo packageInfo(nullptr, opt.getName(), "");
CheckerRegistry::CheckerInfoList::const_iterator e = checkers.end();
CheckerRegistry::CheckerInfoList::const_iterator i =
std::lower_bound(checkers.begin(), e, packageInfo, checkerNameLT);
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 897164b..e710c7f 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -12,8 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "CoreEngine"
-
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtCXX.h"
@@ -26,6 +24,8 @@
using namespace clang;
using namespace ento;
+#define DEBUG_TYPE "CoreEngine"
+
STATISTIC(NumSteps,
"The # of steps executed.");
STATISTIC(NumReachedMaxSteps,
@@ -192,9 +192,9 @@
if (!InitState)
// Generate the root.
- generateNode(StartLoc, SubEng.getInitialState(L), 0);
+ generateNode(StartLoc, SubEng.getInitialState(L), nullptr);
else
- generateNode(StartLoc, InitState, 0);
+ generateNode(StartLoc, InitState, nullptr);
}
// Check if we have a steps limit
@@ -567,7 +567,7 @@
bool isNew;
ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew);
Node->addPredecessor(N, *G);
- return isNew ? Node : 0;
+ return isNew ? Node : nullptr;
}
@@ -616,7 +616,7 @@
Frontier.erase(FromN);
if (!IsNew)
- return 0;
+ return nullptr;
if (!MarkAsSink)
Frontier.Add(N);
@@ -640,7 +640,7 @@
ExplodedNode *NodePred) {
// If the branch has been marked infeasible we should not generate a node.
if (!isFeasible(branch))
- return NULL;
+ return nullptr;
ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF,
NodePred->getLocationContext());
@@ -659,7 +659,7 @@
Succ->addPredecessor(Pred, *Eng.G);
if (!IsNew)
- return 0;
+ return nullptr;
if (!IsSink)
Eng.WList->enqueue(Succ);
@@ -678,7 +678,7 @@
false, &IsNew);
Succ->addPredecessor(Pred, *Eng.G);
if (!IsNew)
- return 0;
+ return nullptr;
Eng.WList->enqueue(Succ);
return Succ;
@@ -695,8 +695,8 @@
// Sanity check for default blocks that are unreachable and not caught
// by earlier stages.
if (!DefaultBlock)
- return NULL;
-
+ return nullptr;
+
bool IsNew;
ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
Pred->getLocationContext()), St,
@@ -704,7 +704,7 @@
Succ->addPredecessor(Pred, *Eng.G);
if (!IsNew)
- return 0;
+ return nullptr;
if (!IsSink)
Eng.WList->enqueue(Succ);
diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp
index 0041d9f..6a26650 100644
--- a/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/lib/StaticAnalyzer/Core/Environment.cpp
@@ -54,7 +54,8 @@
EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
: std::pair<const Stmt *,
const StackFrameContext *>(ignoreTransparentExprs(S),
- L ? L->getCurrentStackFrame() : 0) {}
+ L ? L->getCurrentStackFrame()
+ : nullptr) {}
SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
const SVal* X = ExprBindings.lookup(E);
@@ -208,7 +209,7 @@
Out << " (" << (const void*) En.getLocationContext() << ','
<< (const void*) S << ") ";
LangOptions LO; // FIXME.
- S->printPretty(Out, 0, PrintingPolicy(LO));
+ S->printPretty(Out, nullptr, PrintingPolicy(LO));
Out << " : " << I.getData();
}
}
diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 7812c96..1c9a282 100644
--- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -34,7 +34,7 @@
ExplodedNode::Auditor::~Auditor() {}
#ifndef NDEBUG
-static ExplodedNode::Auditor* NodeAuditor = 0;
+static ExplodedNode::Auditor* NodeAuditor = nullptr;
#endif
void ExplodedNode::SetAuditor(ExplodedNode::Auditor* A) {
@@ -276,11 +276,11 @@
ExplodedNode * const *ExplodedNode::NodeGroup::begin() const {
if (getFlag())
- return 0;
+ return nullptr;
const GroupStorage &Storage = reinterpret_cast<const GroupStorage &>(P);
if (Storage.isNull())
- return 0;
+ return nullptr;
if (ExplodedNodeVector *V = Storage.dyn_cast<ExplodedNodeVector *>())
return V->begin();
return Storage.getAddrOfPtr1();
@@ -288,11 +288,11 @@
ExplodedNode * const *ExplodedNode::NodeGroup::end() const {
if (getFlag())
- return 0;
+ return nullptr;
const GroupStorage &Storage = reinterpret_cast<const GroupStorage &>(P);
if (Storage.isNull())
- return 0;
+ return nullptr;
if (ExplodedNodeVector *V = Storage.dyn_cast<ExplodedNodeVector *>())
return V->end();
return Storage.getAddrOfPtr1() + 1;
@@ -304,7 +304,7 @@
bool* IsNew) {
// Profile 'State' to determine if we already have an existing node.
llvm::FoldingSetNodeID profile;
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
NodeTy::Profile(profile, L, State, IsSink);
NodeTy* V = Nodes.FindNodeOrInsertPos(profile, InsertPos);
@@ -342,7 +342,7 @@
InterExplodedGraphMap *InverseMap) const{
if (Nodes.empty())
- return 0;
+ return nullptr;
typedef llvm::DenseSet<const ExplodedNode*> Pass1Ty;
Pass1Ty Pass1;
@@ -385,7 +385,7 @@
// We didn't hit a root? Return with a null pointer for the new graph.
if (WL2.empty())
- return 0;
+ return nullptr;
// Create an empty graph.
ExplodedGraph* G = MakeEmptyGraph();
@@ -400,7 +400,8 @@
// Create the corresponding node in the new graph and record the mapping
// from the old node to the new node.
- ExplodedNode *NewN = G->getNode(N->getLocation(), N->State, N->isSink(), 0);
+ ExplodedNode *NewN = G->getNode(N->getLocation(), N->State, N->isSink(),
+ nullptr);
Pass2[N] = NewN;
// Also record the reverse mapping from the new node to the old node.
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index e7f49b2..ac87d58 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -13,8 +13,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "ExprEngine"
-
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CharUnits.h"
@@ -40,6 +38,8 @@
using namespace ento;
using llvm::APSInt;
+#define DEBUG_TYPE "ExprEngine"
+
STATISTIC(NumRemoveDeadBindings,
"The # of times RemoveDeadBindings is called");
STATISTIC(NumMaxBlockCountReached,
@@ -70,7 +70,7 @@
this),
SymMgr(StateMgr.getSymbolManager()),
svalBuilder(StateMgr.getSValBuilder()),
- currStmtIdx(0), currBldrCtx(0),
+ currStmtIdx(0), currBldrCtx(nullptr),
ObjCNoRet(mgr.getASTContext()),
ObjCGCEnabled(gcEnabled), BR(mgr, *this),
VisitedCallees(VisitedCalleesIn),
@@ -155,7 +155,7 @@
// top-level function. This is our starting assumption for
// analyzing an "open" program.
const StackFrameContext *SFC = InitLoc->getCurrentStackFrame();
- if (SFC->getParent() == 0) {
+ if (SFC->getParent() == nullptr) {
loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC);
SVal V = state->getSVal(L);
if (Optional<Loc> LV = V.getAs<Loc>()) {
@@ -211,7 +211,7 @@
// Create a temporary object region for the inner expression (which may have
// a more derived type) and bind the value into it.
- const TypedValueRegion *TR = NULL;
+ const TypedValueRegion *TR = nullptr;
if (const MaterializeTemporaryExpr *MT =
dyn_cast<MaterializeTemporaryExpr>(Result)) {
StorageDuration SD = MT->getStorageDuration();
@@ -335,7 +335,7 @@
const Stmt *DiagnosticStmt,
ProgramPoint::Kind K) {
assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
- ReferenceStmt == 0 || isa<ReturnStmt>(ReferenceStmt))
+ ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))
&& "PostStmt is not generally supported by the SymbolReaper yet");
assert(LC && "Must pass the current (or expiring) LocationContext");
@@ -356,7 +356,7 @@
LC = LC->getParent();
}
- const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : 0;
+ const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : nullptr;
SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());
getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
@@ -664,7 +664,7 @@
// FIXME: Inlining of temporary destructors is not supported yet anyway, so we
// just put a NULL region for now. This will need to be changed later.
- VisitCXXDestructor(varType, NULL, D.getBindTemporaryExpr(),
+ VisitCXXDestructor(varType, nullptr, D.getBindTemporaryExpr(),
/*IsBase=*/ false, Pred, Dst);
}
@@ -871,7 +871,8 @@
it != et; ++it) {
ExplodedNode *N = *it;
const LocationContext *LCtx = N->getLocationContext();
- SVal result = svalBuilder.conjureSymbolVal(0, Ex, LCtx, resultType,
+ SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+ resultType,
currBldrCtx->blockCount());
ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result);
Bldr2.generateNode(S, N, state);
@@ -951,7 +952,7 @@
ProgramStateRef NewState =
createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
if (NewState != State) {
- Pred = Bldr.generateNode(OCE, Pred, NewState, /*Tag=*/0,
+ Pred = Bldr.generateNode(OCE, Pred, NewState, /*Tag=*/nullptr,
ProgramPoint::PreStmtKind);
// Did we cache out?
if (!Pred)
@@ -1210,14 +1211,14 @@
const StackFrameContext *CalleeSF = CalleeLC->getCurrentStackFrame();
const StackFrameContext *CallerSF = CalleeSF->getParent()->getCurrentStackFrame();
assert(CalleeSF && CallerSF);
- ExplodedNode *BeforeProcessingCall = 0;
+ ExplodedNode *BeforeProcessingCall = nullptr;
const Stmt *CE = CalleeSF->getCallSite();
// Find the first node before we started processing the call expression.
while (N) {
ProgramPoint L = N->getLocation();
BeforeProcessingCall = N;
- N = N->pred_empty() ? NULL : *(N->pred_begin());
+ N = N->pred_empty() ? nullptr : *(N->pred_begin());
// Skip the nodes corresponding to the inlined code.
if (L.getLocationContext()->getCurrentStackFrame() != CallerSF)
@@ -1352,6 +1353,33 @@
return state->getSVal(Ex, LCtx);
}
+#ifndef NDEBUG
+static const Stmt *getRightmostLeaf(const Stmt *Condition) {
+ while (Condition) {
+ const BinaryOperator *BO = dyn_cast<BinaryOperator>(Condition);
+ if (!BO || !BO->isLogicalOp()) {
+ return Condition;
+ }
+ Condition = BO->getRHS()->IgnoreParens();
+ }
+ return nullptr;
+}
+#endif
+
+// Returns the condition the branch at the end of 'B' depends on and whose value
+// has been evaluated within 'B'.
+// In most cases, the terminator condition of 'B' will be evaluated fully in
+// the last statement of 'B'; in those cases, the resolved condition is the
+// given 'Condition'.
+// If the condition of the branch is a logical binary operator tree, the CFG is
+// optimized: in that case, we know that the expression formed by all but the
+// rightmost leaf of the logical binary operator tree must be true, and thus
+// the branch condition is at this point equivalent to the truth value of that
+// rightmost leaf; the CFG block thus only evaluates this rightmost leaf
+// expression in its final statement. As the full condition in that case was
+// not evaluated, and is thus not in the SVal cache, we need to use that leaf
+// expression to evaluate the truth value of the condition in the current state
+// space.
static const Stmt *ResolveCondition(const Stmt *Condition,
const CFGBlock *B) {
if (const Expr *Ex = dyn_cast<Expr>(Condition))
@@ -1361,6 +1389,12 @@
if (!BO || !BO->isLogicalOp())
return Condition;
+ // FIXME: This is a workaround until we handle temporary destructor branches
+ // correctly; currently, temporary destructor branches lead to blocks that
+ // only have a terminator (and no statements). These blocks violate the
+ // invariant this function assumes.
+ if (B->getTerminator().isTemporaryDtorsBranch()) return Condition;
+
// For logical operations, we still have the case where some branches
// use the traditional "merge" approach and others sink the branch
// directly into the basic blocks representing the logical operation.
@@ -1375,18 +1409,9 @@
Optional<CFGStmt> CS = Elem.getAs<CFGStmt>();
if (!CS)
continue;
- if (CS->getStmt() != Condition)
- break;
- return Condition;
- }
-
- assert(I != E);
-
- while (Condition) {
- BO = dyn_cast<BinaryOperator>(Condition);
- if (!BO || !BO->isLogicalOp())
- return Condition;
- Condition = BO->getRHS()->IgnoreParens();
+ const Stmt *LastStmt = CS->getStmt();
+ assert(LastStmt == Condition || LastStmt == getRightmostLeaf(Condition));
+ return LastStmt;
}
llvm_unreachable("could not resolve condition");
}
@@ -1484,7 +1509,7 @@
builder.markInfeasible(false);
}
}
- currBldrCtx = 0;
+ currBldrCtx = nullptr;
}
/// The GDM component containing the set of global variables which have been
@@ -1513,7 +1538,7 @@
builder.generateNode(state, initHasRun, Pred);
builder.markInfeasible(!initHasRun);
- currBldrCtx = 0;
+ currBldrCtx = nullptr;
}
/// processIndirectGoto - Called by CoreEngine. Used to generate successor
@@ -1654,7 +1679,7 @@
}
else {
defaultIsFeasible = false;
- DefaultSt = NULL;
+ DefaultSt = nullptr;
}
}
@@ -1715,7 +1740,7 @@
V = UnknownVal();
}
- Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
+ Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
return;
}
@@ -1727,7 +1752,7 @@
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
SVal V = svalBuilder.getFunctionPointer(FD);
- Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
+ Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
return;
}
@@ -1738,7 +1763,7 @@
SVal V = svalBuilder.conjureSymbolVal(Ex, LCtx, getContext().VoidPtrTy,
currBldrCtx->blockCount());
state = state->assume(V.castAs<DefinedOrUnknownSVal>(), true);
- Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
+ Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
return;
}
@@ -1768,7 +1793,7 @@
state->getSVal(Idx, LCtx),
state->getSVal(Base, LCtx));
assert(A->isGLValue());
- Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), 0,
+ Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
}
}
@@ -1842,7 +1867,7 @@
L = UnknownVal();
}
- Bldr.generateNode(M, *I, state->BindExpr(M, LCtx, L), 0,
+ Bldr.generateNode(M, *I, state->BindExpr(M, LCtx, L), nullptr,
ProgramPoint::PostLValueKind);
} else {
Bldr.takeNodes(*I);
@@ -1908,9 +1933,9 @@
const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols();
State = getCheckerManager().runCheckersForPointerEscape(State,
EscapedSymbols,
- /*CallEvent*/ 0,
+ /*CallEvent*/ nullptr,
PSK_EscapeOnBind,
- 0);
+ nullptr);
return State;
}
@@ -1929,7 +1954,7 @@
if (!Call)
return getCheckerManager().runCheckersForPointerEscape(State,
*Invalidated,
- 0,
+ nullptr,
PSK_EscapeOther,
&ITraits);
@@ -1986,7 +2011,8 @@
// If the location is not a 'Loc', it will already be handled by
// the checkers. There is nothing left to do.
if (!location.getAs<Loc>()) {
- const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/0, /*tag*/0);
+ const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
+ /*tag*/nullptr);
ProgramStateRef state = Pred->getState();
state = processPointerEscapedOnBind(state, location, Val);
Bldr.generateNode(L, state, Pred);
@@ -2007,13 +2033,13 @@
state = state->bindLoc(location.castAs<Loc>(),
Val, /* notifyChanges = */ !atDeclInit);
- const MemRegion *LocReg = 0;
+ const MemRegion *LocReg = nullptr;
if (Optional<loc::MemRegionVal> LocRegVal =
location.getAs<loc::MemRegionVal>()) {
LocReg = LocRegVal->getRegion();
}
-
- const ProgramPoint L = PostStore(StoreE, LC, LocReg, 0);
+
+ const ProgramPoint L = PostStore(StoreE, LC, LocReg, nullptr);
Bldr.generateNode(L, state, PredI);
}
}
@@ -2402,11 +2428,11 @@
if (const CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
Out << "\\lcase ";
LangOptions LO; // FIXME.
- C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO));
+ C->getLHS()->printPretty(Out, nullptr, PrintingPolicy(LO));
if (const Stmt *RHS = C->getRHS()) {
Out << " .. ";
- RHS->printPretty(Out, 0, PrintingPolicy(LO));
+ RHS->printPretty(Out, nullptr, PrintingPolicy(LO));
}
Out << ":";
@@ -2448,7 +2474,7 @@
Out << S->getStmtClassName() << ' ' << (const void*) S << ' ';
LangOptions LO; // FIXME.
- S->printPretty(Out, 0, PrintingPolicy(LO));
+ S->printPretty(Out, nullptr, PrintingPolicy(LO));
printLocation(Out, S->getLocStart());
if (Loc.getAs<PreStmt>())
@@ -2538,8 +2564,8 @@
llvm::ViewGraph(*G.roots_begin(), "ExprEngine");
- GraphPrintCheckerState = NULL;
- GraphPrintSourceManager = NULL;
+ GraphPrintCheckerState = nullptr;
+ GraphPrintSourceManager = nullptr;
}
#endif
}
@@ -2556,7 +2582,7 @@
else
llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedExprEngine");
- GraphPrintCheckerState = NULL;
- GraphPrintSourceManager = NULL;
+ GraphPrintCheckerState = nullptr;
+ GraphPrintSourceManager = nullptr;
#endif
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 91b072f..ffda527 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -47,7 +47,8 @@
// FIXME: Handle structs.
if (RightV.isUnknown()) {
unsigned Count = currBldrCtx->blockCount();
- RightV = svalBuilder.conjureSymbolVal(0, B->getRHS(), LCtx, Count);
+ RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx,
+ Count);
}
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
@@ -81,6 +82,12 @@
}
}
+ // Although we don't yet model pointers-to-members, we do need to make
+ // sure that the members of temporaries have a valid 'this' pointer for
+ // other checks.
+ if (B->getOpcode() == BO_PtrMemD)
+ state = createTemporaryRegionIfNeeded(state, LCtx, LHS);
+
// Process non-assignments except commas or short-circuited
// logical expressions (LAnd and LOr).
SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
@@ -151,7 +158,7 @@
// The symbolic value is actually for the type of the left-hand side
// expression, not the computation type, as this is the value the
// LValue on the LHS will bind to.
- LHSVal = svalBuilder.conjureSymbolVal(0, B->getRHS(), LCtx, LTy,
+ LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy,
currBldrCtx->blockCount());
// However, we need to convert the symbol to the computation type.
Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
@@ -211,8 +218,8 @@
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
Bldr.generateNode(BE, Pred,
State->BindExpr(BE, Pred->getLocationContext(), V),
- 0, ProgramPoint::PostLValueKind);
-
+ nullptr, ProgramPoint::PostLValueKind);
+
// FIXME: Move all post/pre visits to ::Visit().
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
}
@@ -361,7 +368,7 @@
// If we don't know if the cast succeeded, conjure a new symbol.
if (val.isUnknown()) {
DefinedOrUnknownSVal NewSym =
- svalBuilder.conjureSymbolVal(0, CastE, LCtx, resultType,
+ svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
currBldrCtx->blockCount());
state = state->BindExpr(CastE, LCtx, NewSym);
} else
@@ -389,7 +396,7 @@
QualType resultType = CastE->getType();
if (CastE->isGLValue())
resultType = getContext().getPointerType(resultType);
- SVal result = svalBuilder.conjureSymbolVal(0, CastE, LCtx,
+ SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx,
resultType,
currBldrCtx->blockCount());
state = state->BindExpr(CastE, LCtx, result);
@@ -487,7 +494,7 @@
Ty = getContext().getPointerType(Ty);
}
- InitVal = svalBuilder.conjureSymbolVal(0, InitEx, LC, Ty,
+ InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty,
currBldrCtx->blockCount());
}
@@ -634,7 +641,7 @@
StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
- const CFGBlock *SrcBlock = 0;
+ const CFGBlock *SrcBlock = nullptr;
// Find the predecessor block.
ProgramStateRef SrcState = state;
@@ -679,7 +686,8 @@
}
if (!hasValue)
- V = svalBuilder.conjureSymbolVal(0, Ex, LCtx, currBldrCtx->blockCount());
+ V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+ currBldrCtx->blockCount());
// Generate a new node with the binding from the appropriate path.
B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));
@@ -929,7 +937,8 @@
// Conjure a new symbol if necessary to recover precision.
if (Result.isUnknown()){
DefinedOrUnknownSVal SymVal =
- svalBuilder.conjureSymbolVal(0, Ex, LCtx, currBldrCtx->blockCount());
+ svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+ currBldrCtx->blockCount());
Result = SymVal;
// If the value is a location, ++/-- should always preserve
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 52fe156..2a76621 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -113,14 +113,22 @@
// See if we're constructing an existing region by looking at the next
// element in the CFG.
const CFGBlock *B = CurrBldrCtx.getBlock();
- if (CurrStmtIdx + 1 < B->size()) {
- CFGElement Next = (*B)[CurrStmtIdx+1];
+ unsigned int NextStmtIdx = CurrStmtIdx + 1;
+ if (NextStmtIdx < B->size()) {
+ CFGElement Next = (*B)[NextStmtIdx];
+
+ // Is this a destructor? If so, we might be in the middle of an assignment
+ // to a local or member: look ahead one more element to see what we find.
+ while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) {
+ ++NextStmtIdx;
+ Next = (*B)[NextStmtIdx];
+ }
// Is this a constructor for a local variable?
if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) {
if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) {
if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
- if (Var->getInit()->IgnoreImplicit() == CE) {
+ if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) {
SVal LValue = State->getLValue(Var, LCtx);
QualType Ty = Var->getType();
LValue = makeZeroElementRegion(State, LValue, Ty);
@@ -172,7 +180,7 @@
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
- const MemRegion *Target = 0;
+ const MemRegion *Target = nullptr;
// FIXME: Handle arrays, which run the same constructor for every element.
// For now, we just run the first constructor (which should still invalidate
@@ -254,7 +262,8 @@
// since it's then possible to be initializing one part of a multi-
// dimensional array.
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal);
- Bldr.generateNode(CE, *I, State, /*tag=*/0, ProgramPoint::PreStmtKind);
+ Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
+ ProgramPoint::PreStmtKind);
}
}
}
@@ -389,7 +398,7 @@
if (IsStandardGlobalOpNewFunction)
symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
else
- symVal = svalBuilder.conjureSymbolVal(0, CNE, LCtx, CNE->getType(),
+ symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
blockCount);
ProgramStateRef State = Pred->getState();
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 72af75d..4619f62 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -11,8 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "ExprEngine"
-
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -28,6 +26,8 @@
using namespace clang;
using namespace ento;
+#define DEBUG_TYPE "ExprEngine"
+
STATISTIC(NumOfDynamicDispatchPathSplits,
"The # of times we split the path due to imprecise dynamic dispatch info");
@@ -69,8 +69,8 @@
// corresponding Block.
static std::pair<const Stmt*,
const CFGBlock*> getLastStmt(const ExplodedNode *Node) {
- const Stmt *S = 0;
- const CFGBlock *Blk = 0;
+ const Stmt *S = nullptr;
+ const CFGBlock *Blk = nullptr;
const StackFrameContext *SF =
Node->getLocation().getLocationContext()->getCurrentStackFrame();
@@ -108,12 +108,12 @@
}
if (Node->pred_empty())
- return std::pair<const Stmt*, const CFGBlock*>((Stmt*)0, (CFGBlock*)0);
+ return std::make_pair(nullptr, nullptr);
Node = *Node->pred_begin();
}
- return std::pair<const Stmt*, const CFGBlock*>(S, Blk);
+ return std::make_pair(S, Blk);
}
/// Adjusts a return value when the called function's return type does not
@@ -160,8 +160,8 @@
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// Find the last statement in the function and the corresponding basic block.
- const Stmt *LastSt = 0;
- const CFGBlock *Blk = 0;
+ const Stmt *LastSt = nullptr;
+ const CFGBlock *Blk = nullptr;
std::tie(LastSt, Blk) = getLastStmt(Pred);
if (!Blk || !LastSt) {
Dst.Add(Pred);
@@ -229,8 +229,8 @@
const Stmt *CE = calleeCtx->getCallSite();
ProgramStateRef state = CEBNode->getState();
// Find the last statement in the function and the corresponding basic block.
- const Stmt *LastSt = 0;
- const CFGBlock *Blk = 0;
+ const Stmt *LastSt = nullptr;
+ const CFGBlock *Blk = nullptr;
std::tie(LastSt, Blk) = getLastStmt(CEBNode);
// Generate a CallEvent /before/ cleaning the state, so that we can get the
@@ -296,10 +296,10 @@
// context, telling it to clean up everything in the callee's context
// (and its children). We use the callee's function body as a diagnostic
// statement, with which the program point will be associated.
- removeDead(BindedRetNode, CleanedNodes, 0, calleeCtx,
+ removeDead(BindedRetNode, CleanedNodes, nullptr, calleeCtx,
calleeCtx->getAnalysisDeclContext()->getBody(),
ProgramPoint::PostStmtPurgeDeadSymbolsKind);
- currBldrCtx = 0;
+ currBldrCtx = nullptr;
} else {
CleanedNodes.Add(CEBNode);
}
@@ -387,14 +387,14 @@
const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
if (!ND)
return false;
-
+
while (const DeclContext *Parent = ND->getParent()) {
if (!isa<NamespaceDecl>(Parent))
break;
ND = cast<NamespaceDecl>(Parent);
}
- return ND->getName() == "std";
+ return ND->isStdNamespace();
}
// The GDM component containing the dynamic dispatch bifurcation info. When
@@ -471,7 +471,7 @@
const Stmt *CallE) {
const void *ReplayState = State->get<ReplayWithoutInlining>();
if (!ReplayState)
- return 0;
+ return nullptr;
assert(ReplayState == CallE && "Backtracked to the wrong call.");
(void)CallE;
@@ -565,7 +565,7 @@
QualType ResultTy = Call.getResultType();
SValBuilder &SVB = getSValBuilder();
unsigned Count = currBldrCtx->blockCount();
- SVal R = SVB.conjureSymbolVal(0, E, LCtx, ResultTy, Count);
+ SVal R = SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
return State->BindExpr(E, LCtx, R);
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index 57c04bf..a6611e0 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -77,7 +77,7 @@
if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
- assert(elemD->getInit() == 0);
+ assert(elemD->getInit() == nullptr);
elementV = state->getLValue(elemD, Pred->getLocationContext());
}
else {
@@ -85,7 +85,7 @@
}
ExplodedNodeSet dstLocation;
- evalLocation(dstLocation, S, elem, Pred, state, elementV, NULL, false);
+ evalLocation(dstLocation, S, elem, Pred, state, elementV, nullptr, false);
ExplodedNodeSet Tmp;
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 07a793e..e8ec005 100644
--- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -42,7 +42,7 @@
public:
HTMLDiagnostics(const std::string& prefix, const Preprocessor &pp);
- virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
+ virtual ~HTMLDiagnostics() { FlushDiagnostics(nullptr); }
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) override;
@@ -307,7 +307,7 @@
// Create the html for the message.
- const char *Kind = 0;
+ const char *Kind = nullptr;
switch (P.getKind()) {
case PathDiagnosticPiece::Call:
llvm_unreachable("Calls should already be handled");
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index 8f6c373..12bbfdf 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -148,7 +148,7 @@
bool SubRegion::isSubRegionOf(const MemRegion* R) const {
const MemRegion* r = getSuperRegion();
- while (r != 0) {
+ while (r != nullptr) {
if (r == R)
return true;
if (const SubRegion* sr = dyn_cast<SubRegion>(r))
@@ -173,7 +173,7 @@
const StackFrameContext *VarRegion::getStackFrame() const {
const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
- return SSR ? SSR->getStackFrame() : NULL;
+ return SSR ? SSR->getStackFrame() : nullptr;
}
//===----------------------------------------------------------------------===//
@@ -508,11 +508,11 @@
}
void StringRegion::dumpToStream(raw_ostream &os) const {
- Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOpts()));
+ Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
}
void ObjCStringRegion::dumpToStream(raw_ostream &os) const {
- Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOpts()));
+ Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
}
void SymbolicRegion::dumpToStream(raw_ostream &os) const {
@@ -757,12 +757,12 @@
LC = LC->getParent();
}
- return (const StackFrameContext*)0;
+ return (const StackFrameContext *)nullptr;
}
const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
const LocationContext *LC) {
- const MemRegion *sReg = 0;
+ const MemRegion *sReg = nullptr;
if (D->hasGlobalStorage() && !D->isStaticLocal()) {
@@ -850,7 +850,7 @@
MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
const LocationContext *LC,
unsigned blockCount) {
- const MemRegion *sReg = 0;
+ const MemRegion *sReg = nullptr;
const BlockDecl *BD = BC->getDecl();
if (!BD->hasCaptures()) {
// This handles 'static' blocks.
@@ -877,14 +877,14 @@
const CXXTempObjectRegion *
MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) {
return getSubRegion<CXXTempObjectRegion>(
- Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, NULL));
+ Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr));
}
const CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
const LocationContext *LC) {
- const MemRegion *sReg = 0;
+ const MemRegion *sReg = nullptr;
if (CL->isFileScope())
sReg = getGlobalsRegion();
@@ -1111,7 +1111,7 @@
return SymR;
SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
}
- return 0;
+ return nullptr;
}
// FIXME: Merge with the implementation of the same method in Store.cpp
@@ -1128,7 +1128,7 @@
RegionRawOffset ElementRegion::getAsArrayOffset() const {
CharUnits offset = CharUnits::Zero();
const ElementRegion *ER = this;
- const MemRegion *superR = NULL;
+ const MemRegion *superR = nullptr;
ASTContext &C = getContext();
// FIXME: Handle multi-dimensional arrays.
@@ -1160,7 +1160,7 @@
continue;
}
- return NULL;
+ return nullptr;
}
assert(superR && "super region cannot be NULL");
@@ -1184,7 +1184,7 @@
RegionOffset MemRegion::getAsOffset() const {
const MemRegion *R = this;
- const MemRegion *SymbolicOffsetBase = 0;
+ const MemRegion *SymbolicOffsetBase = nullptr;
int64_t Offset = 0;
while (1) {
@@ -1356,8 +1356,8 @@
std::pair<const VarRegion *, const VarRegion *>
BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
MemRegionManager &MemMgr = *getMemRegionManager();
- const VarRegion *VR = 0;
- const VarRegion *OriginalVR = 0;
+ const VarRegion *VR = nullptr;
+ const VarRegion *OriginalVR = nullptr;
if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
VR = MemMgr.getVarRegion(VD, this);
@@ -1400,8 +1400,8 @@
new (BVOriginal) VarVec(BC, E - I);
for ( ; I != E; ++I) {
- const VarRegion *VR = 0;
- const VarRegion *OriginalVR = 0;
+ const VarRegion *VR = nullptr;
+ const VarRegion *OriginalVR = nullptr;
std::tie(VR, OriginalVR) = getCaptureRegions(*I);
assert(VR);
assert(OriginalVR);
@@ -1421,8 +1421,8 @@
static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
if (Vec == (void*) 0x1)
- return BlockDataRegion::referenced_vars_iterator(0, 0);
-
+ return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
+
BumpVector<const MemRegion*> *VecOriginal =
static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
@@ -1438,8 +1438,8 @@
static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
if (Vec == (void*) 0x1)
- return BlockDataRegion::referenced_vars_iterator(0, 0);
-
+ return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
+
BumpVector<const MemRegion*> *VecOriginal =
static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
@@ -1454,7 +1454,7 @@
if (I.getCapturedRegion() == R)
return I.getOriginalRegion();
}
- return 0;
+ return nullptr;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 89e4309..a9527de 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/SourceManager.h"
@@ -128,7 +129,7 @@
// If the call is within a macro, don't do anything (for now).
if (CallLoc.isMacroID())
- return 0;
+ return nullptr;
assert(SMgr.isInMainFile(CallLoc) &&
"The call piece should be in the main file.");
@@ -139,7 +140,7 @@
const PathPieces &Path = CP->path;
if (Path.empty())
- return 0;
+ return nullptr;
// Check if the last piece in the callee path is a call to a function outside
// of the main file.
@@ -149,7 +150,7 @@
}
// Otherwise, the last piece is in the main file.
- return 0;
+ return nullptr;
}
void PathDiagnostic::resetDiagnosticLocationToMainFile() {
@@ -259,7 +260,7 @@
// Profile the node to see if we already have something matching it
llvm::FoldingSetNodeID profile;
D->Profile(profile);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
// Keep the PathDiagnostic with the shorter path.
@@ -451,6 +452,11 @@
Diags.clear();
}
+PathDiagnosticConsumer::FilesMade::~FilesMade() {
+ for (PDFileEntry &Entry : *this)
+ Entry.~PDFileEntry();
+}
+
void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
StringRef ConsumerName,
StringRef FileName) {
@@ -480,7 +486,7 @@
void *InsertPos;
PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos);
if (!Entry)
- return 0;
+ return nullptr;
return &Entry->files;
}
@@ -656,7 +662,7 @@
PathDiagnosticLocation::create(const ProgramPoint& P,
const SourceManager &SMng) {
- const Stmt* S = 0;
+ const Stmt* S = nullptr;
if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
const CFGBlock *BSrc = BE->getSrc();
S = BSrc->getTerminatorCondition();
@@ -697,7 +703,7 @@
if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
return PIPP->getInitializer()->getInit();
- return 0;
+ return nullptr;
}
const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
@@ -724,7 +730,7 @@
}
}
- return 0;
+ return nullptr;
}
PathDiagnosticLocation
@@ -859,13 +865,13 @@
void PathDiagnosticLocation::flatten() {
if (K == StmtK) {
K = RangeK;
- S = 0;
- D = 0;
+ S = nullptr;
+ D = nullptr;
}
else if (K == DeclK) {
K = SingleLocK;
- S = 0;
- D = 0;
+ S = nullptr;
+ D = nullptr;
}
}
@@ -975,7 +981,7 @@
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallEnterEvent() const {
if (!Callee)
- return 0;
+ return nullptr;
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
@@ -990,12 +996,12 @@
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
if (!callEnterWithin.asLocation().isValid())
- return 0;
+ return nullptr;
if (Callee->isImplicit() || !Callee->hasBody())
- return 0;
+ return nullptr;
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
if (MD->isDefaulted())
- return 0;
+ return nullptr;
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
@@ -1009,7 +1015,7 @@
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallExitEvent() const {
if (NoExit)
- return 0;
+ return nullptr;
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 8e1ea25..2585e54 100644
--- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -292,7 +292,7 @@
// ranges of the diagnostics.
FIDMap FM;
SmallVector<FileID, 10> Fids;
- const SourceManager* SM = 0;
+ const SourceManager* SM = nullptr;
if (!Diags.empty())
SM = &(*(*Diags.begin())->path.begin())->getLocation().getManager();
diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp
index 0bc510a..1714a27 100644
--- a/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -207,7 +207,7 @@
const StoreRef &newStore =
Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
- *IS, *ITraits, NULL, NULL);
+ *IS, *ITraits, nullptr, nullptr);
return makeWithStore(newStore);
}
@@ -387,7 +387,7 @@
if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
return I;
- ProgramState *newState = 0;
+ ProgramState *newState = nullptr;
if (!freeStates.empty()) {
newState = freeStates.back();
freeStates.pop_back();
diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 362b94f..77578d3 100644
--- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -45,7 +45,7 @@
return *second;
}
const llvm::APSInt *getConcreteValue() const {
- return &From() == &To() ? &From() : NULL;
+ return &From() == &To() ? &From() : nullptr;
}
void Profile(llvm::FoldingSetNodeID &ID) const {
@@ -98,7 +98,7 @@
/// constant then this method returns that value. Otherwise, it returns
/// NULL.
const llvm::APSInt* getConcreteValue() const {
- return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : 0;
+ return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : nullptr;
}
private:
@@ -336,7 +336,7 @@
const llvm::APSInt* RangeConstraintManager::getSymVal(ProgramStateRef St,
SymbolRef sym) const {
const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
- return T ? T->getConcreteValue() : NULL;
+ return T ? T->getConcreteValue() : nullptr;
}
ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
@@ -432,7 +432,7 @@
// [Int-Adjustment+1, Int-Adjustment-1]
// Notice that the lower bound is greater than the upper bound.
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -442,12 +442,12 @@
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
- return NULL;
+ return nullptr;
// [Int-Adjustment, Int-Adjustment]
llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -458,7 +458,7 @@
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return NULL;
+ return nullptr;
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
@@ -469,14 +469,14 @@
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Min = AdjustmentType.getMinValue();
if (ComparisonVal == Min)
- return NULL;
+ return nullptr;
llvm::APSInt Lower = Min-Adjustment;
llvm::APSInt Upper = ComparisonVal-Adjustment;
--Upper;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -491,21 +491,21 @@
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return NULL;
+ return nullptr;
}
// Special case for Int == Max. This is always false.
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Max = AdjustmentType.getMaxValue();
if (ComparisonVal == Max)
- return NULL;
+ return nullptr;
llvm::APSInt Lower = ComparisonVal-Adjustment;
llvm::APSInt Upper = Max-Adjustment;
++Lower;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -520,7 +520,7 @@
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return NULL;
+ return nullptr;
}
// Special case for Int == Min. This is always feasible.
@@ -534,7 +534,7 @@
llvm::APSInt Upper = Max-Adjustment;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -545,7 +545,7 @@
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return NULL;
+ return nullptr;
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
@@ -563,7 +563,7 @@
llvm::APSInt Upper = ComparisonVal-Adjustment;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
//===------------------------------------------------------------------------===
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index b811c67..3bbbb34 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -262,7 +262,7 @@
const SVal *RegionBindingsRef::lookup(BindingKey K) const {
const ClusterBindings *Cluster = lookup(K.getBaseRegion());
if (!Cluster)
- return 0;
+ return nullptr;
return Cluster->lookup(K);
}
@@ -1625,8 +1625,8 @@
// getBindingForField if 'R' has a direct binding.
// Lazy binding?
- Store lazyBindingStore = NULL;
- const SubRegion *lazyBindingRegion = NULL;
+ Store lazyBindingStore = nullptr;
+ const SubRegion *lazyBindingRegion = nullptr;
std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
if (lazyBindingRegion)
return getLazyBinding(lazyBindingRegion,
@@ -2291,7 +2291,7 @@
if (const SymbolicRegion *SR = *I) {
if (SymReaper.isLive(SR->getSymbol())) {
changed |= AddToWorkList(SR);
- *I = NULL;
+ *I = nullptr;
}
}
}
diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp
index 6506915..8de939f 100644
--- a/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/lib/StaticAnalyzer/Core/SVals.cpp
@@ -56,7 +56,7 @@
return FD;
}
- return 0;
+ return nullptr;
}
/// \brief If this SVal is a location (subclasses Loc) and wraps a symbol,
@@ -78,7 +78,7 @@
dyn_cast<SymbolicRegion>(R->StripCasts()))
return SymR->getSymbol();
}
- return 0;
+ return nullptr;
}
/// Get the symbol in the SVal or its base region.
@@ -86,7 +86,7 @@
Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
if (!X)
- return 0;
+ return nullptr;
const MemRegion *R = X->getRegion();
@@ -97,7 +97,7 @@
R = SR->getSuperRegion();
}
- return 0;
+ return nullptr;
}
// TODO: The next 3 functions have to be simplified.
@@ -139,12 +139,12 @@
if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
return X->getLoc().getAsRegion();
- return 0;
+ return nullptr;
}
const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
const MemRegion *R = getRegion();
- return R ? R->StripCasts(StripBaseCasts) : NULL;
+ return R ? R->StripCasts(StripBaseCasts) : nullptr;
}
const void *nonloc::LazyCompoundVal::getStore() const {
diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
index e6653ae..35930e4 100644
--- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
@@ -181,7 +181,7 @@
case nonloc::ConcreteIntKind: {
bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
bool isFeasible = b ? Assumption : !Assumption;
- return isFeasible ? state : NULL;
+ return isFeasible ? state : nullptr;
}
case nonloc::LocAsIntegerKind:
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index b488d3c..df9e4d6 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -817,7 +817,7 @@
RegionOffset LeftOffset = LeftMR->getAsOffset();
RegionOffset RightOffset = RightMR->getAsOffset();
- if (LeftOffset.getRegion() != NULL &&
+ if (LeftOffset.getRegion() != nullptr &&
LeftOffset.getRegion() == RightOffset.getRegion() &&
!LeftOffset.hasSymbolicOffset() && !RightOffset.hasSymbolicOffset()) {
int64_t left = LeftOffset.getOffset();
@@ -900,7 +900,7 @@
if (const MemRegion *region = lhs.getAsRegion()) {
rhs = convertToArrayIndex(rhs).castAs<NonLoc>();
SVal index = UnknownVal();
- const MemRegion *superR = 0;
+ const MemRegion *superR = nullptr;
QualType elementType;
if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
@@ -928,7 +928,7 @@
const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
SVal V) {
if (V.isUnknownOrUndef())
- return NULL;
+ return nullptr;
if (Optional<loc::ConcreteInt> X = V.getAs<loc::ConcreteInt>())
return &X->getValue();
@@ -940,5 +940,5 @@
return state->getConstraintManager().getSymVal(state, Sym);
// FIXME: Add support for SymExprs.
- return NULL;
+ return nullptr;
}
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp
index 0beb9db..e38be3e 100644
--- a/lib/StaticAnalyzer/Core/Store.cpp
+++ b/lib/StaticAnalyzer/Core/Store.cpp
@@ -88,7 +88,7 @@
// We don't know what to make of it. Return a NULL region, which
// will be interpretted as UnknownVal.
- return NULL;
+ return nullptr;
}
// Now assume we are casting from pointer to pointer. Other cases should
@@ -166,7 +166,7 @@
// If we cannot compute a raw offset, throw up our hands and return
// a NULL MemRegion*.
if (!baseR)
- return NULL;
+ return nullptr;
CharUnits off = rawOff.getOffset();
@@ -193,7 +193,7 @@
// Compute the index for the new ElementRegion.
int64_t newIndex = 0;
- const MemRegion *newSuperR = 0;
+ const MemRegion *newSuperR = nullptr;
// We can only compute sizeof(PointeeTy) if it is a complete type.
if (IsCompleteType(Ctx, PointeeTy)) {
@@ -300,7 +300,7 @@
return TVR->getValueType()->getAsCXXRecordDecl();
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
return SR->getSymbol()->getType()->getPointeeCXXRecordDecl();
- return 0;
+ return nullptr;
}
SVal StoreManager::evalDynamicCast(SVal Base, QualType TargetType,
@@ -401,7 +401,7 @@
return Base;
Loc BaseL = Base.castAs<Loc>();
- const MemRegion* BaseR = 0;
+ const MemRegion* BaseR = nullptr;
switch (BaseL.getSubKind()) {
case loc::MemRegionKind:
diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index a04cb41..cca0461 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -347,7 +347,7 @@
void SymbolManager::addSymbolDependency(const SymbolRef Primary,
const SymbolRef Dependent) {
SymbolDependTy::iterator I = SymbolDependencies.find(Primary);
- SymbolRefSmallVectorTy *dependencies = 0;
+ SymbolRefSmallVectorTy *dependencies = nullptr;
if (I == SymbolDependencies.end()) {
dependencies = new SymbolRefSmallVectorTy();
SymbolDependencies[Primary] = dependencies;
@@ -361,7 +361,7 @@
const SymbolRef Primary) {
SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
if (I == SymbolDependencies.end())
- return 0;
+ return nullptr;
return I->second;
}
@@ -487,7 +487,7 @@
bool
SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const {
- if (LCtx == 0)
+ if (LCtx == nullptr)
return false;
if (LCtx != ELCtx) {
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 563924d..ccaa8b6 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -11,8 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "AnalysisConsumer"
-
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DataRecursiveASTVisitor.h"
@@ -51,6 +49,8 @@
using namespace ento;
using llvm::SmallPtrSet;
+#define DEBUG_TYPE "AnalysisConsumer"
+
static ExplodedNode::Auditor* CreateUbiViz();
STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
@@ -185,8 +185,8 @@
const std::string& outdir,
AnalyzerOptionsRef opts,
ArrayRef<std::string> plugins)
- : RecVisitorMode(0), RecVisitorBR(0),
- Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins) {
+ : RecVisitorMode(0), RecVisitorBR(nullptr),
+ Ctx(nullptr), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins) {
DigestAnalyzerOptions();
if (Opts->PrintStats) {
llvm::EnableStatistics();
@@ -307,7 +307,7 @@
/// analyzed. This allows to redefine the default inlining policies when
/// analyzing a given function.
ExprEngine::InliningModes
- getInliningModeForFunction(const Decl *D, SetOfConstDecls Visited);
+ getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
/// \brief Build the call graph for all the top level decls of this TU and
/// use it to define the order in which the functions should be visited.
@@ -321,7 +321,7 @@
/// given root function.
void HandleCode(Decl *D, AnalysisMode Mode,
ExprEngine::InliningModes IMode = ExprEngine::Inline_Minimal,
- SetOfConstDecls *VisitedCallees = 0);
+ SetOfConstDecls *VisitedCallees = nullptr);
void RunPathSensitiveChecks(Decl *D,
ExprEngine::InliningModes IMode,
@@ -390,7 +390,7 @@
//===----------------------------------------------------------------------===//
// AnalysisConsumer implementation.
//===----------------------------------------------------------------------===//
-llvm::Timer* AnalysisConsumer::TUTotalTimer = 0;
+llvm::Timer* AnalysisConsumer::TUTotalTimer = nullptr;
bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
storeTopLevelDecls(DG);
@@ -414,8 +414,8 @@
}
static bool shouldSkipFunction(const Decl *D,
- SetOfConstDecls Visited,
- SetOfConstDecls VisitedAsTopLevel) {
+ const SetOfConstDecls &Visited,
+ const SetOfConstDecls &VisitedAsTopLevel) {
if (VisitedAsTopLevel.count(D))
return true;
@@ -435,7 +435,7 @@
ExprEngine::InliningModes
AnalysisConsumer::getInliningModeForFunction(const Decl *D,
- SetOfConstDecls Visited) {
+ const SetOfConstDecls &Visited) {
// We want to reanalyze all ObjC methods as top level to report Retain
// Count naming convention errors more aggressively. But we should tune down
// inlining when reanalyzing an already inlined function.
@@ -489,7 +489,7 @@
SetOfConstDecls VisitedCallees;
HandleCode(D, AM_Path, getInliningModeForFunction(D, Visited),
- (Mgr->options.InliningMode == All ? 0 : &VisitedCallees));
+ (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees));
// Add the visited callees to the global visited set.
for (SetOfConstDecls::iterator I = VisitedCallees.begin(),
@@ -539,14 +539,14 @@
// After all decls handled, run checkers on the entire TranslationUnit.
checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
- RecVisitorBR = 0;
+ RecVisitorBR = nullptr;
}
// Explicitly destroy the PathDiagnosticConsumer. This will flush its output.
// FIXME: This should be replaced with something that doesn't rely on
// side-effects in PathDiagnosticConsumer's destructor. This is required when
// used with option -disable-free.
- Mgr.reset(NULL);
+ Mgr.reset(nullptr);
if (TUTotalTimer) TUTotalTimer->stopTimer();
@@ -653,7 +653,7 @@
// Release the auditor (if any) so that it doesn't monitor the graph
// created BugReporter.
- ExplodedNode::SetAuditor(0);
+ ExplodedNode::SetAuditor(nullptr);
// Visualize the exploded graph.
if (Mgr->options.visualizeExplodedGraphWithGraphViz)
@@ -776,16 +776,17 @@
}
UbigraphViz::~UbigraphViz() {
- Out.reset(0);
+ Out.reset(nullptr);
llvm::errs() << "Running 'ubiviz' program... ";
std::string ErrMsg;
std::string Ubiviz = llvm::sys::FindProgramByName("ubiviz");
std::vector<const char*> args;
args.push_back(Ubiviz.c_str());
args.push_back(Filename.c_str());
- args.push_back(0);
+ args.push_back(nullptr);
- if (llvm::sys::ExecuteAndWait(Ubiviz, &args[0], 0, 0, 0, 0, &ErrMsg)) {
+ if (llvm::sys::ExecuteAndWait(Ubiviz, &args[0], nullptr, nullptr, 0, 0,
+ &ErrMsg)) {
llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
}
diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index d9d5bae..e2577c3 100644
--- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -40,7 +40,7 @@
public:
ClangCheckerRegistry(ArrayRef<std::string> plugins,
- DiagnosticsEngine *diags = 0);
+ DiagnosticsEngine *diags = nullptr);
};
} // end anonymous namespace
@@ -73,7 +73,7 @@
bool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) {
// If the version string is null, it's not an analyzer plugin.
- if (versionString == 0)
+ if (!versionString)
return false;
// For now, none of the static analyzer API is considered stable.
diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp
index b513446..94bdc8d 100644
--- a/lib/Tooling/CompilationDatabase.cpp
+++ b/lib/Tooling/CompilationDatabase.cpp
@@ -14,6 +14,7 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -51,7 +52,7 @@
ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
}
ErrorMessage = ErrorStream.str();
- return NULL;
+ return nullptr;
}
static CompilationDatabase *
@@ -75,7 +76,7 @@
Directory = llvm::sys::path::parent_path(Directory);
}
ErrorMessage = ErrorStream.str();
- return NULL;
+ return nullptr;
}
CompilationDatabase *
@@ -150,7 +151,7 @@
// options.
class UnusedInputDiagConsumer : public DiagnosticConsumer {
public:
- UnusedInputDiagConsumer() : Other(0) {}
+ UnusedInputDiagConsumer() : Other(nullptr) {}
// Useful for debugging, chain diagnostics to another consumer after
// recording for our own purposes.
@@ -211,11 +212,11 @@
IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
&*DiagOpts, &DiagClient, false);
- // Neither clang executable nor default image name are required since the
- // jobs the driver builds will not be executed.
+ // The clang executable path isn't required since the jobs the driver builds
+ // will not be executed.
std::unique_ptr<driver::Driver> NewDriver(new driver::Driver(
/* ClangExecutable= */ "", llvm::sys::getDefaultTargetTriple(),
- /* DefaultImageName= */ "", Diagnostics));
+ Diagnostics));
NewDriver->setCheckInputsExist(false);
// This becomes the new argv[0]. The value is actually not important as it
@@ -238,8 +239,9 @@
// Remove -no-integrated-as; it's not used for syntax checking,
// and it confuses targets which don't support this option.
- std::remove_if(Args.begin(), Args.end(),
- MatchesAny(std::string("-no-integrated-as")));
+ Args.erase(std::remove_if(Args.begin(), Args.end(),
+ MatchesAny(std::string("-no-integrated-as"))),
+ Args.end());
const std::unique_ptr<driver::Compilation> Compilation(
NewDriver->BuildCompilation(Args));
@@ -288,13 +290,13 @@
Twine Directory) {
const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
if (DoubleDash == Argv + Argc)
- return NULL;
+ return nullptr;
std::vector<const char *> CommandLine(DoubleDash + 1, Argv + Argc);
Argc = DoubleDash - Argv;
std::vector<std::string> StrippedArgs;
if (!stripPositionalArgs(CommandLine, StrippedArgs))
- return 0;
+ return nullptr;
return new FixedCompilationDatabase(Directory, StrippedArgs);
}
diff --git a/lib/Tooling/JSONCompilationDatabase.cpp b/lib/Tooling/JSONCompilationDatabase.cpp
index 5fe0980..bba71f2 100644
--- a/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/lib/Tooling/JSONCompilationDatabase.cpp
@@ -125,7 +125,7 @@
std::unique_ptr<CompilationDatabase> Database(
JSONCompilationDatabase::loadFromFile(JSONDatabasePath, ErrorMessage));
if (!Database)
- return NULL;
+ return nullptr;
return Database.release();
}
};
@@ -147,14 +147,14 @@
std::unique_ptr<llvm::MemoryBuffer> DatabaseBuffer;
llvm::error_code Result =
llvm::MemoryBuffer::getFile(FilePath, DatabaseBuffer);
- if (Result != 0) {
+ if (Result != nullptr) {
ErrorMessage = "Error while opening JSON database: " + Result.message();
- return NULL;
+ return nullptr;
}
std::unique_ptr<JSONCompilationDatabase> Database(
new JSONCompilationDatabase(DatabaseBuffer.release()));
if (!Database->parse(ErrorMessage))
- return NULL;
+ return nullptr;
return Database.release();
}
@@ -166,7 +166,7 @@
std::unique_ptr<JSONCompilationDatabase> Database(
new JSONCompilationDatabase(DatabaseBuffer.release()));
if (!Database->parse(ErrorMessage))
- return NULL;
+ return nullptr;
return Database.release();
}
@@ -235,12 +235,12 @@
return false;
}
llvm::yaml::Node *Root = I->getRoot();
- if (Root == NULL) {
+ if (!Root) {
ErrorMessage = "Error while parsing YAML.";
return false;
}
llvm::yaml::SequenceNode *Array = dyn_cast<llvm::yaml::SequenceNode>(Root);
- if (Array == NULL) {
+ if (!Array) {
ErrorMessage = "Expected array.";
return false;
}
@@ -248,30 +248,30 @@
AE = Array->end();
AI != AE; ++AI) {
llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&*AI);
- if (Object == NULL) {
+ if (!Object) {
ErrorMessage = "Expected object.";
return false;
}
- llvm::yaml::ScalarNode *Directory = NULL;
- llvm::yaml::ScalarNode *Command = NULL;
- llvm::yaml::ScalarNode *File = NULL;
+ llvm::yaml::ScalarNode *Directory = nullptr;
+ llvm::yaml::ScalarNode *Command = nullptr;
+ llvm::yaml::ScalarNode *File = nullptr;
for (llvm::yaml::MappingNode::iterator KVI = Object->begin(),
KVE = Object->end();
KVI != KVE; ++KVI) {
llvm::yaml::Node *Value = (*KVI).getValue();
- if (Value == NULL) {
+ if (!Value) {
ErrorMessage = "Expected value.";
return false;
}
llvm::yaml::ScalarNode *ValueString =
dyn_cast<llvm::yaml::ScalarNode>(Value);
- if (ValueString == NULL) {
+ if (!ValueString) {
ErrorMessage = "Expected string as value.";
return false;
}
llvm::yaml::ScalarNode *KeyString =
dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey());
- if (KeyString == NULL) {
+ if (!KeyString) {
ErrorMessage = "Expected strings as key.";
return false;
}
diff --git a/lib/Tooling/Refactoring.cpp b/lib/Tooling/Refactoring.cpp
index df9600e..4b4056b 100644
--- a/lib/Tooling/Refactoring.cpp
+++ b/lib/Tooling/Refactoring.cpp
@@ -53,7 +53,7 @@
bool Replacement::apply(Rewriter &Rewrite) const {
SourceManager &SM = Rewrite.getSourceMgr();
const FileEntry *Entry = SM.getFileManager().getFile(FilePath);
- if (Entry == NULL)
+ if (!Entry)
return false;
FileID ID;
// FIXME: Use SM.translateFile directly.
@@ -106,7 +106,7 @@
const std::pair<FileID, unsigned> DecomposedLocation =
Sources.getDecomposedLoc(Start);
const FileEntry *Entry = Sources.getFileEntryForID(DecomposedLocation.first);
- if (Entry != NULL) {
+ if (Entry) {
// Make FilePath absolute so replacements can be applied correctly when
// relative paths for files are used.
llvm::SmallString<256> FilePath(Entry->getName());
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index 7425e3b..35e3eb4 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -38,6 +38,8 @@
# include <unistd.h>
#endif
+#define DEBUG_TYPE "clang-tooling"
+
namespace clang {
namespace tooling {
@@ -52,10 +54,8 @@
/// \brief Builds a clang driver initialized for running clang tools.
static clang::driver::Driver *newDriver(clang::DiagnosticsEngine *Diagnostics,
const char *BinaryName) {
- const char *DefaultOutputName = "a.out";
clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
- BinaryName, llvm::sys::getDefaultTargetTriple(),
- DefaultOutputName, *Diagnostics);
+ BinaryName, llvm::sys::getDefaultTargetTriple(), *Diagnostics);
CompilerDriver->setTitle("clang_based_tool");
return CompilerDriver;
}
@@ -75,7 +75,7 @@
Jobs.Print(error_stream, "; ", true);
Diagnostics->Report(clang::diag::err_fe_expected_compiler_job)
<< error_stream.str();
- return NULL;
+ return nullptr;
}
// The one job we find should be to invoke clang again.
@@ -83,7 +83,7 @@
cast<clang::driver::Command>(*Jobs.begin());
if (StringRef(Cmd->getCreator().getName()) != "clang") {
Diagnostics->Report(clang::diag::err_fe_expected_clang_command);
- return NULL;
+ return nullptr;
}
return &Cmd->getArguments();
@@ -171,7 +171,7 @@
Action(Action),
OwnsAction(false),
Files(Files),
- DiagConsumer(NULL) {}
+ DiagConsumer(nullptr) {}
ToolInvocation::ToolInvocation(std::vector<std::string> CommandLine,
FrontendAction *FAction, FileManager *Files)
@@ -179,7 +179,7 @@
Action(new SingleFrontendActionFactory(FAction)),
OwnsAction(true),
Files(Files),
- DiagConsumer(NULL) {}
+ DiagConsumer(nullptr) {}
ToolInvocation::~ToolInvocation() {
if (OwnsAction)
@@ -216,7 +216,7 @@
Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
&Diagnostics, Compilation.get());
- if (CC1Args == NULL) {
+ if (!CC1Args) {
return false;
}
std::unique_ptr<clang::CompilerInvocation> Invocation(
@@ -256,7 +256,7 @@
// pass it to an std::unique_ptr declared after the Compiler variable.
std::unique_ptr<FrontendAction> ScopedToolAction(create());
- // Create the compilers actual diagnostics engine.
+ // Create the compiler's actual diagnostics engine.
Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!Compiler.hasDiagnostics())
return false;
@@ -271,7 +271,7 @@
ClangTool::ClangTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths)
- : Files(new FileManager(FileSystemOptions())), DiagConsumer(NULL) {
+ : Files(new FileManager(FileSystemOptions())), DiagConsumer(nullptr) {
ArgsAdjusters.push_back(new ClangStripOutputAdjuster());
ArgsAdjusters.push_back(new ClangSyntaxOnlyAdjuster());
for (const auto &SourcePath : SourcePaths) {
@@ -290,7 +290,7 @@
// about the .cc files that were not found, and the use case where I
// specify all files I want to run over explicitly, where this should
// be an error. We'll want to add an option for this.
- llvm::outs() << "Skipping " << File << ". Command line not found.\n";
+ llvm::errs() << "Skipping " << File << ". Compile command not found.\n";
}
}
}
@@ -369,55 +369,58 @@
namespace {
class ASTBuilderAction : public ToolAction {
- std::vector<ASTUnit *> &ASTs;
+ std::vector<std::unique_ptr<ASTUnit>> &ASTs;
public:
- ASTBuilderAction(std::vector<ASTUnit *> &ASTs) : ASTs(ASTs) {}
+ ASTBuilderAction(std::vector<std::unique_ptr<ASTUnit>> &ASTs) : ASTs(ASTs) {}
bool runInvocation(CompilerInvocation *Invocation, FileManager *Files,
DiagnosticConsumer *DiagConsumer) override {
// FIXME: This should use the provided FileManager.
- ASTUnit *AST = ASTUnit::LoadFromCompilerInvocation(
+ std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
Invocation, CompilerInstance::createDiagnostics(
&Invocation->getDiagnosticOpts(), DiagConsumer,
/*ShouldOwnClient=*/false));
if (!AST)
return false;
- ASTs.push_back(AST);
+ ASTs.push_back(std::move(AST));
return true;
}
};
}
-int ClangTool::buildASTs(std::vector<ASTUnit *> &ASTs) {
+int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
ASTBuilderAction Action(ASTs);
return run(&Action);
}
-ASTUnit *buildASTFromCode(const Twine &Code, const Twine &FileName) {
+std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code,
+ const Twine &FileName) {
return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName);
}
-ASTUnit *buildASTFromCodeWithArgs(const Twine &Code,
- const std::vector<std::string> &Args,
- const Twine &FileName) {
+std::unique_ptr<ASTUnit>
+buildASTFromCodeWithArgs(const Twine &Code,
+ const std::vector<std::string> &Args,
+ const Twine &FileName) {
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
- std::vector<ASTUnit *> ASTs;
+ std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
- ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action, 0);
+ ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action,
+ nullptr);
SmallString<1024> CodeStorage;
Invocation.mapVirtualFile(FileNameRef,
Code.toNullTerminatedStringRef(CodeStorage));
if (!Invocation.run())
- return 0;
+ return nullptr;
assert(ASTs.size() == 1);
- return ASTs[0];
+ return std::move(ASTs[0]);
}
} // end namespace tooling