diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/Decl.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/Decl.cpp | 762 |
1 files changed, 446 insertions, 316 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 6bd9858..7448de2 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -13,6 +13,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" @@ -29,7 +30,6 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/type_traits.h" #include <algorithm> using namespace clang; @@ -158,8 +158,7 @@ static bool usesTypeVisibility(const NamedDecl *D) { /// Does the given declaration have member specialization information, /// and if so, is it an explicit specialization? template <class T> static typename -llvm::enable_if_c<!llvm::is_base_of<RedeclarableTemplateDecl, T>::value, - bool>::type +std::enable_if<!std::is_base_of<RedeclarableTemplateDecl, T>::value, bool>::type isExplicitMemberSpecialization(const T *D) { if (const MemberSpecializationInfo *member = D->getMemberSpecializationInfo()) { @@ -209,11 +208,8 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D, // If we're on Mac OS X, an 'availability' for Mac OS X attribute // implies visibility(default). if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) { - for (specific_attr_iterator<AvailabilityAttr> - A = D->specific_attr_begin<AvailabilityAttr>(), - AEnd = D->specific_attr_end<AvailabilityAttr>(); - A != AEnd; ++A) - if ((*A)->getPlatform()->getName().equals("macosx")) + for (const auto *A : D->specific_attrs<AvailabilityAttr>()) + if (A->getPlatform()->getName().equals("macosx")) return DefaultVisibility; } @@ -231,23 +227,21 @@ getLVForType(const Type &T, LVComputationKind computation) { /// 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()) { @@ -267,7 +261,7 @@ getLVForTemplateParameterList(const TemplateParameterList *params, // 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()) { @@ -292,7 +286,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, 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)) @@ -307,43 +301,41 @@ static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { /// /// 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"); @@ -479,6 +471,58 @@ static void mergeTemplateLV(LinkageInfo &LV, LV.mergeExternalVisibility(argsLV); } +/// Should we consider visibility associated with the template +/// arguments and parameters of the given variable template +/// specialization? As usual, follow class template specialization +/// logic up to initialization. +static bool shouldConsiderTemplateVisibility( + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility (and note that implicit + // instantiations won't have a direct attribute). + if (!spec->isExplicitInstantiationOrSpecialization()) + return true; + + // An explicit variable specialization is an independent, top-level + // declaration. As such, if it has an explicit visibility attribute, + // that must directly express the user's intent, and we should honor + // it. + if (spec->isExplicitSpecialization() && + hasExplicitVisibilityAlready(computation)) + return false; + + return !hasDirectVisibilityAttribute(spec, computation); +} + +/// Merge in template-related linkage and visibility for the given +/// variable template specialization. As usual, follow class template +/// specialization logic up to initialization. +static void mergeTemplateLV(LinkageInfo &LV, + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { + bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); + + // Merge information from the template parameters, but ignore + // visibility if we're only considering template arguments. + + VarTemplateDecl *temp = spec->getSpecializedTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(tempLV, + considerVisibility && !hasExplicitVisibilityAlready(computation)); + + // Merge information from the template arguments. We ignore + // template-argument visibility if we've got an explicit + // instantiation with a visibility attribute. + const TemplateArgumentList &templateArgs = spec->getTemplateArgs(); + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); + if (considerVisibility) + LV.mergeVisibility(argsLV); + LV.mergeExternalVisibility(argsLV); +} + static bool useInlineVisibilityHidden(const NamedDecl *D) { // FIXME: we should warn if -fvisibility-inlines-hidden is used with c. const LangOptions &Opts = D->getASTContext().getLangOpts(); @@ -498,7 +542,7 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) { 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. @@ -512,9 +556,9 @@ template <typename T> static bool isFirstInExternCContext(T *D) { return First->isInExternCContext(); } -static bool isSingleLineExternC(const Decl &D) { +static bool isSingleLineLanguageLinkage(const Decl &D) { if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext())) - if (SD->getLanguage() == LinkageSpecDecl::lang_c && !SD->hasBraces()) + if (!SD->hasBraces()) return true; return false; } @@ -548,7 +592,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && - !isSingleLineExternC(*Var)) + !isSingleLineLanguageLinkage(*Var)) return LinkageInfo::internal(); } @@ -561,16 +605,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (PrevVar->getStorageClass() == SC_Static) return LinkageInfo::internal(); } - } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { + } else if (const FunctionDecl *Function = D->getAsFunction()) { // C++ [temp]p4: // A non-member function template can have internal linkage; any // other template name shall have external linkage. - const FunctionDecl *Function = 0; - if (const FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(D)) - Function = FunTmpl->getTemplatedDecl(); - else - Function = cast<FunctionDecl>(D); // Explicitly declared static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) @@ -676,6 +714,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // C99 6.2.2p4 and propagating the visibility attribute, so we don't have // to do it here. + // As per function and class template specializations (below), + // consider LV for the template and template arguments. We're at file + // scope, so we do not need to worry about nested specializations. + if (const VarTemplateSpecializationDecl *spec + = dyn_cast<VarTemplateSpecializationDecl>(Var)) { + mergeTemplateLV(LV, spec, computation); + } + // - a function, unless it has internal linkage; or } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // In theory, we can modify the function's LV by the LV of its @@ -782,11 +828,18 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // really have linkage, but it's convenient to say they do for the // purposes of calculating linkage of pointer-to-data-member // template arguments. + // + // Templates also don't officially have linkage, but since we ignore + // the C++ standard and look at template arguments when determining + // linkage and visibility of a template specialization, we might hit + // a template template argument that way. If we do, we need to + // consider its linkage. if (!(isa<CXXMethodDecl>(D) || isa<VarDecl>(D) || isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || - isa<TagDecl>(D))) + isa<TagDecl>(D) || + isa<TemplateDecl>(D))) return LinkageInfo::none(); LinkageInfo LV; @@ -825,7 +878,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // 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 @@ -876,6 +929,10 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // Static data members. } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (const VarTemplateSpecializationDecl *spec + = dyn_cast<VarTemplateSpecializationDecl>(VD)) + mergeTemplateLV(LV, spec, computation); + // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. LinkageInfo typeLV = getLVForType(*VD->getType(), computation); @@ -989,6 +1046,10 @@ getExplicitVisibilityAux(const NamedDecl *ND, 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. @@ -1242,16 +1303,13 @@ public: // 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; - for (NamedDecl::redecl_iterator I = D->redecls_begin(), - E = D->redecls_end(); - I != E; ++I) { - NamedDecl *T = cast<NamedDecl>(*I); + // computed also does. + NamedDecl *Old = nullptr; + for (auto I : D->redecls()) { + NamedDecl *T = cast<NamedDecl>(I); if (T == D) continue; - if (T->hasCachedLinkage()) { + if (!T->isInvalidDecl() && T->hasCachedLinkage()) { Old = T; break; } @@ -1270,13 +1328,9 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, } std::string NamedDecl::getQualifiedNameAsString() const { - return getQualifiedNameAsString(getASTContext().getPrintingPolicy()); -} - -std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { std::string QualName; llvm::raw_string_ostream OS(QualName); - printQualifiedName(OS, P); + printQualifiedName(OS, getASTContext().getPrintingPolicy()); return OS.str(); } @@ -1313,17 +1367,20 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, TemplateArgs.size(), P); } else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) { + if (P.SuppressUnwrittenScope && + (ND->isAnonymousNamespace() || ND->isInline())) + continue; if (ND->isAnonymousNamespace()) - OS << "<anonymous namespace>"; + OS << "(anonymous namespace)"; else OS << *ND; } else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) { if (!RD->getIdentifier()) - OS << "<anonymous " << RD->getKindName() << '>'; + OS << "(anonymous " << RD->getKindName() << ')'; 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>()); @@ -1352,7 +1409,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, if (getDeclName()) OS << *this; else - OS << "<anonymous>"; + OS << "(anonymous)"; } void NamedDecl::getNameForDiagnostic(raw_ostream &OS, @@ -1392,6 +1449,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { if (isa<ObjCMethodDecl>(this)) return false; + // FIXME: Is this correct if one of the decls comes from an inline namespace? if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD)) return true; @@ -1418,14 +1476,19 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { // A typedef of an Objective-C class type can replace an Objective-C class // declaration or definition, and vice versa. + // FIXME: Is this correct if one of the decls comes from an inline namespace? if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) || (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD))) return true; - + // For non-function declarations, if the declarations are of the - // same kind then this must be a redeclaration, or semantic analysis - // would not have given us the new declaration. - return this->getKind() == OldD->getKind(); + // same kind and have the same parent then this must be a redeclaration, + // or semantic analysis would not have given us the new declaration. + // Note that inline namespaces can give us two declarations with the same + // name and kind in the same scope but different contexts. + return this->getKind() == OldD->getKind() && + this->getDeclContext()->getRedeclContext()->Equals( + OldD->getDeclContext()->getRedeclContext()); } bool NamedDecl::hasLinkage() const { @@ -1453,11 +1516,9 @@ bool NamedDecl::isCXXInstanceMember() const { if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D)) return true; - if (isa<CXXMethodDecl>(D)) - return cast<CXXMethodDecl>(D)->isInstance(); - if (isa<FunctionTemplateDecl>(D)) - return cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D) - ->getTemplatedDecl())->isInstance(); + if (const CXXMethodDecl *MD = + dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction())) + return MD->isInstance(); return false; } @@ -1574,7 +1635,9 @@ bool typeIsPostfix(clang::QualType QT) { SourceRange DeclaratorDecl::getSourceRange() const { SourceLocation RangeEnd = getLocation(); if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { - if (typeIsPostfix(TInfo->getType())) + // If the declaration has no name or the type extends past the name take the + // end location of the type. + if (!getDeclName() || typeIsPostfix(TInfo->getType())) RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); } return SourceRange(getOuterLocStart(), RangeEnd); @@ -1584,13 +1647,13 @@ void 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). @@ -1620,12 +1683,16 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { 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() { - assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); - assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); +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), + "ParmVarDeclBitfields too large!"); AllBits = 0; VarDeclBits.SClass = SC; // Everything else is implicitly initialized to false. @@ -1635,13 +1702,13 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, SourceLocation IdL, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S) { - return new (C) 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) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarDecl)); - return new (Mem) 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) { @@ -1649,6 +1716,21 @@ void VarDecl::setStorageClass(StorageClass SC) { 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(); @@ -1661,7 +1743,7 @@ SourceRange VarDecl::getSourceRange() const { } template<typename T> -static LanguageLinkage getLanguageLinkageTemplate(const T &D) { +static LanguageLinkage getDeclLanguageLinkage(const T &D) { // C++ [dcl.link]p1: All function types, function names with external linkage, // and variable names with external linkage have a language linkage. if (!D.hasExternalFormalLinkage()) @@ -1689,7 +1771,7 @@ static LanguageLinkage getLanguageLinkageTemplate(const T &D) { } template<typename T> -static bool isExternCTemplate(const T &D) { +static bool isDeclExternC(const T &D) { // Since the context is ignored for class members, they can only have C++ // language linkage or no language linkage. const DeclContext *DC = D.getDeclContext(); @@ -1702,11 +1784,11 @@ static bool isExternCTemplate(const T &D) { } LanguageLinkage VarDecl::getLanguageLinkage() const { - return getLanguageLinkageTemplate(*this); + return getDeclLanguageLinkage(*this); } bool VarDecl::isExternC() const { - return isExternCTemplate(*this); + return isDeclExternC(*this); } bool VarDecl::isInExternCContext() const { @@ -1775,7 +1857,7 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( // A declaration directly contained in a linkage-specification is treated // as if it contains the extern specifier for the purpose of determining // the linkage of the declared name and whether it is a definition. - if (isSingleLineExternC(*this)) + if (isSingleLineLanguageLinkage(*this)) return DeclarationOnly; // C99 6.9.2p2: @@ -1794,38 +1876,35 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( VarDecl *VarDecl::getActingDefinition() { DefinitionKind Kind = isThisDeclarationADefinition(); if (Kind != TentativeDefinition) - return 0; + return nullptr; - VarDecl *LastTentative = 0; + VarDecl *LastTentative = nullptr; VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - Kind = (*I)->isThisDeclarationADefinition(); + for (auto I : First->redecls()) { + Kind = I->isThisDeclarationADefinition(); if (Kind == Definition) - return 0; + return nullptr; else if (Kind == TentativeDefinition) - LastTentative = *I; + LastTentative = I; } return LastTentative; } VarDecl *VarDecl::getDefinition(ASTContext &C) { VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - if ((*I)->isThisDeclarationADefinition(C) == Definition) - return *I; + for (auto I : First->redecls()) { + if (I->isThisDeclarationADefinition(C) == Definition) + return I; } - return 0; + return nullptr; } VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { DefinitionKind Kind = DeclarationOnly; const VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - Kind = std::max(Kind, (*I)->isThisDeclarationADefinition(C)); + for (auto I : First->redecls()) { + Kind = std::max(Kind, I->isThisDeclarationADefinition(C)); if (Kind == Definition) break; } @@ -1834,15 +1913,13 @@ VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { } const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const { - redecl_iterator I = redecls_begin(), E = redecls_end(); - while (I != E && !I->getInit()) - ++I; - - if (I != E) { - D = *I; - return I->getInit(); + for (auto I : redecls()) { + if (auto Expr = I->getInit()) { + D = I; + return Expr; + } } - return 0; + return nullptr; } bool VarDecl::isOutOfLine() const { @@ -1863,15 +1940,14 @@ bool VarDecl::isOutOfLine() const { VarDecl *VarDecl::getOutOfLineDefinition() { if (!isStaticDataMember()) - return 0; - - for (VarDecl::redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); - RD != RDEnd; ++RD) { + return nullptr; + + for (auto RD : redecls()) { if (RD->getLexicalDeclContext()->isFileContext()) - return *RD; + return RD; } - - return 0; + + return nullptr; } void VarDecl::setInit(Expr *I) { @@ -1948,7 +2024,7 @@ APValue *VarDecl::evaluateValue( // 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()); @@ -1957,7 +2033,7 @@ APValue *VarDecl::evaluateValue( // FIXME: Produce a diagnostic for self-initialization. Eval->CheckedICE = true; Eval->IsICE = false; - return 0; + return nullptr; } Eval->IsEvaluating = true; @@ -1983,7 +2059,7 @@ APValue *VarDecl::evaluateValue( Eval->IsICE = Result && Notes.empty(); } - return Result ? &Eval->Evaluated : 0; + return Result ? &Eval->Evaluated : nullptr; } bool VarDecl::checkInitIsICE() const { @@ -2025,8 +2101,8 @@ bool VarDecl::checkInitIsICE() const { VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return cast<VarDecl>(MSI->getInstantiatedFrom()); - - return 0; + + return nullptr; } TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { @@ -2066,7 +2142,7 @@ MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const { // return getASTContext().getInstantiatedFromStaticDataMember(this); return getASTContext().getTemplateOrSpecializationInfo(this) .dyn_cast<MemberSpecializationInfo *>(); - return 0; + return nullptr; } void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, @@ -2108,8 +2184,8 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) { - return new (C) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo, - S, DefArg); + return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo, + S, DefArg); } QualType ParmVarDecl::getOriginalType() const { @@ -2121,9 +2197,9 @@ QualType ParmVarDecl::getOriginalType() const { } ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl)); - return new (Mem) 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 { @@ -2196,9 +2272,9 @@ bool FunctionDecl::isVariadic() const { } bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + for (auto I : redecls()) { if (I->Body || I->IsLateTemplateParsed) { - Definition = *I; + Definition = I; return true; } } @@ -2221,10 +2297,10 @@ bool FunctionDecl::hasTrivialBody() const } bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + for (auto I : redecls()) { if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed || I->hasAttr<AliasAttr>()) { - Definition = I->IsDeleted ? I->getCanonicalDecl() : *I; + Definition = I->IsDeleted ? I->getCanonicalDecl() : I; return true; } } @@ -2234,12 +2310,12 @@ bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { 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) { @@ -2303,11 +2379,12 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { getDeclName().getCXXOverloadedOperator() == OO_Array_New || getDeclName().getCXXOverloadedOperator() == OO_Array_Delete); - if (isa<CXXRecordDecl>(getDeclContext())) return false; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return false; const FunctionProtoType *proto = getType()->castAs<FunctionProtoType>(); - if (proto->getNumArgs() != 2 || proto->isVariadic()) return false; + if (proto->getNumParams() != 2 || proto->isVariadic()) + return false; ASTContext &Context = cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()) @@ -2315,13 +2392,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { // The result type and first argument type are constant across all // these operators. The second argument must be exactly void*. - return (proto->getArgType(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(); + return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy); } bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { @@ -2335,20 +2406,23 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { if (isa<CXXRecordDecl>(getDeclContext())) return false; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + + // This can only fail for an invalid 'operator new' declaration. + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return false; const FunctionProtoType *FPT = getType()->castAs<FunctionProtoType>(); - if (FPT->getNumArgs() > 2 || FPT->isVariadic()) + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic()) return false; // If this is a single-parameter function, it must be a replaceable global // allocation or deallocation function. - if (FPT->getNumArgs() == 1) + if (FPT->getNumParams() == 1) return true; // Otherwise, we're looking for a second parameter whose type is // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'. - QualType Ty = FPT->getArgType(1); + QualType Ty = FPT->getParamType(1); ASTContext &Ctx = getASTContext(); if (Ctx.getLangOpts().SizedDeallocation && Ctx.hasSameType(Ty, Ctx.getSizeType())) @@ -2358,30 +2432,31 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { 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; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + return nullptr; + + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return nullptr; if (getNumParams() != 2 || isVariadic() || - !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getArgType(1), + !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. @@ -2391,15 +2466,15 @@ FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI)) if (FD->getNumParams() == 1 && !FD->isVariadic()) return FD; - return 0; + return nullptr; } LanguageLinkage FunctionDecl::getLanguageLinkage() const { - return getLanguageLinkageTemplate(*this); + return getDeclLanguageLinkage(*this); } bool FunctionDecl::isExternC() const { - return isExternCTemplate(*this); + return isDeclExternC(*this); } bool FunctionDecl::isInExternCContext() const { @@ -2442,7 +2517,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { FunctionTemplateDecl *PrevFunTmpl - = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; + = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr; assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); FunTmpl->setPreviousDecl(PrevFunTmpl); } @@ -2488,7 +2563,7 @@ unsigned FunctionDecl::getBuiltinID() const { // If the function is marked "overloadable", it has a different mangled name // and is not the C library function. - if (getAttr<OverloadableAttr>()) + if (hasAttr<OverloadableAttr>()) return 0; if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) @@ -2510,16 +2585,13 @@ unsigned FunctionDecl::getBuiltinID() const { /// based on its FunctionType. This is the length of the ParamInfo array /// after it has been created. unsigned FunctionDecl::getNumParams() const { - const FunctionType *FT = getType()->castAs<FunctionType>(); - if (isa<FunctionNoProtoType>(FT)) - return 0; - return cast<FunctionProtoType>(FT)->getNumArgs(); - + const FunctionProtoType *FPT = getType()->getAs<FunctionProtoType>(); + return FPT ? FPT->getNumParams() : 0; } 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. @@ -2536,44 +2608,67 @@ void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; std::copy(NewDecls.begin(), NewDecls.end(), A); DeclsInPrototypeScope = ArrayRef<NamedDecl *>(A, NewDecls.size()); + // Move declarations introduced in prototype to the function context. + for (auto I : NewDecls) { + DeclContext *DC = I->getDeclContext(); + // Forward-declared reference to an enumeration is not added to + // declaration scope, so skip declaration that is absent from its + // declaration contexts. + if (DC->containsDecl(I)) { + DC->removeDecl(I); + I->setDeclContext(this); + addDecl(I); + } + } } } /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default -/// arguments (in C++) or the last parameter is a parameter pack. +/// arguments (in C++) or are parameter packs (C++11). unsigned FunctionDecl::getMinRequiredArguments() const { if (!getASTContext().getLangOpts().CPlusPlus) return getNumParams(); - - unsigned NumRequiredArgs = getNumParams(); - - // If the last parameter is a parameter pack, we don't need an argument for - // it. - if (NumRequiredArgs > 0 && - getParamDecl(NumRequiredArgs - 1)->isParameterPack()) - --NumRequiredArgs; - - // If this parameter has a default argument, we don't need an argument for - // it. - while (NumRequiredArgs > 0 && - getParamDecl(NumRequiredArgs-1)->hasDefaultArg()) - --NumRequiredArgs; - - // We might have parameter packs before the end. These can't be deduced, - // but they can still handle multiple arguments. - unsigned ArgIdx = NumRequiredArgs; - while (ArgIdx > 0) { - if (getParamDecl(ArgIdx - 1)->isParameterPack()) - NumRequiredArgs = ArgIdx; - - --ArgIdx; - } - + + unsigned NumRequiredArgs = 0; + for (auto *Param : params()) + if (!Param->isParameterPack() && !Param->hasDefaultArg()) + ++NumRequiredArgs; return NumRequiredArgs; } +/// \brief The combination of the extern and inline keywords under MSVC forces +/// the function to be required. +/// +/// Note: This function assumes that we will only get called when isInlined() +/// would return true for this FunctionDecl. +bool FunctionDecl::isMSExternInline() const { + assert(isInlined() && "expected to get called on an inlined function!"); + + const ASTContext &Context = getASTContext(); + if (!Context.getLangOpts().MSVCCompat && !hasAttr<DLLExportAttr>()) + return false; + + for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDecl()) + if (FD->getStorageClass() == SC_Extern) + return true; + + return false; +} + +static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) { + if (Redecl->getStorageClass() != SC_Extern) + return false; + + for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD; + FD = FD->getPreviousDecl()) + if (FD->getStorageClass() == SC_Extern) + return false; + + return true; +} + static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { // Only consider file-scope declarations in this test. if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) @@ -2593,7 +2688,7 @@ static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { /// \brief For a function declaration in C or C++, determine whether this /// declaration causes the definition to be externally visible. /// -/// Specifically, this determines if adding the current declaration to the set +/// For instance, this determines if adding the current declaration to the set /// of redeclarations of the given functions causes /// isInlineDefinitionExternallyVisible to change from false to true. bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { @@ -2602,6 +2697,13 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { ASTContext &Context = getASTContext(); + if (Context.getLangOpts().MSVCCompat) { + const FunctionDecl *Definition; + if (hasBody(Definition) && Definition->isInlined() && + redeclForcesDefMSVC(this)) + return true; + } + if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) { // With GNU inlining, a declaration with 'inline' but not 'extern', forces // an externally visible definition. @@ -2649,6 +2751,26 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { return FoundBody; } +SourceRange FunctionDecl::getReturnTypeSourceRange() const { + const TypeSourceInfo *TSI = getTypeSourceInfo(); + if (!TSI) + return SourceRange(); + FunctionTypeLoc FTL = + TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>(); + if (!FTL) + return SourceRange(); + + // Skip self-referential return types. + const SourceManager &SM = getASTContext().getSourceManager(); + SourceRange RTRange = FTL.getReturnLoc().getSourceRange(); + SourceLocation Boundary = getNameInfo().getLocStart(); + if (RTRange.isInvalid() || Boundary.isInvalid() || + !SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary)) + return SourceRange(); + + return RTRange; +} + /// \brief For an inline function definition in C, or for a gnu_inline function /// in C++, determine whether the definition will be externally visible. /// @@ -2683,9 +2805,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // If any declaration is 'inline' but not 'extern', then this definition // is externally visible. - for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); - Redecl != RedeclEnd; - ++Redecl) { + for (auto Redecl : redecls()) { if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != SC_Extern) return true; @@ -2702,10 +2822,8 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // [...] If all of the file scope declarations for a function in a // translation unit include the inline function specifier without extern, // then the definition in that translation unit is an inline definition. - for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); - Redecl != RedeclEnd; - ++Redecl) { - if (RedeclForcesDefC99(*Redecl)) + for (auto Redecl : redecls()) { + if (RedeclForcesDefC99(Redecl)) return true; } @@ -2731,7 +2849,7 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const { if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName) return getDeclName().getCXXLiteralIdentifier(); else - return 0; + return nullptr; } FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { @@ -2753,8 +2871,8 @@ FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) return cast<FunctionDecl>(Info->getInstantiatedFrom()); - - return 0; + + return nullptr; } void @@ -2784,7 +2902,7 @@ bool FunctionDecl::isImplicitlyInstantiable() const { // 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. @@ -2824,14 +2942,34 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) return getClassScopeSpecializationPattern(); - + + // If this is a generic lambda call operator specialization, its + // instantiation pattern is always its primary template's pattern + // even if its primary template was instantiated from another + // member template (which happens with nested generic lambdas). + // Since a lambda's call operator's body is transformed eagerly, + // we don't have to go hunting for a prototype definition template + // (i.e. instantiated-from-member-template) to use as an instantiation + // pattern. + + if (isGenericLambdaCallOperatorSpecialization( + dyn_cast<CXXMethodDecl>(this))) { + assert(getPrimaryTemplate() && "A generic lambda specialization must be " + "generated from a primary call operator " + "template"); + assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() && + "A generic lambda call operator template must always have a body - " + "even if instantiated from a prototype (i.e. as written) member " + "template"); + return getPrimaryTemplate()->getTemplatedDecl(); + } + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of // this template, we're done looking. if (Primary->isMemberSpecialization()) break; - Primary = Primary->getInstantiatedFromMemberTemplate(); } @@ -2847,7 +2985,7 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->Template.getPointer(); } - return 0; + return nullptr; } FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { @@ -2861,7 +2999,7 @@ FunctionDecl::getTemplateSpecializationArgs() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArguments; } - return 0; + return nullptr; } const ASTTemplateArgumentListInfo * @@ -2871,7 +3009,7 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArgumentsAsWritten; } - return 0; + return nullptr; } void @@ -3101,14 +3239,14 @@ FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle) { - return new (C) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, - BW, Mutable, InitStyle); + return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, + BW, Mutable, InitStyle); } FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FieldDecl)); - return new (Mem) 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 { @@ -3180,8 +3318,10 @@ TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); } void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { NamedDeclOrQualifier = TDD; - if (TypeForDecl) - assert(TypeForDecl->isLinkageValid()); + if (const Type *T = getTypeForDecl()) { + (void)T; + assert(T->isLinkageValid()); + } assert(isLinkageValid()); } @@ -3189,10 +3329,10 @@ void TagDecl::startDefinition() { IsBeingDefined = true; if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) { - struct CXXRecordDecl::DefinitionData *Data = + struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) - cast<CXXRecordDecl>(*I)->DefinitionData = Data; + for (auto I : redecls()) + cast<CXXRecordDecl>(I)->DefinitionData = Data; } } @@ -3224,12 +3364,11 @@ TagDecl *TagDecl::getDefinition() const { if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); - for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); - R != REnd; ++R) + for (auto R : redecls()) if (R->isCompleteDefinition()) - return *R; + return R; - return 0; + return nullptr; } void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { @@ -3244,7 +3383,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { getASTContext().Deallocate(getExtInfo()); - NamedDeclOrQualifier = (TypedefNameDecl*) 0; + NamedDeclOrQualifier = (TypedefNameDecl*)nullptr; } else getExtInfo()->QualifierLoc = QualifierLoc; @@ -3275,21 +3414,28 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed) { - EnumDecl *Enum = new (C) EnumDecl(DC, StartLoc, IdLoc, Id, PrevDecl, - IsScoped, IsScopedUsingClassTag, IsFixed); + EnumDecl *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl, + IsScoped, IsScopedUsingClassTag, + IsFixed); Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; C.getTypeDeclType(Enum, PrevDecl); return Enum; } EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumDecl)); - EnumDecl *Enum = new (Mem) 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; } +SourceRange EnumDecl::getIntegerTypeRange() const { + if (const TypeSourceInfo *TI = getIntegerTypeSourceInfo()) + return TI->getTypeLoc().getSourceRange(); + return SourceRange(); +} + void EnumDecl::completeDefinition(QualType NewType, QualType NewPromotionType, unsigned NumPositiveBits, @@ -3325,7 +3471,7 @@ EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const { if (SpecializationInfo) return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom()); - return 0; + return nullptr; } void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, @@ -3338,10 +3484,11 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, // 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; @@ -3353,8 +3500,8 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl* PrevDecl) { - RecordDecl* R = new (C) 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); @@ -3362,9 +3509,9 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, } RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(RecordDecl)); - RecordDecl *R = new (Mem) 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; } @@ -3427,7 +3574,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { if (Decls.empty()) return; - llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, + std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, /*FieldsAlreadyLoaded=*/false); } @@ -3436,7 +3583,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { //===----------------------------------------------------------------------===// 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()) { @@ -3454,7 +3601,7 @@ void BlockDecl::setCaptures(ASTContext &Context, if (begin == end) { NumCaptures = 0; - Captures = 0; + Captures = nullptr; return; } @@ -3469,10 +3616,9 @@ void BlockDecl::setCaptures(ASTContext &Context, } bool BlockDecl::capturesVariable(const VarDecl *variable) const { - for (capture_const_iterator - i = capture_begin(), e = capture_end(); i != e; ++i) + for (const auto &I : captures()) // Only auto vars can be captured, so no redeclaration worries. - if (i->getVariable() == variable) + if (I.getVariable() == variable) return true; return false; @@ -3489,33 +3635,33 @@ SourceRange BlockDecl::getSourceRange() const { void TranslationUnitDecl::anchor() { } TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { - return new (C) 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) 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) LabelDecl(DC, IdentL, II, 0, GnuLabelL); + return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL); } LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LabelDecl)); - return new (Mem) LabelDecl(0, SourceLocation(), 0, 0, SourceLocation()); + return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr, + SourceLocation()); } void ValueDecl::anchor() { } bool ValueDecl::isWeak() const { - for (attr_iterator I = attr_begin(), E = attr_end(); I != E; ++I) - if (isa<WeakAttr>(*I) || isa<WeakRefAttr>(*I)) + for (const auto *I : attrs()) + if (isa<WeakAttr>(I) || isa<WeakRefAttr>(I)) return true; return isWeakImported(); @@ -3527,13 +3673,13 @@ ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) { - return new (C) ImplicitParamDecl(DC, IdLoc, Id, Type); + return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type); } -ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, +ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ImplicitParamDecl)); - return new (Mem) ImplicitParamDecl(0, SourceLocation(), 0, QualType()); + return new (C, ID) ImplicitParamDecl(C, nullptr, SourceLocation(), nullptr, + QualType()); } FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, @@ -3541,66 +3687,53 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, - bool isInlineSpecified, + bool isInlineSpecified, bool hasWrittenPrototype, bool isConstexprSpecified) { - FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, - T, TInfo, SC, - isInlineSpecified, - isConstexprSpecified); + FunctionDecl *New = + 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) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionDecl)); - return new (Mem) FunctionDecl(Function, 0, SourceLocation(), - DeclarationNameInfo(), QualType(), 0, - SC_None, false, false); + return new (C, ID) FunctionDecl(Function, C, nullptr, SourceLocation(), + DeclarationNameInfo(), QualType(), nullptr, + SC_None, false, false); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { - return new (C) BlockDecl(DC, L); + return new (C, DC) BlockDecl(DC, L); } BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(BlockDecl)); - return new (Mem) BlockDecl(0, SourceLocation()); -} - -MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(MSPropertyDecl)); - return new (Mem) MSPropertyDecl(0, SourceLocation(), DeclarationName(), - QualType(), 0, SourceLocation(), - 0, 0); + return new (C, ID) BlockDecl(nullptr, SourceLocation()); } CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC, unsigned NumParams) { - unsigned Size = sizeof(CapturedDecl) + NumParams * sizeof(ImplicitParamDecl*); - return new (C.Allocate(Size)) CapturedDecl(DC, NumParams); + return new (C, DC, NumParams * sizeof(ImplicitParamDecl *)) + CapturedDecl(DC, NumParams); } CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID, - unsigned NumParams) { - unsigned Size = sizeof(CapturedDecl) + NumParams * sizeof(ImplicitParamDecl*); - void *Mem = AllocateDeserializedDecl(C, ID, Size); - return new (Mem) CapturedDecl(0, NumParams); + unsigned NumParams) { + return new (C, ID, NumParams * sizeof(ImplicitParamDecl *)) + CapturedDecl(nullptr, NumParams); } EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V) { - return new (C) EnumConstantDecl(CD, L, Id, T, E, V); + return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V); } EnumConstantDecl * EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumConstantDecl)); - return new (Mem) EnumConstantDecl(0, SourceLocation(), 0, QualType(), 0, - llvm::APSInt()); + return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr, + QualType(), nullptr, llvm::APSInt()); } void IndirectFieldDecl::anchor() { } @@ -3609,14 +3742,14 @@ IndirectFieldDecl * IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, NamedDecl **CH, unsigned CHS) { - return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS); + return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS); } IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(IndirectFieldDecl)); - return new (Mem) IndirectFieldDecl(0, SourceLocation(), DeclarationName(), - QualType(), 0, 0); + return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(), + DeclarationName(), QualType(), nullptr, + 0); } SourceRange EnumConstantDecl::getSourceRange() const { @@ -3631,26 +3764,26 @@ void TypeDecl::anchor() { } TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) { - return new (C) 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) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypedefDecl)); - return new (Mem) 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) TypeAliasDecl(DC, StartLoc, IdLoc, Id, TInfo); + return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo); } TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasDecl)); - return new (Mem) TypeAliasDecl(0, SourceLocation(), SourceLocation(), 0, 0); + return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr); } SourceRange TypedefDecl::getSourceRange() const { @@ -3675,24 +3808,23 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, StringLiteral *Str, SourceLocation AsmLoc, SourceLocation RParenLoc) { - return new (C) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); + return new (C, DC) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); } -FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, +FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FileScopeAsmDecl)); - return new (Mem) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation()); + return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(), + SourceLocation()); } void EmptyDecl::anchor() {} EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { - return new (C) EmptyDecl(DC, L); + return new (C, DC) EmptyDecl(DC, L); } EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EmptyDecl)); - return new (Mem) EmptyDecl(0, SourceLocation()); + return new (C, ID) EmptyDecl(nullptr, SourceLocation()); } //===----------------------------------------------------------------------===// @@ -3730,30 +3862,28 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, *reinterpret_cast<SourceLocation *>(this + 1) = EndLoc; } -ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, +ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs) { - void *Mem = C.Allocate(sizeof(ImportDecl) + - IdentifierLocs.size() * sizeof(SourceLocation)); - return new (Mem) ImportDecl(DC, StartLoc, Imported, IdentifierLocs); + return new (C, DC, IdentifierLocs.size() * sizeof(SourceLocation)) + ImportDecl(DC, StartLoc, Imported, IdentifierLocs); } -ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, +ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - Module *Imported, + Module *Imported, SourceLocation EndLoc) { - void *Mem = C.Allocate(sizeof(ImportDecl) + sizeof(SourceLocation)); - ImportDecl *Import = new (Mem) ImportDecl(DC, StartLoc, Imported, EndLoc); + ImportDecl *Import = + new (C, DC, sizeof(SourceLocation)) ImportDecl(DC, StartLoc, + Imported, EndLoc); Import->setImplicit(); return Import; } ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumLocations) { - void *Mem = AllocateDeserializedDecl(C, ID, - (sizeof(ImportDecl) + - NumLocations * sizeof(SourceLocation))); - return new (Mem) ImportDecl(EmptyShell()); + return new (C, ID, NumLocations * sizeof(SourceLocation)) + ImportDecl(EmptyShell()); } ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const { |