[cfe-commits] r61437 - in /cfe/trunk: include/clang/AST/Attr.h include/clang/Basic/DiagnosticKinds.def lib/CodeGen/CodeGenModule.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclAttr.cpp test/CodeGen/dllimport-dllexport.c test/Sema/dllimmport-dllexport.c
Anton Korobeynikov
asl at math.spbu.ru
Thu Dec 25 16:52:03 PST 2008
Author: asl
Date: Thu Dec 25 18:52:02 2008
New Revision: 61437
URL: http://llvm.org/viewvc/llvm-project?rev=61437&view=rev
Log:
Add full dllimport / dllexport support: both sema checks and codegen.
Patch by Ilya Okonsky
Added:
cfe/trunk/test/CodeGen/dllimport-dllexport.c
cfe/trunk/test/Sema/dllimmport-dllexport.c
Modified:
cfe/trunk/include/clang/AST/Attr.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=61437&r1=61436&r2=61437&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Thu Dec 25 18:52:02 2008
@@ -57,16 +57,17 @@
private:
Attr *Next;
Kind AttrKind;
-
+ bool Inherited : 1;
+
protected:
- Attr(Kind AK) : Next(0), AttrKind(AK) {}
+ Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
public:
virtual ~Attr() {
delete Next;
}
Kind getKind() const { return AttrKind; }
-
+
bool hasKind(Kind kind) const {
return AttrKind == kind;
}
@@ -74,7 +75,10 @@
Attr *getNext() { return Next; }
const Attr *getNext() const { return Next; }
void setNext(Attr *next) { Next = next; }
-
+
+ bool isInherited() const { return Inherited; }
+ void setInherited(bool value) { Inherited = value; }
+
void addAttr(Attr *attr) {
assert((attr != 0) && "addAttr(): attr is null");
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=61437&r1=61436&r2=61437&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu Dec 25 18:52:02 2008
@@ -803,6 +803,8 @@
"Objective-C declarations may only appear in global scope")
// Attributes
+DIAG(err_attribute_can_be_applied_only_to_symbol_declaration, ERROR,
+ "%0 attribute can be applied only to symbol declaration")
DIAG(err_attributes_are_not_compatible, ERROR,
"%0 and %1 attributes are not compatible")
DIAG(err_attribute_wrong_number_arguments, ERROR,
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=61437&r1=61436&r2=61437&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Dec 25 18:52:02 2008
@@ -218,17 +218,30 @@
// approximation of what we really want.
if (!ForDefinition) {
// Only a few attributes are set on declarations.
- if (D->getAttr<DLLImportAttr>())
- GV->setLinkage(llvm::Function::DLLImportLinkage);
+ if (D->getAttr<DLLImportAttr>()) {
+ // The dllimport attribute is overridden by a subsequent declaration as
+ // dllexport.
+ if (!D->getAttr<DLLExportAttr>())
+ // dllimport attribute can be applied only to function decls, not to
+ // definitions.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (!FD->getBody())
+ GV->setLinkage(llvm::Function::DLLImportLinkage);
+ } else
+ GV->setLinkage(llvm::Function::DLLImportLinkage);
+ }
} else {
if (IsInternal) {
GV->setLinkage(llvm::Function::InternalLinkage);
} else {
- if (D->getAttr<DLLImportAttr>())
- GV->setLinkage(llvm::Function::DLLImportLinkage);
- else if (D->getAttr<DLLExportAttr>())
- GV->setLinkage(llvm::Function::DLLExportLinkage);
- else if (D->getAttr<WeakAttr>() || IsInline)
+ if (D->getAttr<DLLExportAttr>()) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // The dllexport attribute is ignored for undefined symbols.
+ if (FD->getBody())
+ GV->setLinkage(llvm::Function::DLLExportLinkage);
+ } else
+ GV->setLinkage(llvm::Function::DLLExportLinkage);
+ } else if (D->getAttr<WeakAttr>() || IsInline)
GV->setLinkage(llvm::Function::WeakLinkage);
}
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61437&r1=61436&r2=61437&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Dec 25 18:52:02 2008
@@ -509,6 +509,7 @@
attr = attr->getNext();
if (!DeclHasAttr(New, tmp)) {
+ tmp->setInherited(true);
New->addAttr(tmp);
} else {
tmp->setNext(0);
@@ -1207,9 +1208,6 @@
D.getDeclSpec().getSourceRange().getBegin());
}
- // Handle attributes.
- ProcessDeclAttributes(NewFD, D);
-
// Set the lexical context. If the declarator has a C++
// scope specifier, the lexical context will be different
// from the semantic context.
@@ -1386,6 +1384,9 @@
PrevDecl = 0;
}
}
+ // Handle attributes. We need to have merged decls when handling attributes
+ // (for example to check for conflicts, etc).
+ ProcessDeclAttributes(NewFD, D);
New = NewFD;
if (getLangOptions().CPlusPlus) {
@@ -2410,7 +2411,7 @@
}
PushDeclContext(FnBodyScope, FD);
-
+
// Check the validity of our function parameters
CheckParmsForFunctionDef(FD);
@@ -2422,6 +2423,25 @@
PushOnScopeChains(Param, FnBodyScope);
}
+ // Checking attributes of current function definition
+ // dllimport attribute.
+ if (FD->getAttr<DLLImportAttr>() && (!FD->getAttr<DLLExportAttr>())) {
+ // dllimport attribute cannot be applied to definition.
+ if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
+ Diag(FD->getLocation(),
+ diag::err_attribute_can_be_applied_only_to_symbol_declaration)
+ << "dllimport";
+ FD->setInvalidDecl();
+ return FD;
+ } else {
+ // If a symbol previously declared dllimport is later defined, the
+ // attribute is ignored in subsequent references, and a warning is
+ // emitted.
+ Diag(FD->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+ << FD->getNameAsCString() << "dllimport";
+ }
+ }
return FD;
}
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=61437&r1=61436&r2=61437&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Dec 25 18:52:02 2008
@@ -685,6 +685,41 @@
return;
}
+ // Attribute can be applied only to functions or variables.
+ if (isa<VarDecl>(d)) {
+ d->addAttr(new DLLImportAttr());
+ return;
+ }
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(d);
+ if (!FD) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << "dllimport" << "function or variable";
+ return;
+ }
+
+ // Currently, the dllimport attribute is ignored for inlined functions.
+ // Warning is emitted.
+ if (FD->isInline()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+
+ // The attribute is also overridden by a subsequent declaration as dllexport.
+ // Warning is emitted.
+ for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
+ nextAttr = nextAttr->getNext()) {
+ if (nextAttr->getKind() == AttributeList::AT_dllexport) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+ }
+
+ if (d->getAttr<DLLExportAttr>()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+
d->addAttr(new DLLImportAttr());
}
@@ -695,6 +730,27 @@
return;
}
+ // Attribute can be applied only to functions or variables.
+ if (isa<VarDecl>(d)) {
+ d->addAttr(new DLLExportAttr());
+ return;
+ }
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(d);
+ if (!FD) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << "dllexport" << "function or variable";
+ return;
+ }
+
+ // Currently, the dllexport attribute is ignored for inlined functions,
+ // unless the -fkeep-inline-functions flag has been used. Warning is emitted;
+ if (FD->isInline()) {
+ // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
+ return;
+ }
+
d->addAttr(new DLLExportAttr());
}
Added: cfe/trunk/test/CodeGen/dllimport-dllexport.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/dllimport-dllexport.c?rev=61437&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/dllimport-dllexport.c (added)
+++ cfe/trunk/test/CodeGen/dllimport-dllexport.c Thu Dec 25 18:52:02 2008
@@ -0,0 +1,7 @@
+// RUN: clang -emit-llvm < %s -o %t &&
+// RUN: grep 'dllexport' %t | count 1 &&
+// RUN: not grep 'dllimport' %t
+
+void __attribute__((dllimport)) foo1();
+void __attribute__((dllexport)) foo1(){}
+void __attribute__((dllexport)) foo2();
Added: cfe/trunk/test/Sema/dllimmport-dllexport.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/dllimmport-dllexport.c?rev=61437&view=auto
==============================================================================
--- cfe/trunk/test/Sema/dllimmport-dllexport.c (added)
+++ cfe/trunk/test/Sema/dllimmport-dllexport.c Thu Dec 25 18:52:02 2008
@@ -0,0 +1,18 @@
+// RUN: clang -fsyntax-only -verify %s
+
+inline void __attribute__((dllexport)) foo1(){} // expected-warning{{dllexport attribute ignored}}
+inline void __attribute__((dllimport)) foo2(){} // expected-warning{{dllimport attribute ignored}}
+
+void __attribute__((dllimport)) foo3(){} // expected-error{{dllimport attribute can be applied only to symbol declaration}}
+
+void __attribute__((dllimport, dllexport)) foo4(); // expected-warning{{dllimport attribute ignored}}
+
+void __attribute__((dllexport)) foo5();
+void __attribute__((dllimport)) foo5(); // expected-warning{{dllimport attribute ignored}}
+
+typedef int __attribute__((dllexport)) type6; // expected-warning{{'dllexport' attribute only applies to function or variable types}}
+
+typedef int __attribute__((dllimport)) type7; // expected-warning{{'dllimport' attribute only applies to function or variable}}
+
+void __attribute__((dllimport)) foo6();
+void foo6(){} // expected-warning {{'foo6' redeclared without dllimport attribute: previous dllimport ignored}}
More information about the cfe-commits
mailing list