diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:53:39 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:53:39 +0000 | 
| commit | 11edbfca22fe6e8280caeb77832f4dfbb68ed274 (patch) | |
| tree | a3e238dbe004c4ea0f061135a0c1d4430e50c28e /clang/lib/Sema/SemaDecl.cpp | |
| parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) | |
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 34 | 
1 files changed, 24 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e2b921bfe78f..051fad04219f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13088,9 +13088,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {    // C++ [module.import/6] external definitions are not permitted in header    // units.    if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() && -      VDecl->isThisDeclarationADefinition() && +      !VDecl->isInvalidDecl() && VDecl->isThisDeclarationADefinition() &&        VDecl->getFormalLinkage() == Linkage::ExternalLinkage && -      !VDecl->isInline()) { +      !VDecl->isInline() && !VDecl->isTemplated() && +      !isa<VarTemplateSpecializationDecl>(VDecl)) {      Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit);      VDecl->setInvalidDecl();    } @@ -15259,9 +15260,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,    // FIXME: Consider an alternate location for the test where the inlined()    // state is complete.    if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() && +      !FD->isInvalidDecl() && !FD->isInlined() && +      BodyKind != FnBodyKind::Delete && BodyKind != FnBodyKind::Default &&        FD->getFormalLinkage() == Linkage::ExternalLinkage && -      !FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete && -      BodyKind != FnBodyKind::Default && !FD->isInlined()) { +      !FD->isTemplated() && !FD->isTemplateInstantiation()) {      assert(FD->isThisDeclarationADefinition());      Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);      FD->setInvalidDecl(); @@ -16616,8 +16618,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,                 bool &IsDependent, SourceLocation ScopedEnumKWLoc,                 bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,                 bool IsTypeSpecifier, bool IsTemplateParamOrArg, -               OffsetOfKind OOK, UsingShadowDecl *&FoundUsingShadow, -               SkipBodyInfo *SkipBody) { +               OffsetOfKind OOK, SkipBodyInfo *SkipBody) {    // If this is not a definition, it must have a name.    IdentifierInfo *OrigName = Name;    assert((Name != nullptr || TUK == TUK_Definition) && @@ -17052,7 +17053,6 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,      // redefinition if either context is within the other.      if (auto *Shadow = dyn_cast<UsingShadowDecl>(DirectPrevDecl)) {        auto *OldTag = dyn_cast<TagDecl>(PrevDecl); -      FoundUsingShadow = Shadow;        if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend &&            isDeclInScope(Shadow, SearchDC, S, isMemberSpecialization) &&            !(OldTag && isAcceptableTagRedeclContext( @@ -18871,10 +18871,24 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,      ProcessDeclAttributeList(S, Record, Attrs);      // Check to see if a FieldDecl is a pointer to a function. -    auto IsFunctionPointer = [&](const Decl *D) { +    auto IsFunctionPointerOrForwardDecl = [&](const Decl *D) {        const FieldDecl *FD = dyn_cast<FieldDecl>(D); -      if (!FD) +      if (!FD) { +        // Check whether this is a forward declaration that was inserted by +        // Clang. This happens when a non-forward declared / defined type is +        // used, e.g.: +        // +        //   struct foo { +        //     struct bar *(*f)(); +        //     struct bar *(*g)(); +        //   }; +        // +        // "struct bar" shows up in the decl AST as a "RecordDecl" with an +        // incomplete definition. +        if (const auto *TD = dyn_cast<TagDecl>(D)) +          return !TD->isCompleteDefinition();          return false; +      }        QualType FieldType = FD->getType().getDesugaredType(Context);        if (isa<PointerType>(FieldType)) {          QualType PointeeType = cast<PointerType>(FieldType)->getPointeeType(); @@ -18888,7 +18902,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,      if (!getLangOpts().CPlusPlus &&          (Record->hasAttr<RandomizeLayoutAttr>() ||           (!Record->hasAttr<NoRandomizeLayoutAttr>() && -          llvm::all_of(Record->decls(), IsFunctionPointer))) && +          llvm::all_of(Record->decls(), IsFunctionPointerOrForwardDecl))) &&          !Record->isUnion() && !getLangOpts().RandstructSeed.empty() &&          !Record->isRandomized()) {        SmallVector<Decl *, 32> NewDeclOrdering;  | 
