diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/TargetAttributesSema.cpp | 86 | ||||
-rw-r--r-- | clang/lib/Sema/TargetAttributesSema.h | 27 |
5 files changed, 130 insertions, 5 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index b32ddfd2093..fefe924bc46 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "TargetAttributesSema.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/APFloat.h" #include "clang/AST/ASTConsumer.h" @@ -347,7 +348,8 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, bool CompleteTranslationUnit, CodeCompleteConsumer *CodeCompleter) - : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), + : TheTargetAttributesSema(0), + LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0), @@ -368,6 +370,11 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0)); } +Sema::~Sema() { + if (PackContext) FreePackedContext(); + delete TheTargetAttributesSema; +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// If isLvalue, the result of the cast is an lvalue. diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 54dd060fcee..f487fbeb5b4 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -101,6 +101,7 @@ namespace clang { class InitializationKind; class InitializationSequence; class VisibleDeclConsumer; + class TargetAttributesSema; /// BlockSemaInfo - When a block is being parsed, this contains information /// about the block. It is pointed to from Sema::CurBlock. @@ -176,6 +177,7 @@ public: class Sema : public Action { Sema(const Sema&); // DO NOT IMPLEMENT void operator=(const Sema&); // DO NOT IMPLEMENT + mutable const TargetAttributesSema* TheTargetAttributesSema; public: const LangOptions &LangOpts; Preprocessor &PP; @@ -426,13 +428,12 @@ public: Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, bool CompleteTranslationUnit = true, CodeCompleteConsumer *CompletionConsumer = 0); - ~Sema() { - if (PackContext) FreePackedContext(); - } + ~Sema(); const LangOptions &getLangOptions() const { return LangOpts; } Diagnostic &getDiagnostics() const { return Diags; } SourceManager &getSourceManager() const { return SourceMgr; } + const TargetAttributesSema &getTargetAttributesSema() const; /// \brief Helper class that creates diagnostics with optional /// template instantiation stacks. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 094e5b56e55..ceab525db12 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "TargetAttributesSema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" @@ -1959,7 +1960,10 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, // Just ignore break; default: - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + // Ask target about the attribute. + const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); + if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); break; } } diff --git a/clang/lib/Sema/TargetAttributesSema.cpp b/clang/lib/Sema/TargetAttributesSema.cpp new file mode 100644 index 00000000000..7c19bf6e4fd --- /dev/null +++ b/clang/lib/Sema/TargetAttributesSema.cpp @@ -0,0 +1,86 @@ +//===-- 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 "Sema.h" +#include "TargetAttributesSema.h" +#include "clang/Basic/TargetInfo.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 HandleMSP430InterruptAttr(Decl *d, + const AttributeList &Attr, Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // FIXME: Check for decl - it should be void ()(void). + + Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0)); + llvm::APSInt NumParams(32); + if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "interrupt" << NumParamsExpr->getSourceRange(); + return; + } + + unsigned Num = NumParams.getLimitedValue(255); + if ((Num & 1) || Num > 30) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "interrupt" << (int)NumParams.getSExtValue() + << NumParamsExpr->getSourceRange(); + return; + } + + d->addAttr(::new (S.Context) MSP430InterruptAttr(Num)); + d->addAttr(::new (S.Context) UsedAttr()); + } + +namespace { + class MSP430AttributesSema : public TargetAttributesSema { + public: + MSP430AttributesSema() { } + bool ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) const { + if (Attr.getName()->getName() == "interrupt") { + HandleMSP430InterruptAttr(D, Attr, S); + return true; + } + return false; + } + }; +} + +const TargetAttributesSema &Sema::getTargetAttributesSema() const { + if (TheTargetAttributesSema) + return *TheTargetAttributesSema; + + const llvm::Triple &Triple(Context.Target.getTriple()); + switch (Triple.getArch()) { + default: + return *(TheTargetAttributesSema = new TargetAttributesSema); + + case llvm::Triple::msp430: + return *(TheTargetAttributesSema = new MSP430AttributesSema); + } +} + diff --git a/clang/lib/Sema/TargetAttributesSema.h b/clang/lib/Sema/TargetAttributesSema.h new file mode 100644 index 00000000000..8794e4013ec --- /dev/null +++ b/clang/lib/Sema/TargetAttributesSema.h @@ -0,0 +1,27 @@ +//===--- 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 Attr; + class Sema; + + class TargetAttributesSema { + public: + virtual ~TargetAttributesSema(); + virtual bool ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) const; + }; +} + +#endif |