diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/Decl.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/Decl.cpp | 172 |
1 files changed, 118 insertions, 54 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 4c323da..95d52cb 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -28,6 +28,8 @@ #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" +#include <algorithm> + using namespace clang; //===----------------------------------------------------------------------===// @@ -51,7 +53,7 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) { // If we're on Mac OS X, an 'availability' for Mac OS X attribute // implies visibility(default). - if (D->getASTContext().Target.getTriple().isOSDarwin()) { + if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) { for (specific_attr_iterator<AvailabilityAttr> A = D->specific_attr_begin<AvailabilityAttr>(), AEnd = D->specific_attr_end<AvailabilityAttr>(); @@ -818,7 +820,7 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { if (Ctx->isFunctionOrMethod()) return getNameAsString(); - typedef llvm::SmallVector<const DeclContext *, 8> ContextsTy; + typedef SmallVector<const DeclContext *, 8> ContextsTy; ContextsTy Contexts; // Collect contexts. @@ -845,18 +847,18 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { if (ND->isAnonymousNamespace()) OS << "<anonymous namespace>"; else - OS << ND; + OS << *ND; } else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) { if (!RD->getIdentifier()) OS << "<anonymous " << RD->getKindName() << '>'; else - OS << RD; + OS << *RD; } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { const FunctionProtoType *FT = 0; if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>()); - OS << FD << '('; + OS << *FD << '('; if (FT) { unsigned NumParams = FD->getNumParams(); for (unsigned i = 0; i < NumParams; ++i) { @@ -875,13 +877,13 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { } OS << ')'; } else { - OS << cast<NamedDecl>(*I); + OS << *cast<NamedDecl>(*I); } OS << "::"; } if (getDeclName()) - OS << this; + OS << *this; else OS << "<anonymous>"; @@ -1003,8 +1005,7 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; - } - else { + } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { @@ -1120,15 +1121,16 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { switch (SC) { - case SC_None: break; - case SC_Auto: return "auto"; break; - case SC_Extern: return "extern"; break; - case SC_PrivateExtern: return "__private_extern__"; break; - case SC_Register: return "register"; break; - case SC_Static: return "static"; break; + case SC_None: break; + case SC_Auto: return "auto"; + case SC_Extern: return "extern"; + case SC_OpenCLWorkGroupLocal: return "<<work-group-local>>"; + case SC_PrivateExtern: return "__private_extern__"; + case SC_Register: return "register"; + case SC_Static: return "static"; } - assert(0 && "Invalid storage class"); + llvm_unreachable("Invalid storage class"); return 0; } @@ -1388,6 +1390,16 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, S, SCAsWritten, DefArg); } +SourceRange ParmVarDecl::getSourceRange() const { + if (!hasInheritedDefaultArg()) { + SourceRange ArgRange = getDefaultArgRange(); + if (ArgRange.isValid()) + return SourceRange(getOuterLocStart(), ArgRange.getEnd()); + } + + return DeclaratorDecl::getSourceRange(); +} + Expr *ParmVarDecl::getDefaultArg() { assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); assert(!hasUninstantiatedDefaultArg() && @@ -1429,6 +1441,15 @@ bool ParmVarDecl::isParameterPack() const { return isa<PackExpansionType>(getType()); } +void ParmVarDecl::setParameterIndexLarge(unsigned parameterIndex) { + getASTContext().setParameterIndex(this, parameterIndex); + ParmVarDeclBits.ParameterIndex = ParameterIndexSentinel; +} + +unsigned ParmVarDecl::getParameterIndexLarge() const { + return getASTContext().getParameterIndex(this); +} + //===----------------------------------------------------------------------===// // FunctionDecl Implementation //===----------------------------------------------------------------------===// @@ -1678,20 +1699,14 @@ unsigned FunctionDecl::getNumParams() const { } void FunctionDecl::setParams(ASTContext &C, - ParmVarDecl **NewParamInfo, unsigned NumParams) { + llvm::ArrayRef<ParmVarDecl *> NewParamInfo) { assert(ParamInfo == 0 && "Already has param info!"); - assert(NumParams == getNumParams() && "Parameter count mismatch!"); + assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!"); // Zero params -> null pointer. - if (NumParams) { - void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); - ParamInfo = new (Mem) ParmVarDecl*[NumParams]; - memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); - - // Update source range. The check below allows us to set EndRangeLoc before - // setting the parameters. - if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation()) - EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd(); + if (!NewParamInfo.empty()) { + ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()]; + std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo); } } @@ -1762,6 +1777,33 @@ bool FunctionDecl::isInlined() const { return false; } +/// \brief For a function declaration in C or C++, determine whether this +/// declaration causes the definition to be externally visible. +/// +/// Determines whether this is the first non-inline redeclaration of an inline +/// function in a language where "inline" does not normally require an +/// externally visible definition. +bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { + assert(!doesThisDeclarationHaveABody() && + "Must have a declaration without a body."); + + ASTContext &Context = getASTContext(); + + // In C99 mode, a function may have an inline definition (causing it to + // be deferred) then redeclared later. As a special case, "extern inline" + // is not required to produce an external symbol. + if (Context.getLangOptions().GNUInline || !Context.getLangOptions().C99 || + Context.getLangOptions().CPlusPlus) + return false; + if (getLinkage() != ExternalLinkage || isInlineSpecified()) + return false; + const FunctionDecl *Definition = 0; + if (hasBody(Definition)) + return Definition->isInlined() && + Definition->isInlineDefinitionExternallyVisible(); + return false; +} + /// \brief For an inline function definition in C or C++, determine whether the /// definition will be externally visible. /// @@ -1814,7 +1856,12 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // Only consider file-scope declarations in this test. if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) continue; - + + // Only consider explicit declarations; the presence of a builtin for a + // libcall shouldn't affect whether a definition is externally visible. + if (Redecl->isImplicit()) + continue; + if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern) return true; // Not an inline definition } @@ -1857,8 +1904,7 @@ FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { <DependentFunctionTemplateSpecializationInfo*>()) return TK_DependentFunctionTemplateSpecialization; - assert(false && "Did we miss a TemplateOrSpecialization type?"); - return TK_NonTemplate; + llvm_unreachable("Did we miss a TemplateOrSpecialization type?"); } FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { @@ -1890,13 +1936,17 @@ bool FunctionDecl::isImplicitlyInstantiable() const { switch (getTemplateSpecializationKind()) { case TSK_Undeclared: - case TSK_ExplicitSpecialization: case TSK_ExplicitInstantiationDefinition: return false; case TSK_ImplicitInstantiation: return true; + // It is possible to instantiate TSK_ExplicitSpecialization kind + // if the FunctionDecl has a class scope specialization pattern. + case TSK_ExplicitSpecialization: + return getClassScopeSpecializationPattern() != 0; + case TSK_ExplicitInstantiationDeclaration: // Handled below. break; @@ -1919,6 +1969,10 @@ bool FunctionDecl::isImplicitlyInstantiable() const { } FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { + // Handle class scope explicit specialization special case. + if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return getClassScopeSpecializationPattern(); + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of @@ -1944,6 +1998,10 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { return 0; } +FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { + return getASTContext().getClassScopeSpecializationPattern(this); +} + const TemplateArgumentList * FunctionDecl::getTemplateSpecializationArgs() const { if (FunctionTemplateSpecializationInfo *Info @@ -1954,7 +2012,7 @@ FunctionDecl::getTemplateSpecializationArgs() const { return 0; } -const TemplateArgumentListInfo * +const ASTTemplateArgumentListInfo * FunctionDecl::getTemplateSpecializationArgsAsWritten() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization @@ -2069,7 +2127,7 @@ FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, MSInfo->getPointOfInstantiation().isInvalid()) MSInfo->setPointOfInstantiation(PointOfInstantiation); } else - assert(false && "Function cannot have a template specialization kind"); + llvm_unreachable("Function cannot have a template specialization kind"); } SourceLocation FunctionDecl::getPointOfInstantiation() const { @@ -2134,6 +2192,12 @@ bool FieldDecl::isAnonymousStructOrUnion() const { return false; } +unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { + assert(isBitField() && "not a bitfield"); + Expr *BitWidth = InitializerOrBitWidth.getPointer(); + return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue(); +} + unsigned FieldDecl::getFieldIndex() const { if (CachedFieldIndex) return CachedFieldIndex - 1; @@ -2165,8 +2229,8 @@ unsigned FieldDecl::getFieldIndex() const { } SourceRange FieldDecl::getSourceRange() const { - if (isBitField()) - return SourceRange(getInnerLocStart(), getBitWidth()->getLocEnd()); + if (const Expr *E = InitializerOrBitWidth.getPointer()) + return SourceRange(getInnerLocStart(), E->getLocEnd()); return DeclaratorDecl::getSourceRange(); } @@ -2218,22 +2282,22 @@ void TagDecl::completeDefinition() { cast<CXXRecordDecl>(this)->hasDefinition()) && "definition completed but not started"); - IsDefinition = true; + IsCompleteDefinition = true; IsBeingDefined = false; if (ASTMutationListener *L = getASTMutationListener()) L->CompletedTagDefinition(this); } -TagDecl* TagDecl::getDefinition() const { - if (isDefinition()) +TagDecl *TagDecl::getDefinition() const { + if (isCompleteDefinition()) return const_cast<TagDecl *>(this); if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); R != REnd; ++R) - if (R->isDefinition()) + if (R->isCompleteDefinition()) return *R; return 0; @@ -2246,8 +2310,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; - } - else { + } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { @@ -2296,7 +2359,7 @@ void EnumDecl::completeDefinition(QualType NewType, QualType NewPromotionType, unsigned NumPositiveBits, unsigned NumNegativeBits) { - assert(!isDefinition() && "Cannot redefine enums!"); + assert(!isCompleteDefinition() && "Cannot redefine enums!"); if (!IntegerType) IntegerType = NewType.getTypePtr(); PromotionType = NewPromotionType; @@ -2349,7 +2412,7 @@ RecordDecl::field_iterator RecordDecl::field_begin() const { /// completeDefinition - Notes that the definition of this type is now /// complete. void RecordDecl::completeDefinition() { - assert(!isDefinition() && "Cannot redefine record!"); + assert(!isCompleteDefinition() && "Cannot redefine record!"); TagDecl::completeDefinition(); } @@ -2360,7 +2423,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { // Notify that we have a RecordDecl doing some initialization. ExternalASTSource::Deserializing TheFields(Source); - llvm::SmallVector<Decl*, 64> Decls; + SmallVector<Decl*, 64> Decls; LoadedFieldsFromExternalStorage = true; switch (Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls)) { case ELR_Success: @@ -2380,23 +2443,22 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { if (Decls.empty()) return; - llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls); + llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, + /*FieldsAlreadyLoaded=*/false); } //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// -void BlockDecl::setParams(ParmVarDecl **NewParamInfo, - unsigned NParms) { +void BlockDecl::setParams(llvm::ArrayRef<ParmVarDecl *> NewParamInfo) { assert(ParamInfo == 0 && "Already has param info!"); // Zero params -> null pointer. - if (NParms) { - NumParams = NParms; - void *Mem = getASTContext().Allocate(sizeof(ParmVarDecl*)*NumParams); - ParamInfo = new (Mem) ParmVarDecl*[NumParams]; - memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); + if (!NewParamInfo.empty()) { + NumParams = NewParamInfo.size(); + ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()]; + std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo); } } @@ -2481,10 +2543,12 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, QualType T, TypeSourceInfo *TInfo, StorageClass SC, StorageClass SCAsWritten, bool isInlineSpecified, - bool hasWrittenPrototype) { + bool hasWrittenPrototype, + bool isConstexprSpecified) { FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, T, TInfo, SC, SCAsWritten, - isInlineSpecified); + isInlineSpecified, + isConstexprSpecified); New->HasWrittenPrototype = hasWrittenPrototype; return New; } |