diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index eda6e161954..d2a2bb20206 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2243,6 +2243,19 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); + // Microsoft docs say: + // "If a base-class has a code_seg attribute, derived classes must have the + // same attribute." + const auto *BaseCSA = CXXBaseDecl->getAttr<CodeSegAttr>(); + const auto *DerivedCSA = Class->getAttr<CodeSegAttr>(); + if ((DerivedCSA || BaseCSA) && + (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) { + Diag(Class->getLocation(), diag::err_mismatched_code_seg_base); + Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here) + << CXXBaseDecl; + return nullptr; + } + // A class which contains a flexible array member is not suitable for use as a // base class: // - If the layout determines that a base comes before another base, @@ -5614,6 +5627,16 @@ static void checkForMultipleExportedDefaultConstructors(Sema &S, } } +void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) { + // Mark any compiler-generated routines with the implicit code_seg attribute. + for (auto *Method : Class->methods()) { + if (Method->isUserProvided()) + continue; + if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true)) + Method->addAttr(A); + } +} + /// Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); @@ -6122,6 +6145,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } checkClassLevelDLLAttribute(Record); + checkClassLevelCodeSegAttribute(Record); bool ClangABICompat4 = Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4; @@ -14589,6 +14613,16 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, } } + // Virtual overrides must have the same code_seg. + const auto *OldCSA = Old->getAttr<CodeSegAttr>(); + const auto *NewCSA = New->getAttr<CodeSegAttr>(); + if ((NewCSA || OldCSA) && + (!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) { + Diag(New->getLocation(), diag::err_mismatched_code_seg_override); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv(); // If the calling conventions match, everything is fine |