diff options
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r-- | lib/AST/Decl.cpp | 1305 |
1 files changed, 814 insertions, 491 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7b13755..bf807ae 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -12,23 +12,24 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Decl.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/TypeLoc.h" -#include "clang/AST/Stmt.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyPrinter.h" -#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Module.h" #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; @@ -37,17 +38,163 @@ using namespace clang; // NamedDecl Implementation //===----------------------------------------------------------------------===// -static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) { +// Visibility rules aren't rigorously externally specified, but here +// are the basic principles behind what we implement: +// +// 1. An explicit visibility attribute is generally a direct expression +// of the user's intent and should be honored. Only the innermost +// visibility attribute applies. If no visibility attribute applies, +// global visibility settings are considered. +// +// 2. There is one caveat to the above: on or in a template pattern, +// an explicit visibility attribute is just a default rule, and +// visibility can be decreased by the visibility of template +// arguments. But this, too, has an exception: an attribute on an +// explicit specialization or instantiation causes all the visibility +// restrictions of the template arguments to be ignored. +// +// 3. A variable that does not otherwise have explicit visibility can +// be restricted by the visibility of its type. +// +// 4. A visibility restriction is explicit if it comes from an +// attribute (or something like it), not a global visibility setting. +// When emitting a reference to an external symbol, visibility +// restrictions are ignored unless they are explicit. +// +// 5. When computing the visibility of a non-type, including a +// non-type member of a class, only non-type visibility restrictions +// are considered: the 'visibility' attribute, global value-visibility +// settings, and a few special cases like __private_extern. +// +// 6. When computing the visibility of a type, including a type member +// of a class, only type visibility restrictions are considered: +// the 'type_visibility' attribute and global type-visibility settings. +// However, a 'visibility' attribute counts as a 'type_visibility' +// attribute on any declaration that only has the former. +// +// The visibility of a "secondary" entity, like a template argument, +// is computed using the kind of that entity, not the kind of the +// primary entity for which we are computing visibility. For example, +// the visibility of a specialization of either of these templates: +// template <class T, bool (&compare)(T, X)> bool has_match(list<T>, X); +// template <class T, bool (&compare)(T, X)> class matcher; +// is restricted according to the type visibility of the argument 'T', +// the type visibility of 'bool(&)(T,X)', and the value visibility of +// the argument function 'compare'. That 'has_match' is a value +// and 'matcher' is a type only matters when looking for attributes +// and settings from the immediate context. + +const unsigned IgnoreExplicitVisibilityBit = 2; + +/// Kinds of LV computation. The linkage side of the computation is +/// always the same, but different things can change how visibility is +/// computed. +enum LVComputationKind { + /// Do an LV computation for, ultimately, a type. + /// Visibility may be restricted by type visibility settings and + /// the visibility of template arguments. + LVForType = NamedDecl::VisibilityForType, + + /// Do an LV computation for, ultimately, a non-type declaration. + /// Visibility may be restricted by value visibility settings and + /// the visibility of template arguments. + LVForValue = NamedDecl::VisibilityForValue, + + /// Do an LV computation for, ultimately, a type that already has + /// some sort of explicit visibility. Visibility may only be + /// restricted by the visibility of template arguments. + LVForExplicitType = (LVForType | IgnoreExplicitVisibilityBit), + + /// Do an LV computation for, ultimately, a non-type declaration + /// that already has some sort of explicit visibility. Visibility + /// may only be restricted by the visibility of template arguments. + LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit) +}; + +/// Does this computation kind permit us to consider additional +/// visibility settings from attributes and the like? +static bool hasExplicitVisibilityAlready(LVComputationKind computation) { + return ((unsigned(computation) & IgnoreExplicitVisibilityBit) != 0); +} + +/// Given an LVComputationKind, return one of the same type/value sort +/// that records that it already has explicit visibility. +static LVComputationKind +withExplicitVisibilityAlready(LVComputationKind oldKind) { + LVComputationKind newKind = + static_cast<LVComputationKind>(unsigned(oldKind) | + IgnoreExplicitVisibilityBit); + assert(oldKind != LVForType || newKind == LVForExplicitType); + assert(oldKind != LVForValue || newKind == LVForExplicitValue); + assert(oldKind != LVForExplicitType || newKind == LVForExplicitType); + assert(oldKind != LVForExplicitValue || newKind == LVForExplicitValue); + return newKind; +} + +static Optional<Visibility> getExplicitVisibility(const NamedDecl *D, + LVComputationKind kind) { + assert(!hasExplicitVisibilityAlready(kind) && + "asking for explicit visibility when we shouldn't be"); + return D->getExplicitVisibility((NamedDecl::ExplicitVisibilityKind) kind); +} + +/// Is the given declaration a "type" or a "value" for the purposes of +/// visibility computation? +static bool usesTypeVisibility(const NamedDecl *D) { + return isa<TypeDecl>(D) || + isa<ClassTemplateDecl>(D) || + isa<ObjCInterfaceDecl>(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 +isExplicitMemberSpecialization(const T *D) { + if (const MemberSpecializationInfo *member = + D->getMemberSpecializationInfo()) { + return member->isExplicitSpecialization(); + } + return false; +} + +/// For templates, this question is easier: a member template can't be +/// explicitly instantiated, so there's a single bit indicating whether +/// or not this is an explicit member specialization. +static bool isExplicitMemberSpecialization(const RedeclarableTemplateDecl *D) { + return D->isMemberSpecialization(); +} + +/// Given a visibility attribute, return the explicit visibility +/// associated with it. +template <class T> +static Visibility getVisibilityFromAttr(const T *attr) { + switch (attr->getVisibility()) { + case T::Default: + return DefaultVisibility; + case T::Hidden: + return HiddenVisibility; + case T::Protected: + return ProtectedVisibility; + } + llvm_unreachable("bad visibility kind"); +} + +/// Return the explicit visibility of the given declaration. +static Optional<Visibility> getVisibilityOf(const NamedDecl *D, + NamedDecl::ExplicitVisibilityKind kind) { + // If we're ultimately computing the visibility of a type, look for + // a 'type_visibility' attribute before looking for 'visibility'. + if (kind == NamedDecl::VisibilityForType) { + if (const TypeVisibilityAttr *A = D->getAttr<TypeVisibilityAttr>()) { + return getVisibilityFromAttr(A); + } + } + // If this declaration has an explicit visibility attribute, use it. if (const VisibilityAttr *A = D->getAttr<VisibilityAttr>()) { - switch (A->getVisibility()) { - case VisibilityAttr::Default: - return DefaultVisibility; - case VisibilityAttr::Hidden: - return HiddenVisibility; - case VisibilityAttr::Protected: - return ProtectedVisibility; - } + return getVisibilityFromAttr(A); } // If we're on Mac OS X, an 'availability' for Mac OS X attribute @@ -61,43 +208,61 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) { return DefaultVisibility; } - return llvm::Optional<Visibility>(); -} - -typedef NamedDecl::LinkageInfo LinkageInfo; - -static LinkageInfo getLVForType(QualType T) { - std::pair<Linkage,Visibility> P = T->getLinkageAndVisibility(); - return LinkageInfo(P.first, P.second, T->isVisibilityExplicit()); + return None; } /// \brief Get the most restrictive linkage for the types in the given -/// template parameter list. +/// template parameter list. For visibility purposes, template +/// parameters are part of the signature of a template. static LinkageInfo -getLVForTemplateParameterList(const TemplateParameterList *Params) { - LinkageInfo LV(ExternalLinkage, DefaultVisibility, false); - for (TemplateParameterList::const_iterator P = Params->begin(), - PEnd = Params->end(); +getLVForTemplateParameterList(const TemplateParameterList *params) { + LinkageInfo LV; + for (TemplateParameterList::const_iterator P = params->begin(), + PEnd = params->end(); P != PEnd; ++P) { + + // Template type parameters are the most common and never + // contribute to visibility, pack or not. + 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 (NTTP->isExpandedParameterPack()) { - for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) { - QualType T = NTTP->getExpansionType(I); - if (!T->isDependentType()) - LV.merge(getLVForType(T)); + // Handle the non-pack case first. + if (!NTTP->isExpandedParameterPack()) { + if (!NTTP->getType()->isDependentType()) { + LV.merge(NTTP->getType()->getLinkageAndVisibility()); } continue; } - if (!NTTP->getType()->isDependentType()) { - LV.merge(getLVForType(NTTP->getType())); - continue; + // Look at all the types in an expanded pack. + for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) { + QualType type = NTTP->getExpansionType(i); + if (!type->isDependentType()) + LV.merge(type->getLinkageAndVisibility()); } + continue; } - if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(*P)) { + // Template template parameters can be restricted by their + // template parameters, recursively. + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); + + // Handle the non-pack case first. + if (!TTP->isExpandedParameterPack()) { LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters())); + continue; + } + + // Look at all expansions in an expanded pack. + for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters(); + i != n; ++i) { + LV.merge(getLVForTemplateParameterList( + TTP->getExpansionTemplateParameters(i))); } } @@ -105,67 +270,177 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) { } /// getLVForDecl - Get the linkage and visibility for the given declaration. -static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate); +static LinkageInfo getLVForDecl(const NamedDecl *D, + LVComputationKind computation); /// \brief Get the most restrictive linkage for the types and /// declarations in the given template argument list. -static LinkageInfo getLVForTemplateArgumentList(const TemplateArgument *Args, - unsigned NumArgs, - bool OnlyTemplate) { - LinkageInfo LV(ExternalLinkage, DefaultVisibility, false); +/// +/// 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) { + LinkageInfo LV; - for (unsigned I = 0; I != NumArgs; ++I) { - switch (Args[I].getKind()) { + for (unsigned i = 0, e = args.size(); i != e; ++i) { + const TemplateArgument &arg = args[i]; + switch (arg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Expression: - break; + continue; case TemplateArgument::Type: - LV.mergeWithMin(getLVForType(Args[I].getAsType())); - break; + LV.merge(arg.getAsType()->getLinkageAndVisibility()); + continue; case TemplateArgument::Declaration: - if (NamedDecl *ND = dyn_cast<NamedDecl>(Args[I].getAsDecl())) - LV.mergeWithMin(getLVForDecl(ND, OnlyTemplate)); - break; + if (NamedDecl *ND = dyn_cast<NamedDecl>(arg.getAsDecl())) { + assert(!usesTypeVisibility(ND)); + LV.merge(getLVForDecl(ND, LVForValue)); + } + continue; case TemplateArgument::NullPtr: - LV.mergeWithMin(getLVForType(Args[I].getNullPtrType())); - break; + LV.merge(arg.getNullPtrType()->getLinkageAndVisibility()); + continue; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: if (TemplateDecl *Template - = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl()) - LV.mergeWithMin(getLVForDecl(Template, OnlyTemplate)); - break; + = arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) + LV.merge(getLVForDecl(Template, LVForValue)); + continue; case TemplateArgument::Pack: - LV.mergeWithMin(getLVForTemplateArgumentList(Args[I].pack_begin(), - Args[I].pack_size(), - OnlyTemplate)); - break; + LV.merge(getLVForTemplateArgumentList(arg.getPackAsArray())); + continue; } + llvm_unreachable("bad template argument kind"); } return LV; } static LinkageInfo -getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, - bool OnlyTemplate) { - return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), OnlyTemplate); +getLVForTemplateArgumentList(const TemplateArgumentList &TArgs) { + return getLVForTemplateArgumentList(TArgs.asArray()); } -static bool shouldConsiderTemplateVis(const FunctionDecl *fn, - const FunctionTemplateSpecializationInfo *spec) { - return !fn->hasAttr<VisibilityAttr>() || spec->isExplicitSpecialization(); +static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility. (Implicit instantiations won't + // have a direct attribute.) + if (!specInfo->isExplicitInstantiationOrSpecialization()) + return true; + + return !fn->hasAttr<VisibilityAttr>(); +} + +/// Merge in template-related linkage and visibility for the given +/// function template specialization. +/// +/// We don't need a computation kind here because we can assume +/// LVForValue. +/// +/// \param[out] LV the computation to use for the parent +static void +mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo) { + bool considerVisibility = + shouldConsiderTemplateVisibility(fn, specInfo); + + // Merge information from the template parameters. + FunctionTemplateDecl *temp = specInfo->getTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters()); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + + // Merge information from the template arguments. + const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs); + LV.mergeMaybeWithVisibility(argsLV, considerVisibility); +} + +/// Does the given declaration have a direct visibility attribute +/// that would match the given rules? +static bool hasDirectVisibilityAttribute(const NamedDecl *D, + LVComputationKind computation) { + switch (computation) { + case LVForType: + case LVForExplicitType: + if (D->hasAttr<TypeVisibilityAttr>()) + return true; + // fallthrough + case LVForValue: + case LVForExplicitValue: + if (D->hasAttr<VisibilityAttr>()) + return true; + return false; + } + llvm_unreachable("bad visibility computation kind"); +} + +/// Should we consider visibility associated with the template +/// arguments and parameters of the given class template specialization? +static bool shouldConsiderTemplateVisibility( + const ClassTemplateSpecializationDecl *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). + // + // Furthermore, we want to ignore template parameters and arguments + // for an explicit specialization when computing the visibility of a + // member thereof with explicit visibility. + // + // This is a bit complex; let's unpack it. + // + // An explicit class specialization is an independent, top-level + // declaration. As such, if it or any of its members has an + // explicit visibility attribute, that must directly express the + // user's intent, and we should honor it. The same logic applies to + // an explicit instantiation of a member of such a thing. + + // Fast path: if this is not an explicit instantiation or + // specialization, we always want to consider template-related + // visibility restrictions. + if (!spec->isExplicitInstantiationOrSpecialization()) + return true; + + // This is the 'member thereof' check. + if (spec->isExplicitSpecialization() && + hasExplicitVisibilityAlready(computation)) + return false; + + return !hasDirectVisibilityAttribute(spec, computation); } -static bool -shouldConsiderTemplateVis(const ClassTemplateSpecializationDecl *d) { - return !d->hasAttr<VisibilityAttr>() || d->isExplicitSpecialization(); +/// Merge in template-related linkage and visibility for the given +/// class template specialization. +static void mergeTemplateLV(LinkageInfo &LV, + const ClassTemplateSpecializationDecl *spec, + LVComputationKind computation) { + bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); + + // Merge information from the template parameters, but ignore + // visibility if we're only considering template arguments. + + ClassTemplateDecl *temp = spec->getSpecializedTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters()); + 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); + LV.mergeMaybeWithVisibility(argsLV, considerVisibility); } static bool useInlineVisibilityHidden(const NamedDecl *D) { @@ -196,8 +471,13 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) { FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>(); } +template <typename T> static bool isInExternCContext(T *D) { + const T *First = D->getFirstDeclaration(); + return First->getDeclContext()->isExternCContext(); +} + static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, - bool OnlyTemplate) { + LVComputationKind computation) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && "Not a name having namespace scope"); ASTContext &Context = D->getASTContext(); @@ -218,26 +498,24 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // declared to have external linkage; or (there is no equivalent in C99) if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && - !Var->getType().isVolatileQualified() && - Var->getStorageClass() != SC_Extern && - Var->getStorageClass() != SC_PrivateExtern) { - bool FoundExtern = false; - for (const VarDecl *PrevVar = Var->getPreviousDecl(); - PrevVar && !FoundExtern; - PrevVar = PrevVar->getPreviousDecl()) - if (isExternalLinkage(PrevVar->getLinkage())) - FoundExtern = true; - - if (!FoundExtern) - return LinkageInfo::internal(); - } - if (Var->getStorageClass() == SC_None) { + !Var->getType().isVolatileQualified()) { const VarDecl *PrevVar = Var->getPreviousDecl(); - for (; PrevVar; PrevVar = PrevVar->getPreviousDecl()) - if (PrevVar->getStorageClass() == SC_PrivateExtern) - break; if (PrevVar) return PrevVar->getLinkageAndVisibility(); + + if (Var->getStorageClass() != SC_Extern && + Var->getStorageClass() != SC_PrivateExtern) + return LinkageInfo::internal(); + } + + for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar; + PrevVar = PrevVar->getPreviousDecl()) { + if (PrevVar->getStorageClass() == SC_PrivateExtern && + Var->getStorageClass() == SC_None) + return PrevVar->getLinkageAndVisibility(); + // Explicitly declared static. + if (PrevVar->getStorageClass() == SC_Static) + return LinkageInfo::internal(); } } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { // C++ [temp]p4: @@ -251,7 +529,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, Function = cast<FunctionDecl>(D); // Explicitly declared static. - if (Function->getStorageClass() == SC_Static) + if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) return LinkageInfo(InternalLinkage, DefaultVisibility, false); } else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) { // - a data member of an anonymous union. @@ -262,8 +540,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (D->isInAnonymousNamespace()) { const VarDecl *Var = dyn_cast<VarDecl>(D); const FunctionDecl *Func = dyn_cast<FunctionDecl>(D); - if ((!Var || !Var->getDeclContext()->isExternCContext()) && - (!Func || !Func->getDeclContext()->isExternCContext())) + if ((!Var || !isInExternCContext(Var)) && + (!Func || !isInExternCContext(Func))) return LinkageInfo::uniqueExternal(); } @@ -275,31 +553,41 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // external. LinkageInfo LV; - if (!OnlyTemplate) { - if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) { + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) { LV.mergeVisibility(*Vis, true); } else { // If we're declared in a namespace with a visibility attribute, - // use that namespace's visibility, but don't call it explicit. + // use that namespace's visibility, and it still counts as explicit. for (const DeclContext *DC = D->getDeclContext(); !isa<TranslationUnitDecl>(DC); DC = DC->getParent()) { const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); if (!ND) continue; - if (llvm::Optional<Visibility> Vis = ND->getExplicitVisibility()) { + if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) { LV.mergeVisibility(*Vis, true); break; } } } - } - if (!OnlyTemplate) { - LV.mergeVisibility(Context.getLangOpts().getVisibilityMode()); - // If we're paying attention to global visibility, apply - // -finline-visibility-hidden if this is an inline method. - if (!LV.visibilityExplicit() && useInlineVisibilityHidden(D)) - LV.mergeVisibility(HiddenVisibility, true); + // Add in global settings if the above didn't give us direct visibility. + if (!LV.isVisibilityExplicit()) { + // Use global type/value visibility as appropriate. + Visibility globalVisibility; + if (computation == LVForValue) { + globalVisibility = Context.getLangOpts().getValueVisibilityMode(); + } else { + assert(computation == LVForType); + globalVisibility = Context.getLangOpts().getTypeVisibilityMode(); + } + LV.mergeVisibility(globalVisibility, /*explicit*/ false); + + // If we're paying attention to global visibility, apply + // -finline-visibility-hidden if this is an inline method. + if (useInlineVisibilityHidden(D)) + LV.mergeVisibility(HiddenVisibility, true); + } } // C++ [basic.link]p4: @@ -330,12 +618,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. - if (Context.getLangOpts().CPlusPlus && - !Var->getDeclContext()->isExternCContext()) { - LinkageInfo TypeLV = getLVForType(Var->getType()); - if (TypeLV.linkage() != ExternalLinkage) + if (Context.getLangOpts().CPlusPlus && !isInExternCContext(Var)) { + LinkageInfo TypeLV = Var->getType()->getLinkageAndVisibility(); + if (TypeLV.getLinkage() != ExternalLinkage) return LinkageInfo::uniqueExternal(); - LV.mergeVisibility(TypeLV); + if (!LV.isVisibilityExplicit()) + LV.mergeVisibility(TypeLV); } if (Var->getStorageClass() == SC_PrivateExtern) @@ -355,30 +643,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (Function->getStorageClass() == SC_PrivateExtern) LV.mergeVisibility(HiddenVisibility, true); - // C99 6.2.2p5: - // If the declaration of an identifier for a function has no - // storage-class specifier, its linkage is determined exactly - // as if it were declared with the storage-class specifier - // extern. - if (!Context.getLangOpts().CPlusPlus && - (Function->getStorageClass() == SC_Extern || - Function->getStorageClass() == SC_PrivateExtern || - Function->getStorageClass() == SC_None)) { - // C99 6.2.2p4: - // For an identifier declared with the storage-class specifier - // extern in a scope in which a prior declaration of that - // identifier is visible, if the prior declaration specifies - // internal or external linkage, the linkage of the identifier - // at the later declaration is the same as the linkage - // specified at the prior declaration. If no prior declaration - // is visible, or if the prior declaration specifies no - // linkage, then the identifier has external linkage. - if (const FunctionDecl *PrevFunc = Function->getPreviousDecl()) { - LinkageInfo PrevLV = getLVForDecl(PrevFunc, OnlyTemplate); - if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); - LV.mergeVisibility(PrevLV); - } - } + // Note that Sema::MergeCompatibleFunctionDecls already takes care of + // merging storage classes and visibility attributes, so we don't have to + // look at previous decls in here. // In C++, then if the type of the function uses a type with // unique-external linkage, it's not legally usable from outside @@ -389,21 +656,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, Function->getType()->getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); - // Consider LV from the template and the template arguments unless - // this is an explicit specialization with a visibility attribute. + // Consider LV from the template and the template arguments. + // We're at file scope, so we do not need to worry about nested + // specializations. if (FunctionTemplateSpecializationInfo *specInfo = Function->getTemplateSpecializationInfo()) { - LinkageInfo TempLV = getLVForDecl(specInfo->getTemplate(), true); - const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; - LinkageInfo ArgsLV = getLVForTemplateArgumentList(templateArgs, - OnlyTemplate); - if (shouldConsiderTemplateVis(Function, specInfo)) { - LV.mergeWithMin(TempLV); - LV.mergeWithMin(ArgsLV); - } else { - LV.mergeLinkage(TempLV); - LV.mergeLinkage(ArgsLV); - } + mergeTemplateLV(LV, Function, specInfo); } // - a named class (Clause 9), or an unnamed class defined in a @@ -414,41 +672,33 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // has the typedef name for linkage purposes (7.1.3); or } else if (const TagDecl *Tag = dyn_cast<TagDecl>(D)) { // Unnamed tags have no linkage. - if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) + if (!Tag->hasNameForLinkage()) return LinkageInfo::none(); // If this is a class template specialization, consider the - // linkage of the template and template arguments. + // linkage of the template and template arguments. We're at file + // scope, so we do not need to worry about nested specializations. if (const ClassTemplateSpecializationDecl *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) { - // From the template. - LinkageInfo TempLV = getLVForDecl(spec->getSpecializedTemplate(), true); - - // The arguments at which the template was instantiated. - const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); - LinkageInfo ArgsLV = getLVForTemplateArgumentList(TemplateArgs, - OnlyTemplate); - if (shouldConsiderTemplateVis(spec)) { - LV.mergeWithMin(TempLV); - LV.mergeWithMin(ArgsLV); - } else { - LV.mergeLinkage(TempLV); - LV.mergeLinkage(ArgsLV); - } + mergeTemplateLV(LV, spec, computation); } // - an enumerator belonging to an enumeration with external linkage; } else if (isa<EnumConstantDecl>(D)) { LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), - OnlyTemplate); - if (!isExternalLinkage(EnumLV.linkage())) + computation); + if (!isExternalLinkage(EnumLV.getLinkage())) return LinkageInfo::none(); LV.merge(EnumLV); // - a template, unless it is a function template that has // internal linkage (Clause 14); } else if (const TemplateDecl *temp = dyn_cast<TemplateDecl>(D)) { - LV.merge(getLVForTemplateParameterList(temp->getTemplateParameters())); + bool considerVisibility = !hasExplicitVisibilityAlready(computation); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters()); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + // - a namespace (7.3), unless it is declared within an unnamed // namespace. } else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) { @@ -466,13 +716,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // If we ended up with non-external linkage, visibility should // always be default. - if (LV.linkage() != ExternalLinkage) - return LinkageInfo(LV.linkage(), DefaultVisibility, false); + if (LV.getLinkage() != ExternalLinkage) + return LinkageInfo(LV.getLinkage(), DefaultVisibility, false); return LV; } -static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) { +static LinkageInfo getLVForClassMember(const NamedDecl *D, + LVComputationKind computation) { // Only certain class members have linkage. Note that fields don't // really have linkage, but it's convenient to say they do for the // purposes of calculating linkage of pointer-to-data-member @@ -480,46 +731,45 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) { if (!(isa<CXXMethodDecl>(D) || isa<VarDecl>(D) || isa<FieldDecl>(D) || - (isa<TagDecl>(D) && - (D->getDeclName() || cast<TagDecl>(D)->getTypedefNameForAnonDecl())))) + isa<TagDecl>(D))) return LinkageInfo::none(); LinkageInfo LV; // If we have an explicit visibility attribute, merge that in. - if (!OnlyTemplate) { - if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) LV.mergeVisibility(*Vis, true); // If we're paying attention to global visibility, apply // -finline-visibility-hidden if this is an inline method. // // Note that we do this before merging information about // the class visibility. - if (!LV.visibilityExplicit() && useInlineVisibilityHidden(D)) + if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D)) LV.mergeVisibility(HiddenVisibility, true); } // If this class member has an explicit visibility attribute, the only // thing that can change its visibility is the template arguments, so // only look for them when processing the class. - bool ClassOnlyTemplate = LV.visibilityExplicit() ? true : OnlyTemplate; - - // If this member has an visibility attribute, ClassF will exclude - // attributes on the class or command line options, keeping only information - // about the template instantiation. If the member has no visibility - // attributes, mergeWithMin behaves like merge, so in both cases mergeWithMin - // produces the desired result. - LV.mergeWithMin(getLVForDecl(cast<RecordDecl>(D->getDeclContext()), - ClassOnlyTemplate)); - if (!isExternalLinkage(LV.linkage())) + LVComputationKind classComputation = computation; + if (LV.isVisibilityExplicit()) + classComputation = withExplicitVisibilityAlready(computation); + + LinkageInfo classLV = + getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation); + if (!isExternalLinkage(classLV.getLinkage())) return LinkageInfo::none(); // If the class already has unique-external linkage, we can't improve. - if (LV.linkage() == UniqueExternalLinkage) + if (classLV.getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); - if (!OnlyTemplate) - LV.mergeVisibility(D->getASTContext().getLangOpts().getVisibilityMode()); + // Otherwise, don't merge in classLV yet, because in certain cases + // we need to completely ignore the visibility from it. + + // Specifically, if this decl exists and has an explicit attribute. + const NamedDecl *explicitSpecSuppressor = 0; if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { // If the type of the function uses a type with unique-external @@ -531,192 +781,269 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) { // the template parameters and arguments. if (FunctionTemplateSpecializationInfo *spec = MD->getTemplateSpecializationInfo()) { - const TemplateArgumentList &TemplateArgs = *spec->TemplateArguments; - LinkageInfo ArgsLV = getLVForTemplateArgumentList(TemplateArgs, - OnlyTemplate); - TemplateParameterList *TemplateParams = - spec->getTemplate()->getTemplateParameters(); - LinkageInfo ParamsLV = getLVForTemplateParameterList(TemplateParams); - if (shouldConsiderTemplateVis(MD, spec)) { - LV.mergeWithMin(ArgsLV); - if (!OnlyTemplate) - LV.mergeWithMin(ParamsLV); - } else { - LV.mergeLinkage(ArgsLV); - if (!OnlyTemplate) - LV.mergeLinkage(ParamsLV); + mergeTemplateLV(LV, MD, spec); + if (spec->isExplicitSpecialization()) { + explicitSpecSuppressor = MD; + } else if (isExplicitMemberSpecialization(spec->getTemplate())) { + explicitSpecSuppressor = spec->getTemplate()->getTemplatedDecl(); } + } else if (isExplicitMemberSpecialization(MD)) { + explicitSpecSuppressor = MD; } - // Note that in contrast to basically every other situation, we - // *do* apply -fvisibility to method declarations. - } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { if (const ClassTemplateSpecializationDecl *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { - // Merge template argument/parameter information for member - // class template specializations. - const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); - LinkageInfo ArgsLV = getLVForTemplateArgumentList(TemplateArgs, - OnlyTemplate); - TemplateParameterList *TemplateParams = - spec->getSpecializedTemplate()->getTemplateParameters(); - LinkageInfo ParamsLV = getLVForTemplateParameterList(TemplateParams); - if (shouldConsiderTemplateVis(spec)) { - LV.mergeWithMin(ArgsLV); - if (!OnlyTemplate) - LV.mergeWithMin(ParamsLV); + mergeTemplateLV(LV, spec, computation); + if (spec->isExplicitSpecialization()) { + explicitSpecSuppressor = spec; } else { - LV.mergeLinkage(ArgsLV); - if (!OnlyTemplate) - LV.mergeLinkage(ParamsLV); + const ClassTemplateDecl *temp = spec->getSpecializedTemplate(); + if (isExplicitMemberSpecialization(temp)) { + explicitSpecSuppressor = temp->getTemplatedDecl(); + } } + } else if (isExplicitMemberSpecialization(RD)) { + explicitSpecSuppressor = RD; } // Static data members. } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. - LinkageInfo TypeLV = getLVForType(VD->getType()); - if (TypeLV.linkage() != ExternalLinkage) - LV.mergeLinkage(UniqueExternalLinkage); - LV.mergeVisibility(TypeLV); - } + LinkageInfo typeLV = VD->getType()->getLinkageAndVisibility(); + LV.mergeMaybeWithVisibility(typeLV, + !LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()); - return LV; -} + if (isExplicitMemberSpecialization(VD)) { + explicitSpecSuppressor = VD; + } -static void clearLinkageForClass(const CXXRecordDecl *record) { - for (CXXRecordDecl::decl_iterator - i = record->decls_begin(), e = record->decls_end(); i != e; ++i) { - Decl *child = *i; - if (isa<NamedDecl>(child)) - cast<NamedDecl>(child)->ClearLinkageCache(); + // Template members. + } else if (const TemplateDecl *temp = dyn_cast<TemplateDecl>(D)) { + bool considerVisibility = + (!LV.isVisibilityExplicit() && + !classLV.isVisibilityExplicit() && + !hasExplicitVisibilityAlready(computation)); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters()); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + + if (const RedeclarableTemplateDecl *redeclTemp = + dyn_cast<RedeclarableTemplateDecl>(temp)) { + if (isExplicitMemberSpecialization(redeclTemp)) { + explicitSpecSuppressor = temp->getTemplatedDecl(); + } + } } -} -void NamedDecl::anchor() { } + // We should never be looking for an attribute directly on a template. + assert(!explicitSpecSuppressor || !isa<TemplateDecl>(explicitSpecSuppressor)); -void NamedDecl::ClearLinkageCache() { - // Note that we can't skip clearing the linkage of children just - // because the parent doesn't have cached linkage: we don't cache - // when computing linkage for parent contexts. + // If this member is an explicit member specialization, and it has + // an explicit attribute, ignore visibility from the parent. + bool considerClassVisibility = true; + if (explicitSpecSuppressor && + // optimization: hasDVA() is true only with explicit visibility. + LV.isVisibilityExplicit() && + classLV.getVisibility() != DefaultVisibility && + hasDirectVisibilityAttribute(explicitSpecSuppressor, computation)) { + considerClassVisibility = false; + } - HasCachedLinkage = 0; + // Finally, merge in information from the class. + LV.mergeMaybeWithVisibility(classLV, considerClassVisibility); + return LV; +} - // If we're changing the linkage of a class, we need to reset the - // linkage of child declarations, too. - if (const CXXRecordDecl *record = dyn_cast<CXXRecordDecl>(this)) - clearLinkageForClass(record); +void NamedDecl::anchor() { } - if (ClassTemplateDecl *temp = - dyn_cast<ClassTemplateDecl>(const_cast<NamedDecl*>(this))) { - // Clear linkage for the template pattern. - CXXRecordDecl *record = temp->getTemplatedDecl(); - record->HasCachedLinkage = 0; - clearLinkageForClass(record); +bool NamedDecl::isLinkageValid() const { + if (!HasCachedLinkage) + return true; - // We need to clear linkage for specializations, too. - for (ClassTemplateDecl::spec_iterator - i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) - i->ClearLinkageCache(); - } + return getLVForDecl(this, LVForExplicitValue).getLinkage() == + Linkage(CachedLinkage); +} - // Clear cached linkage for function template decls, too. - if (FunctionTemplateDecl *temp = - dyn_cast<FunctionTemplateDecl>(const_cast<NamedDecl*>(this))) { - temp->getTemplatedDecl()->ClearLinkageCache(); - for (FunctionTemplateDecl::spec_iterator - i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) - i->ClearLinkageCache(); - } - +bool NamedDecl::hasExternalLinkageUncached() const { + return getLVForDecl(this, LVForExplicitValue).getLinkage() == ExternalLinkage; } Linkage NamedDecl::getLinkage() const { - if (HasCachedLinkage) { - assert(Linkage(CachedLinkage) == - getLVForDecl(this, true).linkage()); + if (HasCachedLinkage) return Linkage(CachedLinkage); - } - CachedLinkage = getLVForDecl(this, true).linkage(); + // We don't care about visibility here, so ask for the cheapest + // possible visibility analysis. + CachedLinkage = getLVForDecl(this, LVForExplicitValue).getLinkage(); HasCachedLinkage = 1; + +#ifndef NDEBUG + verifyLinkage(); +#endif + return Linkage(CachedLinkage); } LinkageInfo NamedDecl::getLinkageAndVisibility() const { - LinkageInfo LI = getLVForDecl(this, false); - assert(!HasCachedLinkage || Linkage(CachedLinkage) == LI.linkage()); + LVComputationKind computation = + (usesTypeVisibility(this) ? LVForType : LVForValue); + LinkageInfo LI = getLVForDecl(this, computation); + if (HasCachedLinkage) { + assert(Linkage(CachedLinkage) == LI.getLinkage()); + return LI; + } HasCachedLinkage = 1; - CachedLinkage = LI.linkage(); + CachedLinkage = LI.getLinkage(); + +#ifndef NDEBUG + verifyLinkage(); +#endif + return LI; } -llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const { - // Use the most recent declaration of a variable. - if (const VarDecl *Var = dyn_cast<VarDecl>(this)) { - if (llvm::Optional<Visibility> V = - getVisibilityOf(Var->getMostRecentDecl())) - return V; +void NamedDecl::verifyLinkage() const { + // In C (because of gnu inline) and in c++ with microsoft extensions an + // static can follow an extern, so we can have two decls with different + // linkages. + const LangOptions &Opts = getASTContext().getLangOpts(); + if (!Opts.CPlusPlus || Opts.MicrosoftExt) + return; + + // 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 *D = NULL; + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + NamedDecl *T = cast<NamedDecl>(*I); + if (T == this) + continue; + if (T->HasCachedLinkage != 0) { + D = T; + break; + } + } + assert(!D || D->CachedLinkage == CachedLinkage); +} + +Optional<Visibility> +NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { + // Check the declaration itself first. + if (Optional<Visibility> V = getVisibilityOf(this, kind)) + return V; + + // If this is a member class of a specialization of a class template + // and the corresponding decl has explicit visibility, use that. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) { + CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom, kind); + } + + // If there wasn't explicit visibility there, and this is a + // specialization of a class template, check for visibility + // on the pattern. + if (const ClassTemplateSpecializationDecl *spec + = dyn_cast<ClassTemplateSpecializationDecl>(this)) + return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(), + kind); + // Use the most recent declaration. + const NamedDecl *MostRecent = cast<NamedDecl>(this->getMostRecentDecl()); + if (MostRecent != this) + return MostRecent->getExplicitVisibility(kind); + + if (const VarDecl *Var = dyn_cast<VarDecl>(this)) { if (Var->isStaticDataMember()) { VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember(); if (InstantiatedFrom) - return getVisibilityOf(InstantiatedFrom); + return getVisibilityOf(InstantiatedFrom, kind); } - return llvm::Optional<Visibility>(); + return None; } - // Use the most recent declaration of a function, and also handle - // function template specializations. + // Also handle function template specializations. if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) { - if (llvm::Optional<Visibility> V - = getVisibilityOf(fn->getMostRecentDecl())) - return V; - // If the function is a specialization of a template with an // explicit visibility attribute, use that. if (FunctionTemplateSpecializationInfo *templateInfo = fn->getTemplateSpecializationInfo()) - return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl()); + return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(), + kind); // If the function is a member of a specialization of a class template // and the corresponding decl has explicit visibility, use that. FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction(); if (InstantiatedFrom) - return getVisibilityOf(InstantiatedFrom); + return getVisibilityOf(InstantiatedFrom, kind); - return llvm::Optional<Visibility>(); + return None; } - // Otherwise, just check the declaration itself first. - if (llvm::Optional<Visibility> V = getVisibilityOf(this)) - return V; - // The visibility of a template is stored in the templated decl. if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(this)) - return getVisibilityOf(TD->getTemplatedDecl()); + return getVisibilityOf(TD->getTemplatedDecl(), kind); - // If there wasn't explicit visibility there, and this is a - // specialization of a class template, check for visibility - // on the pattern. - if (const ClassTemplateSpecializationDecl *spec - = dyn_cast<ClassTemplateSpecializationDecl>(this)) - return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl()); + return None; +} - // If this is a member class of a specialization of a class template - // and the corresponding decl has explicit visibility, use that. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) { - CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); - if (InstantiatedFrom) - return getVisibilityOf(InstantiatedFrom); +static LinkageInfo getLVForLocalDecl(const NamedDecl *D, + LVComputationKind computation) { + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + if (Function->isInAnonymousNamespace() && + !Function->getDeclContext()->isExternCContext()) + return LinkageInfo::uniqueExternal(); + + // This is a "void f();" which got merged with a file static. + if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) + return LinkageInfo::internal(); + + LinkageInfo LV; + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = + getExplicitVisibility(Function, computation)) + LV.mergeVisibility(*Vis, true); + } + + // Note that Sema::MergeCompatibleFunctionDecls already takes care of + // merging storage classes and visibility attributes, so we don't have to + // look at previous decls in here. + + return LV; } - return llvm::Optional<Visibility>(); + if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (Var->hasExternalStorage()) { + if (Var->isInAnonymousNamespace() && + !Var->getDeclContext()->isExternCContext()) + return LinkageInfo::uniqueExternal(); + + LinkageInfo LV; + if (Var->getStorageClass() == SC_PrivateExtern) + LV.mergeVisibility(HiddenVisibility, true); + else if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(Var, computation)) + LV.mergeVisibility(*Vis, true); + } + + if (const VarDecl *Prev = Var->getPreviousDecl()) { + LinkageInfo PrevLV = getLVForDecl(Prev, computation); + if (PrevLV.getLinkage()) + LV.setLinkage(PrevLV.getLinkage()); + LV.mergeVisibility(PrevLV); + } + + return LV; + } + } + + return LinkageInfo::none(); } -static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { +static LinkageInfo getLVForDecl(const NamedDecl *D, + LVComputationKind computation) { // Objective-C: treat all Objective-C declarations as having external // linkage. switch (D->getKind()) { @@ -751,12 +1078,11 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { if (isa<ParmVarDecl>(ContextDecl)) DC = ContextDecl->getDeclContext()->getRedeclContext(); else - return getLVForDecl(cast<NamedDecl>(ContextDecl), - OnlyTemplate); + return getLVForDecl(cast<NamedDecl>(ContextDecl), computation); } if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) - return getLVForDecl(ND, OnlyTemplate); + return getLVForDecl(ND, computation); return LinkageInfo::external(); } @@ -767,7 +1093,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { // Handle linkage for namespace-scope names. if (D->getDeclContext()->getRedeclContext()->isFileContext()) - return getLVForNamespaceScopeDecl(D, OnlyTemplate); + return getLVForNamespaceScopeDecl(D, computation); // C++ [basic.link]p5: // In addition, a member function, static data member, a named @@ -777,7 +1103,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { // purposes (7.1.3), has external linkage if the name of the class // has external linkage. if (D->getDeclContext()->isRecord()) - return getLVForClassMember(D, OnlyTemplate); + return getLVForClassMember(D, computation); // C++ [basic.link]p6: // The name of a function declared in block scope and the name of @@ -790,48 +1116,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { // one such matching entity, the program is ill-formed. Otherwise, // if no matching entity is found, the block scope entity receives // external linkage. - if (D->getLexicalDeclContext()->isFunctionOrMethod()) { - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { - if (Function->isInAnonymousNamespace() && - !Function->getDeclContext()->isExternCContext()) - return LinkageInfo::uniqueExternal(); - - LinkageInfo LV; - if (!OnlyTemplate) { - if (llvm::Optional<Visibility> Vis = Function->getExplicitVisibility()) - LV.mergeVisibility(*Vis, true); - } - - if (const FunctionDecl *Prev = Function->getPreviousDecl()) { - LinkageInfo PrevLV = getLVForDecl(Prev, OnlyTemplate); - if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); - LV.mergeVisibility(PrevLV); - } - - return LV; - } - - if (const VarDecl *Var = dyn_cast<VarDecl>(D)) - if (Var->getStorageClass() == SC_Extern || - Var->getStorageClass() == SC_PrivateExtern) { - if (Var->isInAnonymousNamespace() && - !Var->getDeclContext()->isExternCContext()) - return LinkageInfo::uniqueExternal(); - - LinkageInfo LV; - if (Var->getStorageClass() == SC_PrivateExtern) - LV.mergeVisibility(HiddenVisibility, true); - else if (!OnlyTemplate) { - if (llvm::Optional<Visibility> Vis = Var->getExplicitVisibility()) - LV.mergeVisibility(*Vis, true); - } - - // Note that Sema::MergeVarDecl already takes care of implementing - // C99 6.2.2p4 and propagating the visibility attribute, so we don't - // have to do it here. - return LV; - } - } + if (D->getDeclContext()->isFunctionOrMethod()) + return getLVForLocalDecl(D, computation); // C++ [basic.link]p6: // Names not covered by these rules have no linkage. @@ -843,10 +1129,24 @@ std::string NamedDecl::getQualifiedNameAsString() const { } std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { + std::string QualName; + llvm::raw_string_ostream OS(QualName); + printQualifiedName(OS, P); + return OS.str(); +} + +void NamedDecl::printQualifiedName(raw_ostream &OS) const { + printQualifiedName(OS, getASTContext().getPrintingPolicy()); +} + +void NamedDecl::printQualifiedName(raw_ostream &OS, + const PrintingPolicy &P) const { const DeclContext *Ctx = getDeclContext(); - if (Ctx->isFunctionOrMethod()) - return getNameAsString(); + if (Ctx->isFunctionOrMethod()) { + printName(OS); + return; + } typedef SmallVector<const DeclContext *, 8> ContextsTy; ContextsTy Contexts; @@ -855,22 +1155,18 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { while (Ctx && isa<NamedDecl>(Ctx)) { Contexts.push_back(Ctx); Ctx = Ctx->getParent(); - }; - - std::string QualName; - llvm::raw_string_ostream OS(QualName); + } for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend(); I != E; ++I) { if (const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(*I)) { + OS << Spec->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.data(), - TemplateArgs.size(), - P); - OS << Spec->getName() << TemplateArgsStr; + TemplateSpecializationType::PrintTemplateArgumentList(OS, + TemplateArgs.data(), + TemplateArgs.size(), + P); } else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) { if (ND->isAnonymousNamespace()) OS << "<anonymous namespace>"; @@ -912,8 +1208,15 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { OS << *this; else OS << "<anonymous>"; +} - return OS.str(); +void NamedDecl::getNameForDiagnostic(raw_ostream &OS, + const PrintingPolicy &Policy, + bool Qualified) const { + if (Qualified) + printQualifiedName(OS, Policy); + else + printName(OS); } bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { @@ -1166,45 +1469,80 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, SourceLocation IdL, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten) { - return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S, SCAsWritten); + StorageClass S) { + return new (C) VarDecl(Var, 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, SC_None); + QualType(), 0, SC_None); } void VarDecl::setStorageClass(StorageClass SC) { assert(isLegalForVariable(SC)); - if (getStorageClass() != SC) - ClearLinkageCache(); - VarDeclBits.SClass = SC; } SourceRange VarDecl::getSourceRange() const { if (const Expr *Init = getInit()) { SourceLocation InitEnd = Init->getLocEnd(); - if (InitEnd.isValid()) + // If Init is implicit, ignore its source range and fallback on + // DeclaratorDecl::getSourceRange() to handle postfix elements. + if (InitEnd.isValid() && InitEnd != getLocation()) return SourceRange(getOuterLocStart(), InitEnd); } return DeclaratorDecl::getSourceRange(); } -bool VarDecl::isExternC() const { - if (getLinkage() != ExternalLinkage) - return false; +template<typename T> +static LanguageLinkage getLanguageLinkageTemplate(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 (!isExternalLinkage(D.getLinkage())) + return NoLanguageLinkage; + + // Language linkage is a C++ concept, but saying that everything else in C has + // C language linkage fits the implementation nicely. + ASTContext &Context = D.getASTContext(); + if (!Context.getLangOpts().CPlusPlus) + return CLanguageLinkage; - const DeclContext *DC = getDeclContext(); + // C++ [dcl.link]p4: A C language linkage is ignored in determining the + // language linkage of the names of class members and the function type of + // class member functions. + const DeclContext *DC = D.getDeclContext(); if (DC->isRecord()) + return CXXLanguageLinkage; + + // If the first decl is in an extern "C" context, any other redeclaration + // will have C language linkage. If the first one is not in an extern "C" + // context, we would have reported an error for any other decl being in one. + const T *First = D.getFirstDeclaration(); + if (First->getDeclContext()->isExternCContext()) + return CLanguageLinkage; + return CXXLanguageLinkage; +} + +template<typename T> +static bool isExternCTemplate(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(); + if (DC->isRecord()) { + assert(D.getASTContext().getLangOpts().CPlusPlus); return false; + } - ASTContext &Context = getASTContext(); - if (!Context.getLangOpts().CPlusPlus) - return true; - return DC->isExternCContext(); + return D.getLanguageLinkage() == CLanguageLinkage; +} + +LanguageLinkage VarDecl::getLanguageLinkage() const { + return getLanguageLinkageTemplate(*this); +} + +bool VarDecl::isExternC() const { + return isExternCTemplate(*this); } VarDecl *VarDecl::getCanonicalDecl() { @@ -1241,12 +1579,11 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( // AST for 'extern "C" int foo;' is annotated with 'extern'. if (hasExternalStorage()) return DeclarationOnly; - - if (getStorageClassAsWritten() == SC_Extern || - getStorageClassAsWritten() == SC_PrivateExtern) { + + if (hasExternalStorage()) { for (const VarDecl *PrevVar = getPreviousDecl(); PrevVar; PrevVar = PrevVar->getPreviousDecl()) { - if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit()) + if (PrevVar->getLinkage() == InternalLinkage) return DeclarationOnly; } } @@ -1375,7 +1712,7 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const { // In C++11, any variable of reference type can be used in a constant // expression if it is initialized by a constant expression. - if (Lang.CPlusPlus0x && getType()->isReferenceType()) + if (Lang.CPlusPlus11 && getType()->isReferenceType()) return true; // Only const objects can be used in constant expressions in C++. C++98 does @@ -1391,7 +1728,7 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const { // Additionally, in C++11, non-volatile constexpr variables can be used in // constant expressions. - return Lang.CPlusPlus0x && isConstexpr(); + return Lang.CPlusPlus11 && isConstexpr(); } /// Convert the initializer for this declaration to the elaborated EvaluatedStmt @@ -1409,12 +1746,12 @@ EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const { } APValue *VarDecl::evaluateValue() const { - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + SmallVector<PartialDiagnosticAt, 8> Notes; return evaluateValue(Notes); } APValue *VarDecl::evaluateValue( - llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const { + SmallVectorImpl<PartialDiagnosticAt> &Notes) const { EvaluatedStmt *Eval = ensureEvaluatedStmt(); // We only produce notes indicating why an initializer is non-constant the @@ -1447,7 +1784,7 @@ APValue *VarDecl::evaluateValue( // In C++11, we have determined whether the initializer was a constant // expression as a side-effect. - if (getASTContext().getLangOpts().CPlusPlus0x && !Eval->CheckedICE) { + if (getASTContext().getLangOpts().CPlusPlus11 && !Eval->CheckedICE) { Eval->CheckedICE = true; Eval->IsICE = Result && Notes.empty(); } @@ -1471,8 +1808,8 @@ bool VarDecl::checkInitIsICE() const { // In C++11, evaluate the initializer to check whether it's a constant // expression. - if (getASTContext().getLangOpts().CPlusPlus0x) { - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + if (getASTContext().getLangOpts().CPlusPlus11) { + SmallVector<PartialDiagnosticAt, 8> Notes; evaluateValue(Notes); return Eval->IsICE; } @@ -1541,16 +1878,15 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, - Expr *DefArg) { + StorageClass S, Expr *DefArg) { return new (C) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo, - S, SCAsWritten, DefArg); + S, DefArg); } 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, SC_None, 0); + 0, QualType(), 0, SC_None, 0); } SourceRange ParmVarDecl::getSourceRange() const { @@ -1602,17 +1938,13 @@ unsigned ParmVarDecl::getParameterIndexLarge() const { // FunctionDecl Implementation //===----------------------------------------------------------------------===// -void FunctionDecl::getNameForDiagnostic(std::string &S, - const PrintingPolicy &Policy, - bool Qualified) const { - NamedDecl::getNameForDiagnostic(S, Policy, Qualified); +void FunctionDecl::getNameForDiagnostic( + raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { + NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs(); if (TemplateArgs) - S += TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs->data(), - TemplateArgs->size(), - Policy); - + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs->data(), TemplateArgs->size(), Policy); } bool FunctionDecl::isVariadic() const { @@ -1684,13 +2016,6 @@ void FunctionDecl::setPure(bool P) { Parent->markedVirtualFunctionPure(); } -void FunctionDecl::setConstexpr(bool IC) { - IsConstexpr = IC; - CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(this); - if (IC && CD) - CD->getParent()->markedConstructorConstexpr(CD); -} - bool FunctionDecl::isMain() const { const TranslationUnitDecl *tunit = dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); @@ -1722,29 +2047,25 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy); } -bool FunctionDecl::isExternC() const { - if (getLinkage() != ExternalLinkage) - return false; - - if (getAttr<OverloadableAttr>()) - return false; - - const DeclContext *DC = getDeclContext(); - if (DC->isRecord()) - return false; +LanguageLinkage FunctionDecl::getLanguageLinkage() const { + // Users expect to be able to write + // extern "C" void *__builtin_alloca (size_t); + // so consider builtins as having C language linkage. + if (getBuiltinID()) + return CLanguageLinkage; - ASTContext &Context = getASTContext(); - if (!Context.getLangOpts().CPlusPlus) - return true; + return getLanguageLinkageTemplate(*this); +} - return isMain() || DC->isExternCContext(); +bool FunctionDecl::isExternC() const { + return isExternCTemplate(*this); } bool FunctionDecl::isGlobal() const { if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) return Method->isStatic(); - if (getStorageClass() == SC_Static) + if (getCanonicalDecl()->getStorageClass() == SC_Static) return false; for (const DeclContext *DC = getDeclContext(); @@ -1760,6 +2081,12 @@ bool FunctionDecl::isGlobal() const { return true; } +bool FunctionDecl::isNoReturn() const { + return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || + hasAttr<C11NoReturnAttr>() || + getType()->getAs<FunctionType>()->getNoReturnAttr(); +} + void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { redeclarable_base::setPreviousDeclaration(PrevDecl); @@ -1783,14 +2110,6 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDeclaration(); } -void FunctionDecl::setStorageClass(StorageClass SC) { - assert(isLegalForFunction(SC)); - if (getStorageClass() != SC) - ClearLinkageCache(); - - SClass = SC; -} - /// \brief Returns a value indicating whether this function /// corresponds to a builtin function. /// @@ -1851,7 +2170,7 @@ unsigned FunctionDecl::getNumParams() const { } void FunctionDecl::setParams(ASTContext &C, - llvm::ArrayRef<ParmVarDecl *> NewParamInfo) { + ArrayRef<ParmVarDecl *> NewParamInfo) { assert(ParamInfo == 0 && "Already has param info!"); assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!"); @@ -1862,13 +2181,13 @@ void FunctionDecl::setParams(ASTContext &C, } } -void FunctionDecl::setDeclsInPrototypeScope(llvm::ArrayRef<NamedDecl *> NewDecls) { +void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!"); if (!NewDecls.empty()) { NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; std::copy(NewDecls.begin(), NewDecls.end(), A); - DeclsInPrototypeScope = llvm::ArrayRef<NamedDecl*>(A, NewDecls.size()); + DeclsInPrototypeScope = ArrayRef<NamedDecl *>(A, NewDecls.size()); } } @@ -1907,38 +2226,6 @@ unsigned FunctionDecl::getMinRequiredArguments() const { return NumRequiredArgs; } -bool FunctionDecl::isInlined() const { - if (IsInline) - return true; - - if (isa<CXXMethodDecl>(this)) { - if (!isOutOfLine() || getCanonicalDecl()->isInlineSpecified()) - return true; - } - - switch (getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - return false; - - case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - // Handle below. - break; - } - - const FunctionDecl *PatternDecl = getTemplateInstantiationPattern(); - bool HasPattern = false; - if (PatternDecl) - HasPattern = PatternDecl->hasBody(PatternDecl); - - if (HasPattern && PatternDecl) - return PatternDecl->isInlined(); - - return false; -} - static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { // Only consider file-scope declarations in this test. if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) @@ -1973,7 +2260,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { // // FIXME: What happens if gnu_inline gets added on after the first // declaration? - if (!isInlineSpecified() || getStorageClassAsWritten() == SC_Extern) + if (!isInlineSpecified() || getStorageClass() == SC_Extern) return false; const FunctionDecl *Prev = this; @@ -1985,10 +2272,10 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then it is always externally visible. if (!Prev->isInlineSpecified() || - Prev->getStorageClassAsWritten() != SC_Extern) + Prev->getStorageClass() != SC_Extern) return false; } else if (Prev->isInlineSpecified() && - Prev->getStorageClassAsWritten() != SC_Extern) { + Prev->getStorageClass() != SC_Extern) { return false; } } @@ -2014,8 +2301,8 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { return FoundBody; } -/// \brief For an inline function definition in C or C++, determine whether the -/// definition will be externally visible. +/// \brief For an inline function definition in C, or for a gnu_inline function +/// in C++, determine whether the definition will be externally visible. /// /// Inline function definitions are always available for inlining optimizations. /// However, depending on the language dialect, declaration specifiers, and @@ -2043,7 +2330,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then this inline definition is // externally visible. - if (!(isInlineSpecified() && getStorageClassAsWritten() == SC_Extern)) + if (!(isInlineSpecified() && getStorageClass() == SC_Extern)) return true; // If any declaration is 'inline' but not 'extern', then this definition @@ -2052,13 +2339,17 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { Redecl != RedeclEnd; ++Redecl) { if (Redecl->isInlineSpecified() && - Redecl->getStorageClassAsWritten() != SC_Extern) + Redecl->getStorageClass() != SC_Extern) return true; } return false; } + // The rest of this function is C-only. + assert(!Context.getLangOpts().CPlusPlus && + "should not use C inline rules in C++"); + // C99 6.7.4p6: // [...] If all of the file scope declarations for a function in a // translation unit include the inline function specifier without extern, @@ -2118,10 +2409,6 @@ FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { return 0; } -MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { - return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>(); -} - void FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD, @@ -2553,18 +2840,17 @@ TagDecl* TagDecl::getCanonicalDecl() { return getFirstDeclaration(); } -void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { - TypedefNameDeclOrQualifier = TDD; +void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { + TypedefNameDeclOrQualifier = TDD; if (TypeForDecl) - const_cast<Type*>(TypeForDecl)->ClearLinkageCache(); - ClearLinkageCache(); + assert(TypeForDecl->isLinkageValid()); + assert(isLinkageValid()); } void TagDecl::startDefinition() { IsBeingDefined = true; - if (isa<CXXRecordDecl>(this)) { - CXXRecordDecl *D = cast<CXXRecordDecl>(this); + if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) { struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) @@ -2587,6 +2873,16 @@ void TagDecl::completeDefinition() { TagDecl *TagDecl::getDefinition() const { if (isCompleteDefinition()) return const_cast<TagDecl *>(this); + + // If it's possible for us to have an out-of-date definition, check now. + if (MayHaveOutOfDateDef) { + if (IdentifierInfo *II = getIdentifier()) { + if (II->isOutOfDate()) { + updateOutOfDate(*II); + } + } + } + if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); @@ -2643,14 +2939,17 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, bool IsScopedUsingClassTag, bool IsFixed) { EnumDecl *Enum = new (C) EnumDecl(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)); - return new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), 0, 0, - false, false, false); + EnumDecl *Enum = new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), + 0, 0, false, false, false); + Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; + return Enum; } void EnumDecl::completeDefinition(QualType NewType, @@ -2708,6 +3007,7 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, HasFlexibleArrayMember = false; AnonymousStructOrUnion = false; HasObjectMember = false; + HasVolatileMember = false; LoadedFieldsFromExternalStorage = false; assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); } @@ -2717,14 +3017,18 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, IdentifierInfo *Id, RecordDecl* PrevDecl) { RecordDecl* R = new (C) RecordDecl(Record, TK, DC, StartLoc, IdLoc, Id, PrevDecl); + R->MayHaveOutOfDateDef = C.getLangOpts().Modules; + C.getTypeDeclType(R, PrevDecl); return R; } RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(RecordDecl)); - return new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), - SourceLocation(), 0, 0); + RecordDecl *R = new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), + SourceLocation(), 0, 0); + R->MayHaveOutOfDateDef = C.getLangOpts().Modules; + return R; } bool RecordDecl::isInjectedClassName() const { @@ -2793,7 +3097,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { // BlockDecl Implementation //===----------------------------------------------------------------------===// -void BlockDecl::setParams(llvm::ArrayRef<ParmVarDecl *> NewParamInfo) { +void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { assert(ParamInfo == 0 && "Already has param info!"); // Zero params -> null pointer. @@ -2871,6 +3175,14 @@ LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 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)) + return true; + + return isWeakImported(); +} + void ImplicitParamDecl::anchor() { } ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, @@ -2890,12 +3202,12 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass SC, StorageClass SCAsWritten, + StorageClass SC, bool isInlineSpecified, bool hasWrittenPrototype, bool isConstexprSpecified) { FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, - T, TInfo, SC, SCAsWritten, + T, TInfo, SC, isInlineSpecified, isConstexprSpecified); New->HasWrittenPrototype = hasWrittenPrototype; @@ -2906,7 +3218,7 @@ 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, SC_None, false, false); + SC_None, false, false); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { @@ -3013,6 +3325,17 @@ FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, return new (Mem) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation()); } +void EmptyDecl::anchor() {} + +EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { + return new (C) EmptyDecl(DC, L); +} + +EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EmptyDecl)); + return new (Mem) EmptyDecl(0, SourceLocation()); +} + //===----------------------------------------------------------------------===// // ImportDecl Implementation //===----------------------------------------------------------------------===// |