diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 37 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 6 | ||||
-rw-r--r-- | clang/test/Sema/attr-alias-elf.c | 54 |
4 files changed, 101 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 92180e60514..8d8602d41cc 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2015,6 +2015,10 @@ 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 err_cyclic_alias : Error< + "alias definition is part of a cycle">; 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/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 96ae437ff46..d0f34dddca3 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/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" @@ -171,8 +172,42 @@ void CodeGenModule::createCUDARuntime() { CUDARuntime = CreateNVCUDARuntime(*this); } +void CodeGenModule::checkAliases() { + bool Error = false; + for (std::vector<GlobalDecl>::iterator I = Aliases.begin(), + E = Aliases.end(); I != E; ++I) { + const GlobalDecl &GD = *I; + const ValueDecl *D = cast<ValueDecl>(GD.getDecl()); + const AliasAttr *AA = D->getAttr<AliasAttr>(); + StringRef MangledName = getMangledName(GD); + llvm::GlobalValue *Entry = GetGlobalValue(MangledName); + llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry); + llvm::GlobalValue *GV = Alias->getAliasedGlobal(); + if (GV->isDeclaration()) { + Error = true; + getDiags().Report(AA->getLocation(), diag::err_alias_to_undefined); + } else if (!Alias->resolveAliasedGlobal(/*stopOnWeak*/ false)) { + Error = true; + getDiags().Report(AA->getLocation(), diag::err_cyclic_alias); + } + } + if (!Error) + return; + + for (std::vector<GlobalDecl>::iterator I = Aliases.begin(), + E = Aliases.end(); I != E; ++I) { + const GlobalDecl &GD = *I; + StringRef MangledName = getMangledName(GD); + llvm::GlobalValue *Entry = GetGlobalValue(MangledName); + llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry); + Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType())); + Alias->eraseFromParent(); + } +} + void CodeGenModule::Release() { EmitDeferred(); + checkAliases(); EmitCXXGlobalInitFunc(); EmitCXXGlobalDtorFunc(); EmitCXXThreadLocalInitFunc(); @@ -2088,6 +2123,8 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { if (Entry && !Entry->isDeclaration()) return; + Aliases.push_back(GD); + llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType()); // Create a reference to the named value. This ensures that it is emitted diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 066009ca7df..25aaae61e48 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -275,6 +275,10 @@ class CodeGenModule : public CodeGenTypeCache { /// is done. std::vector<GlobalDecl> DeferredDeclsToEmit; + /// List of alias we have emitted. Used to make sure that what they point to + /// is defined once we get to the end of the of the translation unit. + std::vector<GlobalDecl> Aliases; + /// DeferredVTables - A queue of (optional) vtables to consider emitting. std::vector<const CXXRecordDecl*> DeferredVTables; @@ -1077,6 +1081,8 @@ private: /// was deferred. void EmitDeferred(); + void checkAliases(); + /// EmitDeferredVTables - Emit any vtables which we deferred and /// still have a use for. void EmitDeferredVTables(); diff --git a/clang/test/Sema/attr-alias-elf.c b/clang/test/Sema/attr-alias-elf.c new file mode 100644 index 00000000000..88bd7b70958 --- /dev/null +++ b/clang/test/Sema/attr-alias-elf.c @@ -0,0 +1,54 @@ +// 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); + + +void f4() __attribute__((alias("g4"))); +void g4() {} +void h4() __attribute__((alias("f4"))); + +void f5() __attribute__((alias("g5"))); +void h5() __attribute__((alias("f5"))); +void g5() {} + +void g6() {} +void f6() __attribute__((alias("g6"))); +void h6() __attribute__((alias("f6"))); + +void g7() {} +void h7() __attribute__((alias("f7"))); +void f7() __attribute__((alias("g7"))); + +void h8() __attribute__((alias("f8"))); +void g8() {} +void f8() __attribute__((alias("g8"))); + +void h9() __attribute__((alias("f9"))); +void f9() __attribute__((alias("g9"))); +void g9() {} + +void f10() __attribute__((alias("g10"))); // expected-error {{alias definition is part of a cycle}} +void g10() __attribute__((alias("f10"))); // expected-error {{alias definition is part of a cycle}} + +// FIXME: This could be a bit better, h10 is not part of the cycle, it points +// to it. +void h10() __attribute__((alias("g10"))); // expected-error {{alias definition is part of a cycle}} + +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; |