diff options
| author | Aaron Ballman <aaron@aaronballman.com> | 2014-01-09 22:48:32 +0000 |
|---|---|---|
| committer | Aaron Ballman <aaron@aaronballman.com> | 2014-01-09 22:48:32 +0000 |
| commit | ab7691c4ce72faf49e14fe715ec608f236742e24 (patch) | |
| tree | 2d22bb6654b8411d8763c0cfb9b18307ec2e5604 /clang/lib/Sema | |
| parent | a3570186b2385cc6aaeb4babeef94add5ba37ab4 (diff) | |
| download | bcm5719-llvm-ab7691c4ce72faf49e14fe715ec608f236742e24.tar.gz bcm5719-llvm-ab7691c4ce72faf49e14fe715ec608f236742e24.zip | |
Removing the notion of TargetAttributesSema and replacing it with one where the parsed attributes are responsible for knowing their target-specific nature, instead of letting Sema figure it out. This is necessary so that __has_attribute can eventually determine whether a parsed attribute applies to the given target or not.
llvm-svn: 198896
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/AttributeList.cpp | 15 | ||||
| -rw-r--r-- | clang/lib/Sema/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 235 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmtAttr.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/TargetAttributesSema.cpp | 295 | ||||
| -rw-r--r-- | clang/lib/Sema/TargetAttributesSema.h | 27 |
7 files changed, 219 insertions, 359 deletions
diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp index c079c30382c..58a3e23c1b0 100644 --- a/clang/lib/Sema/AttributeList.cpp +++ b/clang/lib/Sema/AttributeList.cpp @@ -156,10 +156,13 @@ struct ParsedAttrInfo { unsigned NumArgs : 4; unsigned OptArgs : 4; unsigned HasCustomParsing : 1; + unsigned IsTargetSpecific : 1; + unsigned IsType : 1; bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, const Decl *); bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); + bool (*ExistsInTarget)(llvm::Triple T); }; namespace { @@ -189,3 +192,15 @@ bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { bool AttributeList::diagnoseLangOpts(Sema &S) const { return getInfo(*this).DiagLangOpts(S, *this); } + +bool AttributeList::isTargetSpecificAttr() const { + return getInfo(*this).IsTargetSpecific; +} + +bool AttributeList::isTypeAttr() const { + return getInfo(*this).IsType; +} + +bool AttributeList::existsInTarget(llvm::Triple T) const { + return getInfo(*this).ExistsInTarget(T); +} diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index c4ebeb59407..75702e1d8b2 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -47,7 +47,6 @@ add_clang_library(clangSema SemaTemplateInstantiateDecl.cpp SemaTemplateVariadic.cpp SemaType.cpp - TargetAttributesSema.cpp TypeLocBuilder.cpp ) diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 1c748f61e06..c824921a4f1 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "TargetAttributesSema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/DeclCXX.h" @@ -70,7 +69,7 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter) - : TheTargetAttributesSema(0), ExternalSource(0), + : ExternalSource(0), isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), @@ -209,7 +208,6 @@ Sema::~Sema() { delete I->second; if (PackContext) FreePackedContext(); if (VisContext) FreeVisContext(); - delete TheTargetAttributesSema; MSStructPragmaOn = false; // Kill all the active scopes. for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 23649c66940..945525bdd54 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "TargetAttributesSema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" @@ -205,7 +204,6 @@ static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, return true; } - /// \brief Check if the attribute has at least as many args as Num. May /// output an error. static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr, @@ -3174,8 +3172,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, return true; } - // TODO: diagnose uses of these conventions on the wrong target. Or, better - // move to TargetAttributesSema one day. + // TODO: diagnose uses of these conventions on the wrong target. switch (attr.getKind()) { case AttributeList::AT_CDecl: CC = CC_C; break; case AttributeList::AT_FastCall: CC = CC_X86FastCall; break; @@ -3712,6 +3709,179 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } +static void handleARMInterruptAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // Check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) + << Attr.getName() << 1; + return; + } + + StringRef Str; + SourceLocation ArgLoc; + + if (Attr.getNumArgs() == 0) + Str = ""; + else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc)) + return; + + ARMInterruptAttr::InterruptType Kind; + if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << Attr.getName() << Str << ArgLoc; + return; + } + + unsigned Index = Attr.getAttributeSpellingListIndex(); + D->addAttr(::new (S.Context) + ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index)); +} + +static void handleMSP430InterruptAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + if (!Attr.isArgExpr(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() + << AANT_ArgumentIntegerConstant; + return; + } + + // FIXME: Check for decl - it should be void ()(void). + + Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); + llvm::APSInt NumParams(32); + if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << NumParamsExpr->getSourceRange(); + return; + } + + unsigned Num = NumParams.getLimitedValue(255); + if ((Num & 1) || Num > 30) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << Attr.getName() << (int)NumParams.getSExtValue() + << NumParamsExpr->getSourceRange(); + return; + } + + D->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num)); + D->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); +} + +static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Dispatch the interrupt attribute based on the current target. + if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430) + handleMSP430InterruptAttr(S, D, Attr); + else + handleARMInterruptAttr(S, D, Attr); +} + +static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, + const AttributeList& Attr) { + // If we try to apply it to a function pointer, don't warn, but don't + // do anything, either. It doesn't matter anyway, because there's nothing + // special about calling a force_align_arg_pointer function. + ValueDecl *VD = dyn_cast<ValueDecl>(D); + if (VD && VD->getType()->isFunctionPointerType()) + return; + // Also don't warn on function pointer typedefs. + TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); + if (TD && (TD->getUnderlyingType()->isFunctionPointerType() || + TD->getUnderlyingType()->isFunctionType())) + return; + // Attribute can only be applied to function types. + if (!isa<FunctionDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << /* function */0; + return; + } + + D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(), + S.Context)); +} + +DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex) { + if (D->hasAttr<DLLExportAttr>()) { + Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport"; + return NULL; + } + + if (D->hasAttr<DLLImportAttr>()) + return NULL; + + if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->hasDefinition()) { + // dllimport cannot be applied to definitions. + Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition) + << "dllimport"; + return NULL; + } + } + + return ::new (Context)DLLImportAttr(Range, Context, + AttrSpellingListIndex); +} + +static void handleDLLImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Attribute can be applied only to functions or variables. + FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD && !isa<VarDecl>(D)) { + // Apparently Visual C++ thinks it is okay to not emit a warning + // in this case, so only emit a warning when -fms-extensions is not + // specified. + if (!S.getLangOpts().MicrosoftExt) + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 2 /*variable and function*/; + return; + } + + // Currently, the dllimport attribute is ignored for inlined functions. + // Warning is emitted. + if (FD && FD->isInlineSpecified()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return; + } + + unsigned Index = Attr.getAttributeSpellingListIndex(); + DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index); + if (NewAttr) + D->addAttr(NewAttr); +} + +DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex) { + if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) { + Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport"; + D->dropAttr<DLLImportAttr>(); + } + + if (D->hasAttr<DLLExportAttr>()) + return NULL; + + return ::new (Context)DLLExportAttr(Range, Context, + AttrSpellingListIndex); +} + +static void handleDLLExportAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Currently, the dllexport attribute is ignored for inlined functions, unless + // the -fkeep-inline-functions flag has been used. Warning is emitted; + if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isInlineSpecified()) { + // FIXME: ... unless the -fkeep-inline-functions flag has been used. + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return; + } + + unsigned Index = Attr.getAttributeSpellingListIndex(); + DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index); + if (NewAttr) + D->addAttr(NewAttr); +} + /// Handles semantic checking for features that are common to all attributes, /// such as checking whether a parameter was properly specified, or the correct /// number of arguments were passed, etc. @@ -3723,8 +3893,7 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, // We also bail on unknown and ignored attributes because those are handled // as part of the target-specific handling logic. if (Attr.hasCustomParsing() || - Attr.getKind() == AttributeList::UnknownAttribute || - Attr.getKind() == AttributeList::IgnoredAttribute) + Attr.getKind() == AttributeList::UnknownAttribute) return false; // Check whether the attribute requires specific language extensions to be @@ -3755,7 +3924,7 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr, bool IncludeCXX11Attributes) { - if (Attr.isInvalid()) + if (Attr.isInvalid() || Attr.getKind() == AttributeList::IgnoredAttribute) return; // Ignore C++11 attributes on declarator chunks: they appertain to the type @@ -3763,28 +3932,42 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) return; + // Unknown attributes are automatically warned on. Target-specific attributes + // which do not apply to the current target architecture are treated as + // though they were unknown attributes. + if (Attr.getKind() == AttributeList::UnknownAttribute || + !Attr.existsInTarget(S.Context.getTargetInfo().getTriple())) { + S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ? + diag::warn_unhandled_ms_attribute_ignored : + diag::warn_unknown_attribute_ignored) << Attr.getName(); + return; + } + if (handleCommonAttributeFeatures(S, scope, D, Attr)) return; switch (Attr.getKind()) { + default: + // Type attributes are handled elsewhere; silently move on. + assert(Attr.isTypeAttr() && "Non-type attribute not handled"); + break; + case AttributeList::AT_Interrupt: + handleInterruptAttr(S, D, Attr); break; + case AttributeList::AT_X86ForceAlignArgPointer: + handleX86ForceAlignArgPointerAttr(S, D, Attr); break; + case AttributeList::AT_DLLExport: + handleDLLExportAttr(S, D, Attr); break; + case AttributeList::AT_DLLImport: + handleDLLImportAttr(S, D, Attr); break; + case AttributeList::AT_Mips16: + handleSimpleAttribute<Mips16Attr>(S, D, Attr); break; + case AttributeList::AT_NoMips16: + handleSimpleAttribute<NoMips16Attr>(S, D, Attr); break; case AttributeList::AT_IBAction: handleSimpleAttribute<IBActionAttr>(S, D, Attr); break; case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; case AttributeList::AT_IBOutletCollection: handleIBOutletCollection(S, D, Attr); break; - case AttributeList::AT_AddressSpace: - case AttributeList::AT_ObjCGC: - case AttributeList::AT_VectorSize: - case AttributeList::AT_NeonVectorType: - case AttributeList::AT_NeonPolyVectorType: - case AttributeList::AT_Ptr32: - case AttributeList::AT_Ptr64: - case AttributeList::AT_SPtr: - case AttributeList::AT_UPtr: - case AttributeList::AT_Regparm: - // Ignore these, these are type attributes, handled by - // ProcessTypeAttributes. - break; case AttributeList::AT_Alias: handleAliasAttr (S, D, Attr); break; case AttributeList::AT_Aligned: handleAlignedAttr (S, D, Attr); break; case AttributeList::AT_AlwaysInline: @@ -3946,9 +4129,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_NoDebug: handleNoDebugAttr (S, D, Attr); break; case AttributeList::AT_NoInline: handleSimpleAttribute<NoInlineAttr>(S, D, Attr); break; - case AttributeList::IgnoredAttribute: - // Just ignore - break; case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg. handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, Attr); break; case AttributeList::AT_StdCall: @@ -4078,15 +4258,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_TypeTagForDatatype: handleTypeTagForDatatypeAttr(S, D, Attr); break; - - default: - // Ask target about the attribute. - const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); - if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) - S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ? - diag::warn_unhandled_ms_attribute_ignored : - diag::warn_unknown_attribute_ignored) << Attr.getName(); - break; } } diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index eb0188a0db3..80d203e3f5b 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "TargetAttributesSema.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" diff --git a/clang/lib/Sema/TargetAttributesSema.cpp b/clang/lib/Sema/TargetAttributesSema.cpp deleted file mode 100644 index b70b15c37b2..00000000000 --- a/clang/lib/Sema/TargetAttributesSema.cpp +++ /dev/null @@ -1,295 +0,0 @@ -//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains semantic analysis implementation for target-specific -// attributes. -// -//===----------------------------------------------------------------------===// - -#include "TargetAttributesSema.h" -#include "clang/AST/DeclCXX.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Sema/SemaInternal.h" -#include "llvm/ADT/Triple.h" - -using namespace clang; - -TargetAttributesSema::~TargetAttributesSema() {} -bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D, - const AttributeList &Attr, Sema &S) const { - return false; -} - -static void HandleARMInterruptAttr(Decl *d, - const AttributeList &Attr, Sema &S) { - // Check the attribute arguments. - if (Attr.getNumArgs() > 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) - << Attr.getName() << 1; - return; - } - - StringRef Str; - SourceLocation ArgLoc; - - if (Attr.getNumArgs() == 0) - Str = ""; - else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc)) - return; - - ARMInterruptAttr::InterruptType Kind; - if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) - << Attr.getName() << Str << ArgLoc; - return; - } - - unsigned Index = Attr.getAttributeSpellingListIndex(); - d->addAttr(::new (S.Context) - ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index)); -} - -namespace { - class ARMAttributesSema : public TargetAttributesSema { - public: - ARMAttributesSema() { } - bool ProcessDeclAttribute(Scope *scope, Decl *D, - const AttributeList &Attr, Sema &S) const { - if (Attr.getKind() == AttributeList::AT_Interrupt) { - HandleARMInterruptAttr(D, Attr, S); - return true; - } - return false; - } - }; -} - -static void HandleMSP430InterruptAttr(Decl *d, - const AttributeList &Attr, Sema &S) { - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 1; - return; - } - - if (!Attr.isArgExpr(0)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() - << AANT_ArgumentIntegerConstant; - return; - } - - // FIXME: Check for decl - it should be void ()(void). - Expr *NumParamsExpr = Attr.getArgAsExpr(0); - llvm::APSInt NumParams(32); - if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) - << Attr.getName() << AANT_ArgumentIntegerConstant - << NumParamsExpr->getSourceRange(); - return; - } - - unsigned Num = NumParams.getLimitedValue(255); - if ((Num & 1) || Num > 30) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) - << Attr.getName() << (int)NumParams.getSExtValue() - << NumParamsExpr->getSourceRange(); - return; - } - - d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num)); - d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); -} - -namespace { - class MSP430AttributesSema : public TargetAttributesSema { - public: - MSP430AttributesSema() { } - bool ProcessDeclAttribute(Scope *scope, Decl *D, - const AttributeList &Attr, Sema &S) const { - if (Attr.getKind() == AttributeList::AT_Interrupt) { - HandleMSP430InterruptAttr(D, Attr, S); - return true; - } - return false; - } - }; -} - -static void HandleX86ForceAlignArgPointerAttr(Decl *D, - const AttributeList& Attr, - Sema &S) { - // If we try to apply it to a function pointer, don't warn, but don't - // do anything, either. It doesn't matter anyway, because there's nothing - // special about calling a force_align_arg_pointer function. - ValueDecl *VD = dyn_cast<ValueDecl>(D); - if (VD && VD->getType()->isFunctionPointerType()) - return; - // Also don't warn on function pointer typedefs. - TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); - if (TD && (TD->getUnderlyingType()->isFunctionPointerType() || - TD->getUnderlyingType()->isFunctionType())) - return; - // Attribute can only be applied to function types. - if (!isa<FunctionDecl>(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << /* function */0; - return; - } - - D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(), - S.Context)); -} - -DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range, - unsigned AttrSpellingListIndex) { - if (D->hasAttr<DLLExportAttr>()) { - Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport"; - return NULL; - } - - if (D->hasAttr<DLLImportAttr>()) - return NULL; - - if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (VD->hasDefinition()) { - // dllimport cannot be applied to definitions. - Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition) - << "dllimport"; - return NULL; - } - } - - return ::new (Context) DLLImportAttr(Range, Context, - AttrSpellingListIndex); -} - -static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { - // Attribute can be applied only to functions or variables. - FunctionDecl *FD = dyn_cast<FunctionDecl>(D); - if (!FD && !isa<VarDecl>(D)) { - // Apparently Visual C++ thinks it is okay to not emit a warning - // in this case, so only emit a warning when -fms-extensions is not - // specified. - if (!S.getLangOpts().MicrosoftExt) - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variable and function*/; - return; - } - - // Currently, the dllimport attribute is ignored for inlined functions. - // Warning is emitted. - if (FD && FD->isInlineSpecified()) { - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); - return; - } - - unsigned Index = Attr.getAttributeSpellingListIndex(); - DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index); - if (NewAttr) - D->addAttr(NewAttr); -} - -DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, - unsigned AttrSpellingListIndex) { - if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) { - Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport"; - D->dropAttr<DLLImportAttr>(); - } - - if (D->hasAttr<DLLExportAttr>()) - return NULL; - - return ::new (Context) DLLExportAttr(Range, Context, - AttrSpellingListIndex); -} - -static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { - // Currently, the dllexport attribute is ignored for inlined functions, unless - // the -fkeep-inline-functions flag has been used. Warning is emitted; - if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isInlineSpecified()) { - // FIXME: ... unless the -fkeep-inline-functions flag has been used. - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); - return; - } - - unsigned Index = Attr.getAttributeSpellingListIndex(); - DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index); - if (NewAttr) - D->addAttr(NewAttr); -} - -namespace { - class X86AttributesSema : public TargetAttributesSema { - public: - X86AttributesSema() { } - bool ProcessDeclAttribute(Scope *scope, Decl *D, - const AttributeList &Attr, Sema &S) const { - const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple()); - if (Triple.getOS() == llvm::Triple::Win32 || - Triple.getOS() == llvm::Triple::MinGW32) { - switch (Attr.getKind()) { - case AttributeList::AT_DLLImport: HandleDLLImportAttr(D, Attr, S); - return true; - case AttributeList::AT_DLLExport: HandleDLLExportAttr(D, Attr, S); - return true; - default: break; - } - } - if (Triple.getArch() != llvm::Triple::x86_64 && - (Attr.getName()->getName() == "force_align_arg_pointer" || - Attr.getName()->getName() == "__force_align_arg_pointer__")) { - HandleX86ForceAlignArgPointerAttr(D, Attr, S); - return true; - } - return false; - } - }; -} - -namespace { - class MipsAttributesSema : public TargetAttributesSema { - public: - MipsAttributesSema() { } - bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, - Sema &S) const { - if (Attr.getKind() == AttributeList::AT_Mips16) { - D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - return true; - } else if (Attr.getKind() == AttributeList::AT_NoMips16) { - D->addAttr(::new (S.Context) NoMips16Attr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - return true; - } - return false; - } - }; -} - -const TargetAttributesSema &Sema::getTargetAttributesSema() const { - if (TheTargetAttributesSema) - return *TheTargetAttributesSema; - - const llvm::Triple &Triple(Context.getTargetInfo().getTriple()); - switch (Triple.getArch()) { - case llvm::Triple::arm: - case llvm::Triple::thumb: - return *(TheTargetAttributesSema = new ARMAttributesSema); - case llvm::Triple::msp430: - return *(TheTargetAttributesSema = new MSP430AttributesSema); - case llvm::Triple::x86: - case llvm::Triple::x86_64: - return *(TheTargetAttributesSema = new X86AttributesSema); - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return *(TheTargetAttributesSema = new MipsAttributesSema); - default: - return *(TheTargetAttributesSema = new TargetAttributesSema); - } -} diff --git a/clang/lib/Sema/TargetAttributesSema.h b/clang/lib/Sema/TargetAttributesSema.h deleted file mode 100644 index 410c900222f..00000000000 --- a/clang/lib/Sema/TargetAttributesSema.h +++ /dev/null @@ -1,27 +0,0 @@ -//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef CLANG_SEMA_TARGETSEMA_H -#define CLANG_SEMA_TARGETSEMA_H - -namespace clang { - class Scope; - class Decl; - class AttributeList; - class Sema; - - class TargetAttributesSema { - public: - virtual ~TargetAttributesSema(); - virtual bool ProcessDeclAttribute(Scope *scope, Decl *D, - const AttributeList &Attr, Sema &S) const; - }; -} - -#endif |

