From e37bf44c8012f36f900955d8513e03791803045e Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 22 Oct 2013 13:51:06 +0000 Subject: [PATCH] This patch causes clang to reject alias attributes that point to undefined names. For example, with this patch we now reject void f1(void) __attribute__((alias("g1"))); This patch is implemented in CodeGen. It is quiet a bit simpler and more compatible with gcc than implementing it in Sema. The downside is that the errors only fire during -emit-llvm. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193161 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ lib/CodeGen/CGExprCXX.cpp | 3 +- lib/CodeGen/CodeGenModule.cpp | 39 +++++++++++++++++++++- lib/CodeGen/CodeGenModule.h | 1 + lib/Sema/SemaDeclAttr.cpp | 7 ++++ test/Sema/attr-alias-elf.c | 22 ++++++++++++ 6 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 test/Sema/attr-alias-elf.c diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 415c4b2963..08240d1568 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2015,6 +2015,8 @@ def err_attribute_weakref_without_alias : Error< "weakref declaration of '%0' must also have an alias attribute">; def err_alias_not_supported_on_darwin : Error < "only weak aliases are supported on darwin">; +def err_alias_to_undefined : Error< + "alias must point to a defined variable or function">; def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 567444253c..2311e084b7 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -929,9 +929,8 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF, /// to a replaceable global allocation function. /// /// We model such elidable calls with the 'builtin' attribute. - llvm::Function *Fn = dyn_cast(CalleeAddr); if (Callee->isReplaceableGlobalAllocationFunction() && - Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) { + !Callee->hasAttr()) { // FIXME: Add addAttribute to CallSite. if (llvm::CallInst *CI = dyn_cast(CallOrInvoke)) CI->addAttribute(llvm::AttributeSet::FunctionIndex, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 96ae437ff4..2939b4a3d2 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -37,6 +37,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/Triple.h" #include "llvm/IR/CallingConv.h" @@ -933,6 +934,12 @@ void CodeGenModule::EmitDeferred() { GlobalDecl D = DeferredDeclsToEmit.back(); DeferredDeclsToEmit.pop_back(); + const ValueDecl *Global = cast(D.getDecl()); + if (Global->hasAttr()) { + EmitAliasDefinition(D); + continue; + } + // Check to see if we've already emitted this. This is necessary // for a couple of reasons: first, decls can end up in the // deferred-decls queue multiple times, and second, decls can end @@ -1098,7 +1105,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // If this is an alias definition (which otherwise looks like a declaration) // emit it now. if (Global->hasAttr()) - return EmitAliasDefinition(GD); + return scheduleAliasDefinitionEmission(GD); // If this is CUDA, be selective about which declarations we emit. if (LangOpts.CUDA) { @@ -2075,6 +2082,24 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { AddGlobalAnnotations(D, Fn); } +void CodeGenModule::scheduleAliasDefinitionEmission(GlobalDecl GD) { + const ValueDecl *D = cast(GD.getDecl()); + const AliasAttr *AA = D->getAttr(); + assert(AA && "Not an alias?"); + + // Schedule it. + DeferredDeclsToEmit.push_back(GD); + + llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType()); + + // Cause the aliasee emission to be scheduled. + if (isa(DeclTy)) + GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GD, /*ForVTable=*/false); + else + GetOrCreateLLVMGlobal(AA->getAliasee(), + llvm::PointerType::getUnqual(DeclTy), 0); +} + void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { const ValueDecl *D = cast(GD.getDecl()); const AliasAttr *AA = D->getAttr(); @@ -2100,6 +2125,18 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), llvm::PointerType::getUnqual(DeclTy), 0); + llvm::GlobalValue *GV = dyn_cast(Aliasee); + if (!GV) { + llvm::ConstantExpr *CE = cast(Aliasee); + assert(CE->getOpcode() == llvm::Instruction::BitCast || + CE->getOpcode() == llvm::Instruction::GetElementPtr); + GV = cast(CE->getOperand(0)); + } + if (GV->isDeclaration()) { + getDiags().Report(AA->getLocation(), diag::err_alias_to_undefined); + return; + } + // Create the new alias itself, but don't set a name yet. llvm::GlobalValue *GA = new llvm::GlobalAlias(Aliasee->getType(), diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 066009ca7d..d2dc8358ea 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -1024,6 +1024,7 @@ private: void EmitGlobalFunctionDefinition(GlobalDecl GD); void EmitGlobalVarDefinition(const VarDecl *D); + void scheduleAliasDefinitionEmission(GlobalDecl GD); void EmitAliasDefinition(GlobalDecl GD); void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D); void EmitObjCIvarInitializations(ObjCImplementationDecl *D); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index a71d3c0d7b..a08abd9efc 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -5020,6 +5020,13 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { W.setUsed(true); if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) IdentifierInfo *NDId = ND->getIdentifier(); + + // FIXME: we should reject this (pr17640). + NamedDecl *Aliasee = LookupSingleName(TUScope, W.getAlias(), + W.getLocation(), LookupOrdinaryName); + if (Aliasee && Aliasee->hasAttr()) + return; + NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation()); NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context, NDId->getName())); diff --git a/test/Sema/attr-alias-elf.c b/test/Sema/attr-alias-elf.c new file mode 100644 index 0000000000..32e41027c8 --- /dev/null +++ b/test/Sema/attr-alias-elf.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -fsyntax-only -verify -emit-llvm-only %s + +void f1(void) __attribute__((alias("g1"))); +void g1(void) { +} + +void f2(void) __attribute__((alias("g2"))); // expected-error {{alias must point to a defined variable or function}} + + +void f3(void) __attribute__((alias("g3"))); // expected-error {{alias must point to a defined variable or function}} +void g3(void); + +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}} + +extern int a3 __attribute__((alias("b3"))); // expected-error {{alias must point to a defined variable or function}} +extern int b3; + +extern int a4 __attribute__((alias("b4"))); // expected-error {{alias must point to a defined variable or function}} +typedef int b4; -- 2.40.0