https://github.com/temyurchenko updated https://github.com/llvm/llvm-project/pull/93913
>From 9b18a5c4132cf093fc9b32f6b4dcfe406d485e3d Mon Sep 17 00:00:00 2001 From: Artem Yurchenko <artemyurche...@zoho.com> Date: Thu, 6 Jun 2024 20:20:19 -0400 Subject: [PATCH] enforce the unbraced `extern <lang>` invariant Quoting 9.11.8: > A declaration directly contained in a linkage-specification is > treated as if it contains the extern specifier (9.2.2) for the > purpose of determining the linkage of the declared name and whether > it is a definition. Such a declaration shall not specify a storage > class. So, the invariant is that function and variable declarations within an unbraced language linkage specification have `StorageClass` set to `SC_None`. Problem: in several places the invariant was broken. Solution: remove the explicit `SC_Extern` specification. Note, that my changes result in the `extern` being implicit in some functions that are not contained in a language linkage specification. --- clang/lib/AST/Decl.cpp | 26 ++++++++++++++++--- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaExpr.cpp | 2 +- .../Clang/ClangExpressionParser.cpp | 2 +- .../Clang/NameSearchContext.cpp | 3 ++- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 1f19dadafa44e..ebaeed0e818e1 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -576,13 +576,19 @@ template <typename T> static bool isFirstInExternCContext(T *D) { return First->isInExternCContext(); } -static bool isSingleLineLanguageLinkage(const Decl &D) { - if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext())) +static bool isUnbracedLanguageLinkage(const DeclContext *DC) { + if (!DC) + return false; + if (const auto *SD = dyn_cast<LinkageSpecDecl>(DC)) if (!SD->hasBraces()) return true; return false; } +static bool hasUnbracedLanguageLinkage(const Decl &D) { + return isUnbracedLanguageLinkage(D.getDeclContext()); +} + static bool isDeclaredInModuleInterfaceOrPartition(const NamedDecl *D) { if (auto *M = D->getOwningModule()) return M->isInterfaceOrPartition(); @@ -644,7 +650,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && - !isSingleLineLanguageLinkage(*Var)) + !hasUnbracedLanguageLinkage(*Var)) return LinkageInfo::internal(); } @@ -2133,6 +2139,12 @@ VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, "ParmVarDeclBitfields too large!"); static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned), "NonParmVarDeclBitfields too large!"); + + // The unbraced `extern "C"` invariant is that the storage class + // specifier is omitted in the source code, i.e. SC_None (but is, + // implicitly, `extern`). + assert(!isUnbracedLanguageLinkage(DC) || SC == SC_None); + AllBits = 0; VarDeclBits.SClass = SC; // Everything else is implicitly initialized to false. @@ -2316,7 +2328,7 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // A declaration directly contained in a linkage-specification is treated // as if it contains the extern specifier for the purpose of determining // the linkage of the declared name and whether it is a definition. - if (isSingleLineLanguageLinkage(*this)) + if (hasUnbracedLanguageLinkage(*this)) return DeclarationOnly; // C99 6.9.2p2: @@ -3041,6 +3053,12 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0), EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) { assert(T.isNull() || T->isFunctionType()); + + // The unbraced `extern "C"` invariant is that the storage class + // specifier is omitted in the source code, i.e. SC_None (but is, + // implicitly, `extern`). + assert(!isUnbracedLanguageLinkage(DC) || S == SC_None); + FunctionDeclBits.SClass = S; FunctionDeclBits.IsInline = isInlineSpecified; FunctionDeclBits.IsInlineSpecified = isInlineSpecified; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 4b9b735f1cfb4..4e2f02ba7007a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2380,7 +2380,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type, } FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type, - /*TInfo=*/nullptr, SC_Extern, + /*TInfo=*/nullptr, SC_None, getCurFPFeatures().isFPConstrained(), false, Type->isFunctionProtoType()); New->setImplicit(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 76145f291887c..60075120fe030 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6286,7 +6286,7 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, FunctionDecl *OverloadDecl = FunctionDecl::Create( Context, Parent, FDecl->getLocation(), FDecl->getLocation(), FDecl->getIdentifier(), OverloadTy, - /*TInfo=*/nullptr, SC_Extern, Sema->getCurFPFeatures().isFPConstrained(), + /*TInfo=*/nullptr, SC_None, Sema->getCurFPFeatures().isFPConstrained(), false, /*hasPrototype=*/true); SmallVector<ParmVarDecl*, 16> Params; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 1dd98567f8d69..12aa1bd60bcb7 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -881,7 +881,7 @@ class CodeComplete : public CodeCompleteConsumer { else ToInsert += "("; raw_string_ostream OS(Description); - F->print(OS, m_desc_policy, false); + F->print(OS, m_desc_policy); OS.flush(); } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) { Description = V->getType().getAsString(m_desc_policy); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp b/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp index da59855a9f162..e02b418b1e793 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp @@ -77,7 +77,8 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, clang::FunctionDecl *func_decl = FunctionDecl::Create( ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type, - nullptr, SC_Extern, /*UsesFPIntrin=*/false, isInlineSpecified, hasWrittenPrototype, + nullptr, SC_None, /*UsesFPIntrin=*/false, isInlineSpecified, + hasWrittenPrototype, isConstexprSpecified ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits