diff options
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r-- | lib/AST/Decl.cpp | 164 |
1 files changed, 124 insertions, 40 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index d1e8d25ea044b..c3fa1c87affd1 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1395,6 +1395,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, return clang::LinkageComputer::getLVForDecl(D, computation); } +void NamedDecl::printName(raw_ostream &os) const { + os << Name; +} + std::string NamedDecl::getQualifiedNameAsString() const { std::string QualName; llvm::raw_string_ostream OS(QualName); @@ -1481,7 +1485,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, OS << "::"; } - if (getDeclName()) + if (getDeclName() || isa<DecompositionDecl>(this)) OS << *this; else OS << "(anonymous)"; @@ -1922,6 +1926,9 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // // FIXME: How do you declare (but not define) a partial specialization of // a static data member template outside the containing class? + if (isThisDeclarationADemotedDefinition()) + return DeclarationOnly; + if (isStaticDataMember()) { if (isOutOfLine() && !(getCanonicalDecl()->isInline() && @@ -2246,6 +2253,56 @@ bool VarDecl::checkInitIsICE() const { return Eval->IsICE; } +VarDecl *VarDecl::getTemplateInstantiationPattern() const { + // If it's a variable template specialization, find the template or partial + // specialization from which it was instantiated. + if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(this)) { + auto From = VDTemplSpec->getInstantiatedFrom(); + if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) { + while (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) { + if (NewVTD->isMemberSpecialization()) + break; + VTD = NewVTD; + } + return VTD->getTemplatedDecl()->getDefinition(); + } + if (auto *VTPSD = + From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { + while (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) { + if (NewVTPSD->isMemberSpecialization()) + break; + VTPSD = NewVTPSD; + } + return VTPSD->getDefinition(); + } + } + + if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { + if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) { + VarDecl *VD = getInstantiatedFromStaticDataMember(); + while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) + VD = NewVD; + return VD->getDefinition(); + } + } + + if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) { + + while (VarTemplate->getInstantiatedFromMemberTemplate()) { + if (VarTemplate->isMemberSpecialization()) + break; + VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate(); + } + + assert((!VarTemplate->getTemplatedDecl() || + !isTemplateInstantiation(getTemplateSpecializationKind())) && + "couldn't find pattern for variable instantiation"); + + return VarTemplate->getTemplatedDecl(); + } + return nullptr; +} + VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return cast<VarDecl>(MSI->getInstantiatedFrom()); @@ -2592,7 +2649,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { return false; const auto *FPT = getType()->castAs<FunctionProtoType>(); - if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic()) + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic()) return false; // If this is a single-parameter function, it must be a replaceable global @@ -2600,20 +2657,42 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { 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->getParamType(1); + unsigned Params = 1; + QualType Ty = FPT->getParamType(Params); ASTContext &Ctx = getASTContext(); + + auto Consume = [&] { + ++Params; + Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType(); + }; + + // In C++14, the next parameter can be a 'std::size_t' for sized delete. + bool IsSizedDelete = false; if (Ctx.getLangOpts().SizedDeallocation && - Ctx.hasSameType(Ty, Ctx.getSizeType())) - return true; - if (!Ty->isReferenceType()) - return false; - Ty = Ty->getPointeeType(); - if (Ty.getCVRQualifiers() != Qualifiers::Const) - return false; - const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace(); + (getDeclName().getCXXOverloadedOperator() == OO_Delete || + getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) && + Ctx.hasSameType(Ty, Ctx.getSizeType())) { + IsSizedDelete = true; + Consume(); + } + + // In C++17, the next parameter can be a 'std::align_val_t' for aligned + // new/delete. + if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) + Consume(); + + // Finally, if this is not a sized delete, the final parameter can + // be a 'const std::nothrow_t&'. + if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) { + Ty = Ty->getPointeeType(); + if (Ty.getCVRQualifiers() != Qualifiers::Const) + return false; + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + if (RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace()) + Consume(); + } + + return Params == FPT->getNumParams(); } LanguageLinkage FunctionDecl::getLanguageLinkage() const { @@ -2653,9 +2732,14 @@ bool FunctionDecl::isGlobal() const { } bool FunctionDecl::isNoReturn() const { - return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || - hasAttr<C11NoReturnAttr>() || - getType()->getAs<FunctionType>()->getNoReturnAttr(); + if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || + hasAttr<C11NoReturnAttr>()) + return true; + + if (auto *FnTy = getType()->getAs<FunctionType>()) + return FnTy->getNoReturnAttr(); + + return false; } void @@ -2756,28 +2840,6 @@ void FunctionDecl::setParams(ASTContext &C, } } -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::makeArrayRef(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 @@ -2964,7 +3026,8 @@ const Attr *FunctionDecl::getUnusedResultAttr() const { /// an externally visible symbol, but "extern inline" will not create an /// externally visible symbol. bool FunctionDecl::isInlineDefinitionExternallyVisible() const { - assert(doesThisDeclarationHaveABody() && "Must have the function definition"); + assert((doesThisDeclarationHaveABody() || willHaveBody()) && + "Must be a function definition"); assert(isInlined() && "Function must be inline"); ASTContext &Context = getASTContext(); @@ -3408,6 +3471,10 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BIstrlen: return Builtin::BIstrlen; + case Builtin::BI__builtin_bzero: + case Builtin::BIbzero: + return Builtin::BIbzero; + default: if (isExternC()) { if (FnInfo->isStr("memset")) @@ -3430,6 +3497,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BIstrndup; else if (FnInfo->isStr("strlen")) return Builtin::BIstrlen; + else if (FnInfo->isStr("bzero")) + return Builtin::BIbzero; } break; } @@ -4281,3 +4350,18 @@ SourceRange ImportDecl::getSourceRange() const { return SourceRange(getLocation(), getIdentifierLocs().back()); } + +//===----------------------------------------------------------------------===// +// ExportDecl Implementation +//===----------------------------------------------------------------------===// + +void ExportDecl::anchor() {} + +ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation ExportLoc) { + return new (C, DC) ExportDecl(DC, ExportLoc); +} + +ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) ExportDecl(nullptr, SourceLocation()); +} |