diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 56 |
3 files changed, 100 insertions, 11 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e83d2cd2930..fc1b108b0d6 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -218,17 +218,30 @@ static void SetGlobalValueAttributes(const Decl *D, // 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); } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 902101d617c..bb0dd4d07cf 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -509,6 +509,7 @@ static void MergeAttributes(Decl *New, Decl *Old) { attr = attr->getNext(); if (!DeclHasAttr(New, tmp)) { + tmp->setInherited(true); New->addAttr(tmp); } else { tmp->setNext(0); @@ -1207,9 +1208,6 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, 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 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, 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 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) { } PushDeclContext(FnBodyScope, FD); - + // Check the validity of our function parameters CheckParmsForFunctionDef(FD); @@ -2422,6 +2423,25 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) { 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; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 81283a85606..759ef0950b5 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -685,6 +685,41 @@ static void HandleDLLImportAttr(Decl *d, const AttributeList &Attr, Sema &S) { 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 @@ static void HandleDLLExportAttr(Decl *d, const AttributeList &Attr, Sema &S) { 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()); } |