Author: Dhruv Chawla Date: 2023-03-06T08:59:02-08:00 New Revision: 9306ef9750b7a319d59f6d3e4977e01e39b8f161
URL: https://github.com/llvm/llvm-project/commit/9306ef9750b7a319d59f6d3e4977e01e39b8f161 DIFF: https://github.com/llvm/llvm-project/commit/9306ef9750b7a319d59f6d3e4977e01e39b8f161.diff LOG: [clang][alias|ifunc]: Add a diagnostic for mangled names When an alias or ifunc attribute refers to a function name that is mangled, a diagnostic is emitted to suggest the mangled name as a replacement for the given function name for every matching name in the current TU. Fixes #59164 Differential Revision: https://reviews.llvm.org/D143803 Added: clang/test/CodeGen/alias.cpp clang/test/CodeGen/attr-ifunc.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticFrontendKinds.td clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/attr-ifunc.c clang/test/Sema/attr-alias-elf.c clang/test/SemaCXX/externc-ifunc-resolver.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cd91fbe78bb2b..c096133029682 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -157,6 +157,8 @@ Improvements to Clang's diagnostics ``-Wno-deprecated-this-capture``. - Clang had failed to emit some ``-Wundefined-internal`` for members of a local class if that class was first introduced with a forward declaration. +- Diagnostic notes and fix-its are now generated for ``ifunc``/``alias`` attributes + which point to functions whose names are mangled. Bug Fixes in This Version ------------------------- diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index c2bce23e9a53f..b35c697701c1d 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -278,6 +278,10 @@ def err_avx_calling_convention : Error<warn_avx_calling_convention.Summary>; def err_alias_to_undefined : Error< "%select{alias|ifunc}0 must point to a defined " "%select{variable or |}1function">; +def note_alias_requires_mangled_name : Note< + "the %select{function or variable|function}0 specified in an %select{alias|ifunc}1 must refer to its mangled name">; +def note_alias_mangled_name_alternative: Note< + "function by that name is mangled as \"%0\"">; def warn_alias_to_weak_alias : Warning< "%select{alias|ifunc}2 will always resolve to %0 even if weak definition of " "%1 is overridden">, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 90c9df4ea4423..b512fb576a2c0 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -338,10 +338,11 @@ static const llvm::GlobalValue *getAliasedGlobal(const llvm::GlobalValue *GV) { return FinalGV; } -static bool checkAliasedGlobal(DiagnosticsEngine &Diags, - SourceLocation Location, bool IsIFunc, - const llvm::GlobalValue *Alias, - const llvm::GlobalValue *&GV) { +static bool checkAliasedGlobal( + DiagnosticsEngine &Diags, SourceLocation Location, bool IsIFunc, + const llvm::GlobalValue *Alias, const llvm::GlobalValue *&GV, + const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames, + SourceRange AliasRange) { GV = getAliasedGlobal(Alias); if (!GV) { Diags.Report(Location, diag::err_cyclic_alias) << IsIFunc; @@ -350,6 +351,22 @@ static bool checkAliasedGlobal(DiagnosticsEngine &Diags, if (GV->isDeclaration()) { Diags.Report(Location, diag::err_alias_to_undefined) << IsIFunc << IsIFunc; + Diags.Report(Location, diag::note_alias_requires_mangled_name) + << IsIFunc << IsIFunc; + // Provide a note if the given function is not found and exists as a + // mangled name. + for (const auto &[Decl, Name] : MangledDeclNames) { + if (const auto *ND = dyn_cast<NamedDecl>(Decl.getDecl())) { + if (ND->getName() == GV->getName()) { + Diags.Report(Location, diag::note_alias_mangled_name_alternative) + << Name + << FixItHint::CreateReplacement( + AliasRange, + (Twine(IsIFunc ? "ifunc" : "alias") + "(\"" + Name + "\")") + .str()); + } + } + } return false; } @@ -381,16 +398,19 @@ void CodeGenModule::checkAliases() { for (const GlobalDecl &GD : Aliases) { const auto *D = cast<ValueDecl>(GD.getDecl()); SourceLocation Location; + SourceRange Range; bool IsIFunc = D->hasAttr<IFuncAttr>(); - if (const Attr *A = D->getDefiningAttr()) + if (const Attr *A = D->getDefiningAttr()) { Location = A->getLocation(); - else + Range = A->getRange(); + } else llvm_unreachable("Not an alias or ifunc?"); StringRef MangledName = getMangledName(GD); llvm::GlobalValue *Alias = GetGlobalValue(MangledName); const llvm::GlobalValue *GV = nullptr; - if (!checkAliasedGlobal(Diags, Location, IsIFunc, Alias, GV)) { + if (!checkAliasedGlobal(Diags, Location, IsIFunc, Alias, GV, + MangledDeclNames, Range)) { Error = true; continue; } diff --git a/clang/test/CodeGen/alias.cpp b/clang/test/CodeGen/alias.cpp new file mode 100644 index 0000000000000..17c1e1ae32f03 --- /dev/null +++ b/clang/test/CodeGen/alias.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-linux -verify -emit-llvm-only %s +// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s + +void *f1_ifunc(void) { return nullptr; } +void f1(void) __attribute__((alias("f1_ifunc"))); +// expected-error@-1 {{alias must point to a defined variable or function}} +// expected-note@-2 {{must refer to its mangled name}} +// expected-note@-3 {{function by that name is mangled as}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:30-[[@LINE-4]]:47}:"alias(\"_Z8f1_ifuncv\")" + +void *f6_resolver_resolver(void) { return 0; } +void *f6_resolver(void) __attribute__((alias("f6_resolver_resolver"))); +// expected-error@-1 {{alias must point to a defined variable or function}} +// expected-note@-2 {{must refer to its mangled name}} +// expected-note@-3 {{function by that name is mangled as}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:40-[[@LINE-4]]:69}:"alias(\"_Z20f6_resolver_resolverv\")" +void f6(void) __attribute__((alias("f6_resolver"))); +// expected-error@-1 {{alias must point to a defined variable or function}} +// expected-note@-2 {{must refer to its mangled name}} +// expected-note@-3 {{function by that name is mangled as}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:30-[[@LINE-4]]:50}:"alias(\"_Z11f6_resolverv\")" + +__attribute__((unused, alias("resolver"), deprecated("hahahaha, isn't C great?"))) +void func(); +// expected-error@-2 {{alias must point to a defined variable or function}} +// expected-note@-3 {{must refer to its mangled name}} + diff --git a/clang/test/CodeGen/attr-ifunc.c b/clang/test/CodeGen/attr-ifunc.c index a0659ae773dd1..4f8fe13530fdb 100644 --- a/clang/test/CodeGen/attr-ifunc.c +++ b/clang/test/CodeGen/attr-ifunc.c @@ -12,6 +12,7 @@ void bar(void) __attribute__((ifunc("foo"))); void *f1_ifunc(void); void f1(void) __attribute__((ifunc("f1_ifunc"))); // expected-error@-1 {{ifunc must point to a defined function}} +// expected-note@-2 {{must refer to its mangled name}} void *f2_a(void) __attribute__((alias("f2_b"))); void *f2_b(void) __attribute__((ifunc("f2_a"))); diff --git a/clang/test/CodeGen/attr-ifunc.cpp b/clang/test/CodeGen/attr-ifunc.cpp new file mode 100644 index 0000000000000..5b5b2c14b4074 --- /dev/null +++ b/clang/test/CodeGen/attr-ifunc.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only %s +// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s + +void *f1_ifunc(void) { return nullptr; } +void f1(void) __attribute__((ifunc("f1_ifunc"))); +// expected-error@-1 {{ifunc must point to a defined function}} +// expected-note@-2 {{must refer to its mangled name}} +// expected-note@-3 {{function by that name is mangled as}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:30-[[@LINE-4]]:47}:"ifunc(\"_Z8f1_ifuncv\")" + +void *f6_resolver_resolver(void) { return 0; } +void *f6_resolver(void) __attribute__((ifunc("f6_resolver_resolver"))); +// expected-error@-1 {{ifunc must point to a defined function}} +// expected-note@-2 {{must refer to its mangled name}} +// expected-note@-3 {{function by that name is mangled as}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:40-[[@LINE-4]]:69}:"ifunc(\"_Z20f6_resolver_resolverv\")" +void f6(void) __attribute__((ifunc("f6_resolver"))); +// expected-error@-1 {{ifunc must point to a defined function}} +// expected-note@-2 {{must refer to its mangled name}} +// expected-note@-3 {{function by that name is mangled as}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:30-[[@LINE-4]]:50}:"ifunc(\"_Z11f6_resolverv\")" + +__attribute__((unused, ifunc("resolver"), deprecated("hahahaha, isn't C great?"))) +void func(); +// expected-error@-2 {{ifunc must point to a defined function}} +// expected-note@-3 {{must refer to its mangled name}} + diff --git a/clang/test/Sema/attr-alias-elf.c b/clang/test/Sema/attr-alias-elf.c index 9fcd872f9ebde..6b629e1b509ae 100644 --- a/clang/test/Sema/attr-alias-elf.c +++ b/clang/test/Sema/attr-alias-elf.c @@ -5,9 +5,10 @@ void g1(void) { } void f2(void) __attribute__((alias("g2"))); // expected-error {{alias must point to a defined variable or function}} - +// expected-note@-1 {{must refer to its mangled name}} void f3(void) __attribute__((alias("g3"))); // expected-error {{alias must point to a defined variable or function}} +// expected-note@-1 {{must refer to its mangled name}} void g3(void); @@ -46,11 +47,14 @@ extern int a1 __attribute__((alias("b1"))); int b1 = 42; extern int a2 __attribute__((alias("b2"))); // expected-error {{alias must point to a defined variable or function}} +// expected-note@-1 {{must refer to its mangled name}} extern int a3 __attribute__((alias("b3"))); // expected-error {{alias must point to a defined variable or function}} +// expected-note@-1 {{must refer to its mangled name}} extern int b3; extern int a4 __attribute__((alias("b4"))); // expected-error {{alias must point to a defined variable or function}} +// expected-note@-1 {{must refer to its mangled name}} typedef int b4; void test2_bar() {} diff --git a/clang/test/SemaCXX/externc-ifunc-resolver.cpp b/clang/test/SemaCXX/externc-ifunc-resolver.cpp index 70c21b0ac7f9b..aa44525bde2ca 100644 --- a/clang/test/SemaCXX/externc-ifunc-resolver.cpp +++ b/clang/test/SemaCXX/externc-ifunc-resolver.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -emit-llvm-only -triple x86_64-linux-gnu -verify %s +// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s extern "C" { __attribute__((used)) static void *resolve_foo() { return 0; } @@ -12,5 +13,10 @@ __attribute__((used)) static void *resolve_foo() { return 0; } // some way to improve this diagnostic (likely by diagnosing when we decide // this case suppresses alias creation). __attribute__((ifunc("resolve_foo"))) void foo(); // expected-error{{ifunc must point to a defined function}} +// expected-note@-1 {{must refer to its mangled name}} +// expected-note@-2 {{function by that name is mangled as}} +// expected-note@-3 {{function by that name is mangled as}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:16-[[@LINE-4]]:36}:"ifunc(\"_ZL11resolve_foov\")" +// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:16-[[@LINE-5]]:36}:"ifunc(\"_ZN2NSL11resolve_fooEv\")" } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits