diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 9 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 81 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 6 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 78 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 20 | ||||
-rw-r--r-- | lib/AST/ExternalASTMerger.cpp | 5 | ||||
-rw-r--r-- | lib/AST/ODRHash.cpp | 18 |
7 files changed, 191 insertions, 26 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a2ff176df11f9..fd9723298fca9 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -8523,7 +8523,10 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, RequiresICE = false; // Read the prefixed modifiers first. - bool Done = false, IsSpecialLong = false; + bool Done = false; + #ifndef NDEBUG + bool IsSpecialLong = false; + #endif while (!Done) { switch (*Str++) { default: Done = true; --Str; break; @@ -8549,7 +8552,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, // 'N' behaves like 'L' for all non LP64 targets and 'int' otherwise. assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!"); assert(HowLong == 0 && "Can't use both 'L' and 'N' modifiers!"); + #ifndef NDEBUG IsSpecialLong = true; + #endif if (Context.getTargetInfo().getLongWidth() == 32) ++HowLong; break; @@ -8558,7 +8563,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, // This modifier represents int64 type. assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!"); assert(HowLong == 0 && "Can't use both 'L' and 'W' modifiers!"); + #ifndef NDEBUG IsSpecialLong = true; + #endif switch (Context.getTargetInfo().getInt64Type()) { default: llvm_unreachable("Unexpected integer type"); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 267c6992af897..573a98efe980b 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -573,6 +573,44 @@ static bool isSingleLineLanguageLinkage(const Decl &D) { return false; } +static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) { + switch (D->getModuleOwnershipKind()) { + case Decl::ModuleOwnershipKind::Unowned: + case Decl::ModuleOwnershipKind::ModulePrivate: + return false; + case Decl::ModuleOwnershipKind::Visible: + case Decl::ModuleOwnershipKind::VisibleWhenImported: + if (auto *M = D->getOwningModule()) + return M->Kind == Module::ModuleInterfaceUnit; + } + llvm_unreachable("unexpected module ownership kind"); +} + +static LinkageInfo getInternalLinkageFor(const NamedDecl *D) { + // Internal linkage declarations within a module interface unit are modeled + // as "module-internal linkage", which means that they have internal linkage + // formally but can be indirectly accessed from outside the module via inline + // functions and templates defined within the module. + if (auto *M = D->getOwningModule()) + if (M->Kind == Module::ModuleInterfaceUnit) + return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); + + return LinkageInfo::internal(); +} + +static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { + // C++ Modules TS [basic.link]/6.8: + // - A name declared at namespace scope that does not have internal linkage + // by the previous rules and that is introduced by a non-exported + // declaration has module linkage. + if (auto *M = D->getOwningModule()) + if (M->Kind == Module::ModuleInterfaceUnit) + if (!isExportedFromModuleIntefaceUnit(D)) + return LinkageInfo(ModuleLinkage, DefaultVisibility, false); + + return LinkageInfo::external(); +} + static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVComputationKind computation) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && @@ -588,16 +626,18 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (const auto *Var = dyn_cast<VarDecl>(D)) { // Explicitly declared static. if (Var->getStorageClass() == SC_Static) - return LinkageInfo::internal(); + return getInternalLinkageFor(Var); // - a non-inline, non-volatile object or reference that is explicitly // declared const or constexpr and neither explicitly declared extern // nor previously declared to have external linkage; or (there is no // equivalent in C99) + // The C++ modules TS adds "non-exported" to this list. if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && !Var->getType().isVolatileQualified() && - !Var->isInline()) { + !Var->isInline() && + !isExportedFromModuleIntefaceUnit(Var)) { const VarDecl *PrevVar = Var->getPreviousDecl(); if (PrevVar) return getLVForDecl(PrevVar, computation); @@ -605,7 +645,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && !isSingleLineLanguageLinkage(*Var)) - return LinkageInfo::internal(); + return getInternalLinkageFor(Var); } for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar; @@ -615,7 +655,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, return PrevVar->getLinkageAndVisibility(); // Explicitly declared static. if (PrevVar->getStorageClass() == SC_Static) - return LinkageInfo::internal(); + return getInternalLinkageFor(Var); } } else if (const FunctionDecl *Function = D->getAsFunction()) { // C++ [temp]p4: @@ -624,7 +664,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // Explicitly declared static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) - return LinkageInfo(InternalLinkage, DefaultVisibility, false); + return getInternalLinkageFor(Function); } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) { // - a data member of an anonymous union. const VarDecl *VD = IFD->getVarDecl(); @@ -637,7 +677,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, const auto *Var = dyn_cast<VarDecl>(D); const auto *Func = dyn_cast<FunctionDecl>(D); // FIXME: In C++11 onwards, anonymous namespaces should give decls - // within them internal linkage, not unique external linkage. + // within them (including those inside extern "C" contexts) internal + // linkage, not unique external linkage: + // + // C++11 [basic.link]p4: + // An unnamed namespace or a namespace declared directly or indirectly + // within an unnamed namespace has internal linkage. if ((!Var || !isFirstInExternCContext(Var)) && (!Func || !isFirstInExternCContext(Func))) return LinkageInfo::uniqueExternal(); @@ -718,7 +763,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // because of this, but unique-external linkage suits us. if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) { LinkageInfo TypeLV = getLVForType(*Var->getType(), computation); - if (TypeLV.getLinkage() != ExternalLinkage) + if (TypeLV.getLinkage() != ExternalLinkage && + TypeLV.getLinkage() != ModuleLinkage) return LinkageInfo::uniqueExternal(); if (!LV.isVisibilityExplicit()) LV.mergeVisibility(TypeLV); @@ -816,7 +862,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // - a namespace (7.3), unless it is declared within an unnamed // namespace. - } else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) { + // + // We handled names in anonymous namespaces above. + } else if (isa<NamespaceDecl>(D)) { return LV; // By extension, we assign external linkage to Objective-C @@ -1125,6 +1173,8 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, if (const auto *ND = dyn_cast<NamedDecl>(DC)) return getLVForDecl(ND, computation); + // FIXME: We have a closure at TU scope with no context declaration. This + // should probably have no linkage. return LinkageInfo::external(); } @@ -1137,7 +1187,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, // This is a "void f();" which got merged with a file static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) - return LinkageInfo::internal(); + return getInternalLinkageFor(Function); LinkageInfo LV; if (!hasExplicitVisibilityAlready(computation)) { @@ -1226,7 +1276,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, LVComputationKind computation) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) - return LinkageInfo::internal(); + return getInternalLinkageFor(D); // Objective-C: treat all Objective-C declarations as having external // linkage. @@ -1259,8 +1309,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, case Decl::TypeAlias: // A typedef declaration has linkage if it gives a type a name for // linkage purposes. - if (!D->getASTContext().getLangOpts().CPlusPlus || - !cast<TypedefNameDecl>(D) + if (!cast<TypedefNameDecl>(D) ->getAnonDeclWithTypedefName(/*AnyRedecl*/true)) return LinkageInfo::none(); break; @@ -1276,14 +1325,14 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, case Decl::ObjCProperty: case Decl::ObjCPropertyImpl: case Decl::ObjCProtocol: - return LinkageInfo::external(); + return getExternalLinkageFor(D); case Decl::CXXRecord: { const auto *Record = cast<CXXRecordDecl>(D); if (Record->isLambda()) { if (!Record->getLambdaManglingNumber()) { // This lambda has no mangling number, so it's internal. - return LinkageInfo::internal(); + return getInternalLinkageFor(D); } // This lambda has its linkage/visibility determined: @@ -1299,7 +1348,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, const CXXRecordDecl *OuterMostLambda = getOutermostEnclosingLambda(Record); if (!OuterMostLambda->getLambdaManglingNumber()) - return LinkageInfo::internal(); + return getInternalLinkageFor(D); return getLVForClosure( OuterMostLambda->getDeclContext()->getRedeclContext(), @@ -1350,7 +1399,7 @@ public: LVComputationKind computation) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) - return LinkageInfo::internal(); + return getInternalLinkageFor(D); if (computation == LVForLinkageOnly && D->hasCachedLinkage()) return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index a0594a0203625..cd2c83a02f599 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -283,8 +283,10 @@ void Decl::setLexicalDeclContext(DeclContext *DC) { setLocalOwningModule(cast<Decl>(DC)->getOwningModule()); } - assert((!hasOwningModule() || getOwningModule()) && - "hidden declaration has no owning module"); + assert( + (getModuleOwnershipKind() != ModuleOwnershipKind::VisibleWhenImported || + getOwningModule()) && + "hidden declaration has no owning module"); } void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 07d128ba555bc..5cab488822515 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1605,6 +1605,84 @@ CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SC_None, false, false, SourceLocation()); } +CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, + bool IsAppleKext) { + assert(isVirtual() && "this method is expected to be virtual"); + + // When building with -fapple-kext, all calls must go through the vtable since + // the kernel linker can do runtime patching of vtables. + if (IsAppleKext) + return nullptr; + + // If the member function is marked 'final', we know that it can't be + // overridden and can therefore devirtualize it unless it's pure virtual. + if (hasAttr<FinalAttr>()) + return isPure() ? nullptr : this; + + // If Base is unknown, we cannot devirtualize. + if (!Base) + return nullptr; + + // If the base expression (after skipping derived-to-base conversions) is a + // class prvalue, then we can devirtualize. + Base = Base->getBestDynamicClassTypeExpr(); + if (Base->isRValue() && Base->getType()->isRecordType()) + return this; + + // If we don't even know what we would call, we can't devirtualize. + const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType(); + if (!BestDynamicDecl) + return nullptr; + + // There may be a method corresponding to MD in a derived class. + CXXMethodDecl *DevirtualizedMethod = + getCorrespondingMethodInClass(BestDynamicDecl); + + // If that method is pure virtual, we can't devirtualize. If this code is + // reached, the result would be UB, not a direct call to the derived class + // function, and we can't assume the derived class function is defined. + if (DevirtualizedMethod->isPure()) + return nullptr; + + // If that method is marked final, we can devirtualize it. + if (DevirtualizedMethod->hasAttr<FinalAttr>()) + return DevirtualizedMethod; + + // Similarly, if the class itself is marked 'final' it can't be overridden + // and we can therefore devirtualize the member function call. + if (BestDynamicDecl->hasAttr<FinalAttr>()) + return DevirtualizedMethod; + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) + if (VD->getType()->isRecordType()) + // This is a record decl. We know the type and can devirtualize it. + return DevirtualizedMethod; + + return nullptr; + } + + // We can devirtualize calls on an object accessed by a class member access + // expression, since by C++11 [basic.life]p6 we know that it can't refer to + // a derived class object constructed in the same location. + if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base)) + if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl())) + return VD->getType()->isRecordType() ? DevirtualizedMethod : nullptr; + + // Likewise for calls on an object accessed by a (non-reference) pointer to + // member access. + if (auto *BO = dyn_cast<BinaryOperator>(Base)) { + if (BO->isPtrMemOp()) { + auto *MPT = BO->getRHS()->getType()->castAs<MemberPointerType>(); + if (MPT->getPointeeType()->isRecordType()) + return DevirtualizedMethod; + } + } + + // We can't devirtualize the call. + return nullptr; +} + bool CXXMethodDecl::isUsualDeallocationFunction() const { if (getOverloadedOperator() != OO_Delete && getOverloadedOperator() != OO_Array_Delete) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index e836135cf2f9a..0c0c861e5d567 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1665,6 +1665,19 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, return true; } +/// Member pointers are constant expressions unless they point to a +/// non-virtual dllimport member function. +static bool CheckMemberPointerConstantExpression(EvalInfo &Info, + SourceLocation Loc, + QualType Type, + const APValue &Value) { + const ValueDecl *Member = Value.getMemberPointerDecl(); + const auto *FD = dyn_cast_or_null<CXXMethodDecl>(Member); + if (!FD) + return true; + return FD->isVirtual() || !FD->hasAttr<DLLImportAttr>(); +} + /// Check that this core constant expression is of literal type, and if not, /// produce an appropriate diagnostic. static bool CheckLiteralType(EvalInfo &Info, const Expr *E, @@ -1757,6 +1770,9 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal); } + if (Value.isMemberPointer()) + return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value); + // Everything else is fine. return true; } @@ -9508,7 +9524,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Mul: if (Result.isComplexFloat()) { // This is an implementation of complex multiplication according to the - // constraints laid out in C11 Annex G. The implemantion uses the + // constraints laid out in C11 Annex G. The implemention uses the // following naming scheme: // (a + ib) * (c + id) ComplexValue LHS = Result; @@ -9589,7 +9605,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Div: if (Result.isComplexFloat()) { // This is an implementation of complex division according to the - // constraints laid out in C11 Annex G. The implemantion uses the + // constraints laid out in C11 Annex G. The implemention uses the // following naming scheme: // (a + ib) / (c + id) ComplexValue LHS = Result; diff --git a/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp index b746edaf64399..4f4a99794c5b0 100644 --- a/lib/AST/ExternalASTMerger.cpp +++ b/lib/AST/ExternalASTMerger.cpp @@ -180,8 +180,3 @@ void ExternalASTMerger::FindExternalLexicalDecls( }); } -void ExternalASTMerger::CompleteType(TagDecl *Tag) { - SmallVector<Decl *, 0> Result; - FindExternalLexicalDecls(Tag, [](Decl::Kind) { return true; }, Result); - Tag->setHasExternalLexicalStorage(false); -} diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 3f66e58eb868c..66b9940b8b086 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -228,6 +228,13 @@ public: Hash.AddQualType(T); } + void AddDecl(const Decl *D) { + Hash.AddBoolean(D); + if (D) { + Hash.AddDecl(D); + } + } + void Visit(const Decl *D) { ID.AddInteger(D->getKind()); Inherited::Visit(D); @@ -321,6 +328,16 @@ public: void VisitTypeAliasDecl(const TypeAliasDecl *D) { Inherited::VisitTypeAliasDecl(D); } + + void VisitFriendDecl(const FriendDecl *D) { + TypeSourceInfo *TSI = D->getFriendType(); + Hash.AddBoolean(TSI); + if (TSI) { + AddQualType(TSI->getType()); + } else { + AddDecl(D->getFriendDecl()); + } + } }; // Only allow a small portion of Decl's to be processed. Remove this once @@ -335,6 +352,7 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) { case Decl::AccessSpec: case Decl::CXXMethod: case Decl::Field: + case Decl::Friend: case Decl::StaticAssert: case Decl::TypeAlias: case Decl::Typedef: |