"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|"
#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"
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();
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
/// 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;
/// was deferred.
void EmitDeferred();
+ void checkAliases();
+
/// EmitDeferredVTables - Emit any vtables which we deferred and
/// still have a use for.
void EmitDeferredVTables();
--- /dev/null
+// 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;