TargetAttributesSema.cpp revision 240670c8f88a0062a76c2f15431341dd0406692f
1//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains semantic analysis implementation for target-specific
11// attributes.
12//
13//===----------------------------------------------------------------------===//
14
15#include "Sema.h"
16#include "TargetAttributesSema.h"
17#include "clang/Basic/TargetInfo.h"
18#include "llvm/ADT/Triple.h"
19
20using namespace clang;
21
22TargetAttributesSema::~TargetAttributesSema() {}
23bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
24                                    const AttributeList &Attr, Sema &S) const {
25  return false;
26}
27
28static void HandleMSP430InterruptAttr(Decl *d,
29                                      const AttributeList &Attr, Sema &S) {
30    // Check the attribute arguments.
31    if (Attr.getNumArgs() != 1) {
32      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
33      return;
34    }
35
36    // FIXME: Check for decl - it should be void ()(void).
37
38    Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
39    llvm::APSInt NumParams(32);
40    if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
41      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
42        << "interrupt" << NumParamsExpr->getSourceRange();
43      return;
44    }
45
46    unsigned Num = NumParams.getLimitedValue(255);
47    if ((Num & 1) || Num > 30) {
48      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
49        << "interrupt" << (int)NumParams.getSExtValue()
50        << NumParamsExpr->getSourceRange();
51      return;
52    }
53
54    d->addAttr(::new (S.Context) MSP430InterruptAttr(Num));
55    d->addAttr(::new (S.Context) UsedAttr());
56  }
57
58namespace {
59  class MSP430AttributesSema : public TargetAttributesSema {
60  public:
61    MSP430AttributesSema() { }
62    bool ProcessDeclAttribute(Scope *scope, Decl *D,
63                              const AttributeList &Attr, Sema &S) const {
64      if (Attr.getName()->getName() == "interrupt") {
65        HandleMSP430InterruptAttr(D, Attr, S);
66        return true;
67      }
68      return false;
69    }
70  };
71}
72
73static void HandleX86ForceAlignArgPointerAttr(Decl *D,
74                                              const AttributeList& Attr,
75                                              Sema &S) {
76  // Check the attribute arguments.
77  if (Attr.getNumArgs() != 0) {
78    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
79    return;
80  }
81
82  // If we try to apply it to a function pointer, don't warn, but don't
83  // do anything, either. It doesn't matter anyway, because there's nothing
84  // special about calling a force_align_arg_pointer function.
85  ValueDecl *VD = dyn_cast<ValueDecl>(D);
86  if (VD && VD->getType()->isFunctionPointerType())
87    return;
88  // Also don't warn on function pointer typedefs.
89  TypedefDecl *TD = dyn_cast<TypedefDecl>(D);
90  if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
91             TD->getUnderlyingType()->isFunctionType()))
92    return;
93  // Attribute can only be applied to function types.
94  if (!isa<FunctionDecl>(D)) {
95    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
96      << Attr.getName() << /* function */0;
97    return;
98  }
99
100  D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr());
101}
102
103static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
104  // check the attribute arguments.
105  if (Attr.getNumArgs() != 0) {
106    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
107    return;
108  }
109
110  // Attribute can be applied only to functions or variables.
111  if (isa<VarDecl>(D)) {
112    D->addAttr(::new (S.Context) DLLImportAttr());
113    return;
114  }
115
116  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
117  if (!FD) {
118    // Apparently Visual C++ thinks it is okay to not emit a warning
119    // in this case, so only emit a warning when -fms-extensions is not
120    // specified.
121    if (!S.getLangOptions().Microsoft)
122      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
123        << Attr.getName() << 2 /*variable and function*/;
124    return;
125  }
126
127  // Currently, the dllimport attribute is ignored for inlined functions.
128  // Warning is emitted.
129  if (FD->isInlineSpecified()) {
130    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
131    return;
132  }
133
134  // The attribute is also overridden by a subsequent declaration as dllexport.
135  // Warning is emitted.
136  for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
137       nextAttr = nextAttr->getNext()) {
138    if (nextAttr->getKind() == AttributeList::AT_dllexport) {
139      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
140      return;
141    }
142  }
143
144  if (D->getAttr<DLLExportAttr>()) {
145    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
146    return;
147  }
148
149  D->addAttr(::new (S.Context) DLLImportAttr());
150}
151
152static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
153  // check the attribute arguments.
154  if (Attr.getNumArgs() != 0) {
155    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
156    return;
157  }
158
159  // Attribute can be applied only to functions or variables.
160  if (isa<VarDecl>(D)) {
161    D->addAttr(::new (S.Context) DLLExportAttr());
162    return;
163  }
164
165  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
166  if (!FD) {
167    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
168      << Attr.getName() << 2 /*variable and function*/;
169    return;
170  }
171
172  // Currently, the dllexport attribute is ignored for inlined functions, unless
173  // the -fkeep-inline-functions flag has been used. Warning is emitted;
174  if (FD->isInlineSpecified()) {
175    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
176    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
177    return;
178  }
179
180  D->addAttr(::new (S.Context) DLLExportAttr());
181}
182
183namespace {
184  class X86AttributesSema : public TargetAttributesSema {
185  public:
186    X86AttributesSema() { }
187    bool ProcessDeclAttribute(Scope *scope, Decl *D,
188                              const AttributeList &Attr, Sema &S) const {
189      const llvm::Triple &Triple(S.Context.Target.getTriple());
190      if (Triple.getOS() == llvm::Triple::Win32 ||
191          Triple.getOS() == llvm::Triple::MinGW32 ||
192          Triple.getOS() == llvm::Triple::MinGW64) {
193        switch (Attr.getKind()) {
194        case AttributeList::AT_dllimport: HandleDLLImportAttr(D, Attr, S);
195                                          return true;
196        case AttributeList::AT_dllexport: HandleDLLExportAttr(D, Attr, S);
197                                          return true;
198        default:                          break;
199        }
200      }
201      if (Attr.getName()->getName() == "force_align_arg_pointer" ||
202          Attr.getName()->getName() == "__force_align_arg_pointer__") {
203        HandleX86ForceAlignArgPointerAttr(D, Attr, S);
204        return true;
205      }
206      return false;
207    }
208  };
209}
210
211const TargetAttributesSema &Sema::getTargetAttributesSema() const {
212  if (TheTargetAttributesSema)
213    return *TheTargetAttributesSema;
214
215  const llvm::Triple &Triple(Context.Target.getTriple());
216  switch (Triple.getArch()) {
217  default:
218    return *(TheTargetAttributesSema = new TargetAttributesSema);
219
220  case llvm::Triple::msp430:
221    return *(TheTargetAttributesSema = new MSP430AttributesSema);
222  case llvm::Triple::x86:
223    return *(TheTargetAttributesSema = new X86AttributesSema);
224  }
225}
226
227