]> granicus.if.org Git - clang/commitdiff
This patch causes clang to reject alias attributes that point to undefined
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 22 Oct 2013 13:51:06 +0000 (13:51 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 22 Oct 2013 13:51:06 +0000 (13:51 +0000)
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
lib/CodeGen/CGExprCXX.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/Sema/SemaDeclAttr.cpp
test/Sema/attr-alias-elf.c [new file with mode: 0644]

index 415c4b29633a84d5ef211811e57d3673bfbe6e3d..08240d1568cad6b5d9043272249908db4cbc7f0a 100644 (file)
@@ -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|"
index 567444253c9af3975f4bf995184a674c6257d237..2311e084b72ab8ff32794f03b6dfdb7a72d70e71 100644 (file)
@@ -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<llvm::Function>(CalleeAddr);
   if (Callee->isReplaceableGlobalAllocationFunction() &&
-      Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
+      !Callee->hasAttr<AliasAttr>()) {
     // FIXME: Add addAttribute to CallSite.
     if (llvm::CallInst *CI = dyn_cast<llvm::CallInst>(CallOrInvoke))
       CI->addAttribute(llvm::AttributeSet::FunctionIndex,
index 96ae437ff46f948d2ba251bd313e81a8c3bd0eda..2939b4a3d2ce026e20c061e2f9668471fc5c31aa 100644 (file)
@@ -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<ValueDecl>(D.getDecl());
+    if (Global->hasAttr<AliasAttr>()) {
+      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<AliasAttr>())
-    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<ValueDecl>(GD.getDecl());
+  const AliasAttr *AA = D->getAttr<AliasAttr>();
+  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<llvm::FunctionType>(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<ValueDecl>(GD.getDecl());
   const AliasAttr *AA = D->getAttr<AliasAttr>();
@@ -2100,6 +2125,18 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
     Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
                                     llvm::PointerType::getUnqual(DeclTy), 0);
 
+  llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(Aliasee);
+  if (!GV) {
+    llvm::ConstantExpr *CE = cast<llvm::ConstantExpr>(Aliasee);
+    assert(CE->getOpcode() == llvm::Instruction::BitCast ||
+           CE->getOpcode() == llvm::Instruction::GetElementPtr);
+    GV = cast<llvm::GlobalValue>(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(),
index 066009ca7df81aa5f85abecb948129f6d8aaa177..d2dc8358eaff9ce09987c70a85d44df843d5c19c 100644 (file)
@@ -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);
index a71d3c0d7b5aebf527f55db99c71338b7cee51f7..a08abd9efcf94fb6ebd52d3ebc03de5ed246298c 100644 (file)
@@ -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<AliasAttr>())
+      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 (file)
index 0000000..32e4102
--- /dev/null
@@ -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;