Skip to content

Commit fecfc83

Browse files
pcctstellar
authored andcommitted
AST: Move __va_list tag back to std conditionally on AArch64.
In post-commit feedback on D104830 Jessica Clarke pointed out that unconditionally adding __va_list to the std namespace caused namespace debug info to be emitted in C, which is not only inappropriate but turned out to confuse the dtrace tool. Therefore, move __va_list back to std only in C++ so that the correct debug info is generated. We also considered moving __va_list to the top level unconditionally but this would contradict the specification and be visible to AST matchers and such, so make it conditional on the language mode. To avoid breaking name mangling for __va_list, teach the Itanium name mangler to always mangle it as if it were in the std namespace when targeting ARM architectures. This logic is not needed for the Microsoft name mangler because Microsoft platforms define va_list as a typedef of char *. Depends on D116773 Differential Revision: https://reviews.llvm.org/D116774
1 parent 725d57c commit fecfc83

File tree

5 files changed

+162
-139
lines changed

5 files changed

+162
-139
lines changed

clang/lib/AST/ASTContext.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8547,21 +8547,18 @@ static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) {
85478547

85488548
static TypedefDecl *
85498549
CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) {
8550+
// struct __va_list
85508551
RecordDecl *VaListTagDecl = Context->buildImplicitRecord("__va_list");
8551-
// namespace std { struct __va_list {
8552-
// Note that we create the namespace even in C. This is intentional so that
8553-
// the type is consistent between C and C++, which is important in cases where
8554-
// the types need to match between translation units (e.g. with
8555-
// -fsanitize=cfi-icall). Ideally we wouldn't have created this namespace at
8556-
// all, but it's now part of the ABI (e.g. in mangled names), so we can't
8557-
// change it.
8558-
auto *NS = NamespaceDecl::Create(
8559-
const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(),
8560-
/*Inline*/ false, SourceLocation(), SourceLocation(),
8561-
&Context->Idents.get("std"),
8562-
/*PrevDecl*/ nullptr);
8563-
NS->setImplicit();
8564-
VaListTagDecl->setDeclContext(NS);
8552+
if (Context->getLangOpts().CPlusPlus) {
8553+
// namespace std { struct __va_list {
8554+
auto *NS = NamespaceDecl::Create(
8555+
const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(),
8556+
/*Inline*/ false, SourceLocation(), SourceLocation(),
8557+
&Context->Idents.get("std"),
8558+
/*PrevDecl*/ nullptr);
8559+
NS->setImplicit();
8560+
VaListTagDecl->setDeclContext(NS);
8561+
}
85658562

85668563
VaListTagDecl->startDefinition();
85678564

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
7171
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
7272
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
7373
const DiscriminatorOverrideTy DiscriminatorOverride = nullptr;
74+
NamespaceDecl *StdNamespace = nullptr;
7475

7576
bool NeedsUniqueInternalLinkageNames = false;
7677

@@ -194,6 +195,8 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
194195
return DiscriminatorOverride;
195196
}
196197

198+
NamespaceDecl *getStdNamespace();
199+
197200
const DeclContext *getEffectiveDeclContext(const Decl *D);
198201
const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
199202
return getEffectiveDeclContext(cast<Decl>(DC));
@@ -590,6 +593,18 @@ class CXXNameMangler {
590593

591594
}
592595

596+
NamespaceDecl *ItaniumMangleContextImpl::getStdNamespace() {
597+
if (!StdNamespace) {
598+
StdNamespace = NamespaceDecl::Create(
599+
getASTContext(), getASTContext().getTranslationUnitDecl(),
600+
/*Inline*/ false, SourceLocation(), SourceLocation(),
601+
&getASTContext().Idents.get("std"),
602+
/*PrevDecl*/ nullptr);
603+
StdNamespace->setImplicit();
604+
}
605+
return StdNamespace;
606+
}
607+
593608
/// Retrieve the declaration context that should be used when mangling the given
594609
/// declaration.
595610
const DeclContext *
@@ -614,6 +629,17 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) {
614629
return ContextParam->getDeclContext();
615630
}
616631

632+
// On ARM and AArch64, the va_list tag is always mangled as if in the std
633+
// namespace. We do not represent va_list as actually being in the std
634+
// namespace in C because this would result in incorrect debug info in C,
635+
// among other things. It is important for both languages to have the same
636+
// mangling in order for -fsanitize=cfi-icall to work.
637+
if (D == getASTContext().getVaListTagDecl()) {
638+
const llvm::Triple &T = getASTContext().getTargetInfo().getTriple();
639+
if (T.isARM() || T.isThumb() || T.isAArch64())
640+
return getStdNamespace();
641+
}
642+
617643
const DeclContext *DC = D->getDeclContext();
618644
if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) ||
619645
isa<OMPDeclareMapperDecl>(DC)) {

0 commit comments

Comments
 (0)