blob: f84373944b2be27daec4f37ef3d5be9f20a59403 [file] [log] [blame]
Anton Korobeynikov82d0a412010-01-10 12:58:08 +00001//===-- 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
Anton Korobeynikov82d0a412010-01-10 12:58:08 +000015#include "TargetAttributesSema.h"
John McCall384aff82010-08-25 07:42:41 +000016#include "clang/AST/DeclCXX.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000017#include "clang/Basic/TargetInfo.h"
18#include "clang/Sema/SemaInternal.h"
Anton Korobeynikov82d0a412010-01-10 12:58:08 +000019#include "llvm/ADT/Triple.h"
20
21using namespace clang;
22
23TargetAttributesSema::~TargetAttributesSema() {}
24bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
25 const AttributeList &Attr, Sema &S) const {
26 return false;
27}
28
29static void HandleMSP430InterruptAttr(Decl *d,
30 const AttributeList &Attr, Sema &S) {
31 // Check the attribute arguments.
32 if (Attr.getNumArgs() != 1) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +000033 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
34 << Attr.getName() << 1;
Anton Korobeynikov82d0a412010-01-10 12:58:08 +000035 return;
36 }
37
38 // FIXME: Check for decl - it should be void ()(void).
39
40 Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
41 llvm::APSInt NumParams(32);
42 if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
Aaron Ballman9f939f72013-07-30 14:10:17 +000043 S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
44 << Attr.getName() << AANT_ArgumentIntegerConstant
45 << NumParamsExpr->getSourceRange();
Anton Korobeynikov82d0a412010-01-10 12:58:08 +000046 return;
47 }
48
49 unsigned Num = NumParams.getLimitedValue(255);
50 if ((Num & 1) || Num > 30) {
51 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
52 << "interrupt" << (int)NumParams.getSExtValue()
53 << NumParamsExpr->getSourceRange();
54 return;
55 }
56
Sean Huntcf807c42010-08-18 23:23:40 +000057 d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
58 d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
Anton Korobeynikov82d0a412010-01-10 12:58:08 +000059 }
60
61namespace {
62 class MSP430AttributesSema : public TargetAttributesSema {
63 public:
64 MSP430AttributesSema() { }
65 bool ProcessDeclAttribute(Scope *scope, Decl *D,
66 const AttributeList &Attr, Sema &S) const {
67 if (Attr.getName()->getName() == "interrupt") {
68 HandleMSP430InterruptAttr(D, Attr, S);
69 return true;
70 }
71 return false;
72 }
73 };
74}
75
Charles Davis5a0164d2010-02-10 23:06:52 +000076static void HandleX86ForceAlignArgPointerAttr(Decl *D,
77 const AttributeList& Attr,
78 Sema &S) {
79 // Check the attribute arguments.
80 if (Attr.getNumArgs() != 0) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +000081 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
82 << Attr.getName() << 0;
Charles Davis5a0164d2010-02-10 23:06:52 +000083 return;
84 }
85
Charles Davisab442162010-02-17 00:44:47 +000086 // If we try to apply it to a function pointer, don't warn, but don't
87 // do anything, either. It doesn't matter anyway, because there's nothing
88 // special about calling a force_align_arg_pointer function.
Charles Davisbeaf5ed2010-02-18 04:39:19 +000089 ValueDecl *VD = dyn_cast<ValueDecl>(D);
Charles Davisab442162010-02-17 00:44:47 +000090 if (VD && VD->getType()->isFunctionPointerType())
Charles Davis5a0164d2010-02-10 23:06:52 +000091 return;
Charles Davisbeaf5ed2010-02-18 04:39:19 +000092 // Also don't warn on function pointer typedefs.
Richard Smith162e1c12011-04-15 14:24:37 +000093 TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
Charles Davise01c0632010-02-18 04:56:59 +000094 if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
95 TD->getUnderlyingType()->isFunctionType()))
Charles Davisbeaf5ed2010-02-18 04:39:19 +000096 return;
Charles Davis5a0164d2010-02-10 23:06:52 +000097 // Attribute can only be applied to function types.
Charles Davis9c00be52010-02-10 23:26:12 +000098 if (!isa<FunctionDecl>(D)) {
Charles Davis5a0164d2010-02-10 23:06:52 +000099 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
100 << Attr.getName() << /* function */0;
101 return;
102 }
103
Argyrios Kyrtzidis768d6ca2011-09-13 16:05:58 +0000104 D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
105 S.Context));
Charles Davis5a0164d2010-02-10 23:06:52 +0000106}
107
Michael Han51d8c522013-01-24 16:46:58 +0000108DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
109 unsigned AttrSpellingListIndex) {
Rafael Espindola98ae8342012-05-10 02:50:16 +0000110 if (D->hasAttr<DLLExportAttr>()) {
111 Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
Rafael Espindola599f1b72012-05-13 03:25:18 +0000112 return NULL;
Rafael Espindola98ae8342012-05-10 02:50:16 +0000113 }
114
115 if (D->hasAttr<DLLImportAttr>())
Rafael Espindola599f1b72012-05-13 03:25:18 +0000116 return NULL;
Rafael Espindola98ae8342012-05-10 02:50:16 +0000117
Reid Klecknerbeba3e82013-05-20 21:53:29 +0000118 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
119 if (VD->hasDefinition()) {
120 // dllimport cannot be applied to definitions.
121 Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition)
122 << "dllimport";
123 return NULL;
124 }
125 }
126
Michael Han51d8c522013-01-24 16:46:58 +0000127 return ::new (Context) DLLImportAttr(Range, Context,
128 AttrSpellingListIndex);
Rafael Espindola98ae8342012-05-10 02:50:16 +0000129}
130
Charles Davisf0122fe2010-02-16 18:27:26 +0000131static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
132 // check the attribute arguments.
133 if (Attr.getNumArgs() != 0) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +0000134 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
135 << Attr.getName() << 0;
Charles Davisf0122fe2010-02-16 18:27:26 +0000136 return;
137 }
138
139 // Attribute can be applied only to functions or variables.
Charles Davisf0122fe2010-02-16 18:27:26 +0000140 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
Rafael Espindola98ae8342012-05-10 02:50:16 +0000141 if (!FD && !isa<VarDecl>(D)) {
Ted Kremenek240670c2010-02-21 05:12:56 +0000142 // Apparently Visual C++ thinks it is okay to not emit a warning
143 // in this case, so only emit a warning when -fms-extensions is not
144 // specified.
David Blaikie4e4d0842012-03-11 07:00:24 +0000145 if (!S.getLangOpts().MicrosoftExt)
Ted Kremenek240670c2010-02-21 05:12:56 +0000146 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
147 << Attr.getName() << 2 /*variable and function*/;
Charles Davisf0122fe2010-02-16 18:27:26 +0000148 return;
149 }
150
151 // Currently, the dllimport attribute is ignored for inlined functions.
152 // Warning is emitted.
Rafael Espindola98ae8342012-05-10 02:50:16 +0000153 if (FD && FD->isInlineSpecified()) {
Charles Davisf0122fe2010-02-16 18:27:26 +0000154 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
155 return;
156 }
157
Michael Han51d8c522013-01-24 16:46:58 +0000158 unsigned Index = Attr.getAttributeSpellingListIndex();
159 DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
Rafael Espindola599f1b72012-05-13 03:25:18 +0000160 if (NewAttr)
161 D->addAttr(NewAttr);
Rafael Espindola98ae8342012-05-10 02:50:16 +0000162}
163
Michael Han51d8c522013-01-24 16:46:58 +0000164DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
165 unsigned AttrSpellingListIndex) {
Rafael Espindola98ae8342012-05-10 02:50:16 +0000166 if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
167 Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
168 D->dropAttr<DLLImportAttr>();
Charles Davisf0122fe2010-02-16 18:27:26 +0000169 }
170
Rafael Espindola98ae8342012-05-10 02:50:16 +0000171 if (D->hasAttr<DLLExportAttr>())
Rafael Espindola599f1b72012-05-13 03:25:18 +0000172 return NULL;
Rafael Espindola98ae8342012-05-10 02:50:16 +0000173
Michael Han51d8c522013-01-24 16:46:58 +0000174 return ::new (Context) DLLExportAttr(Range, Context,
175 AttrSpellingListIndex);
Charles Davisf0122fe2010-02-16 18:27:26 +0000176}
177
178static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
179 // check the attribute arguments.
180 if (Attr.getNumArgs() != 0) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +0000181 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
182 << Attr.getName() << 0;
Charles Davisf0122fe2010-02-16 18:27:26 +0000183 return;
184 }
185
186 // Attribute can be applied only to functions or variables.
Charles Davisf0122fe2010-02-16 18:27:26 +0000187 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
Rafael Espindola98ae8342012-05-10 02:50:16 +0000188 if (!FD && !isa<VarDecl>(D)) {
Charles Davisf0122fe2010-02-16 18:27:26 +0000189 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
190 << Attr.getName() << 2 /*variable and function*/;
191 return;
192 }
193
194 // Currently, the dllexport attribute is ignored for inlined functions, unless
195 // the -fkeep-inline-functions flag has been used. Warning is emitted;
Rafael Espindola98ae8342012-05-10 02:50:16 +0000196 if (FD && FD->isInlineSpecified()) {
Charles Davisf0122fe2010-02-16 18:27:26 +0000197 // FIXME: ... unless the -fkeep-inline-functions flag has been used.
198 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
199 return;
200 }
201
Michael Han51d8c522013-01-24 16:46:58 +0000202 unsigned Index = Attr.getAttributeSpellingListIndex();
203 DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
Rafael Espindola599f1b72012-05-13 03:25:18 +0000204 if (NewAttr)
205 D->addAttr(NewAttr);
Charles Davisf0122fe2010-02-16 18:27:26 +0000206}
207
Charles Davis5a0164d2010-02-10 23:06:52 +0000208namespace {
209 class X86AttributesSema : public TargetAttributesSema {
210 public:
211 X86AttributesSema() { }
212 bool ProcessDeclAttribute(Scope *scope, Decl *D,
213 const AttributeList &Attr, Sema &S) const {
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000214 const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple());
Charles Davisf0122fe2010-02-16 18:27:26 +0000215 if (Triple.getOS() == llvm::Triple::Win32 ||
NAKAMURA Takumi0aa20572011-02-17 08:51:38 +0000216 Triple.getOS() == llvm::Triple::MinGW32) {
Charles Davisf0122fe2010-02-16 18:27:26 +0000217 switch (Attr.getKind()) {
Sean Hunt8e083e72012-06-19 23:57:03 +0000218 case AttributeList::AT_DLLImport: HandleDLLImportAttr(D, Attr, S);
Charles Davisf0122fe2010-02-16 18:27:26 +0000219 return true;
Sean Hunt8e083e72012-06-19 23:57:03 +0000220 case AttributeList::AT_DLLExport: HandleDLLExportAttr(D, Attr, S);
Charles Davisf0122fe2010-02-16 18:27:26 +0000221 return true;
222 default: break;
223 }
224 }
Eli Friedman9afbfbe2011-09-30 18:53:25 +0000225 if (Triple.getArch() != llvm::Triple::x86_64 &&
Benjamin Kramerf2cee5c2011-09-30 20:32:22 +0000226 (Attr.getName()->getName() == "force_align_arg_pointer" ||
227 Attr.getName()->getName() == "__force_align_arg_pointer__")) {
Charles Davis5a0164d2010-02-10 23:06:52 +0000228 HandleX86ForceAlignArgPointerAttr(D, Attr, S);
229 return true;
230 }
231 return false;
232 }
233 };
234}
235
Reed Kotler7dfd1822013-01-16 17:10:28 +0000236static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
237 // check the attribute arguments.
238 if (Attr.hasParameterOrArguments()) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +0000239 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
240 << Attr.getName() << 0;
Reed Kotler7dfd1822013-01-16 17:10:28 +0000241 return;
242 }
243 // Attribute can only be applied to function types.
244 if (!isa<FunctionDecl>(D)) {
245 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
246 << Attr.getName() << /* function */0;
247 return;
248 }
Michael Han51d8c522013-01-24 16:46:58 +0000249 D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context,
250 Attr.getAttributeSpellingListIndex()));
Reed Kotler7dfd1822013-01-16 17:10:28 +0000251}
252
253static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
254 // check the attribute arguments.
255 if (Attr.hasParameterOrArguments()) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +0000256 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
257 << Attr.getName() << 0;
Reed Kotler7dfd1822013-01-16 17:10:28 +0000258 return;
259 }
260 // Attribute can only be applied to function types.
261 if (!isa<FunctionDecl>(D)) {
262 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
263 << Attr.getName() << /* function */0;
264 return;
265 }
Michael Han51d8c522013-01-24 16:46:58 +0000266 D->addAttr(::new (S.Context)
267 NoMips16Attr(Attr.getRange(), S.Context,
268 Attr.getAttributeSpellingListIndex()));
Reed Kotler7dfd1822013-01-16 17:10:28 +0000269}
270
271namespace {
272 class MipsAttributesSema : public TargetAttributesSema {
273 public:
274 MipsAttributesSema() { }
275 bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
276 Sema &S) const {
277 if (Attr.getName()->getName() == "mips16") {
278 HandleMips16Attr(D, Attr, S);
279 return true;
280 } else if (Attr.getName()->getName() == "nomips16") {
281 HandleNoMips16Attr(D, Attr, S);
282 return true;
283 }
284 return false;
285 }
286 };
287}
288
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000289const TargetAttributesSema &Sema::getTargetAttributesSema() const {
290 if (TheTargetAttributesSema)
291 return *TheTargetAttributesSema;
292
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000293 const llvm::Triple &Triple(Context.getTargetInfo().getTriple());
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000294 switch (Triple.getArch()) {
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000295 case llvm::Triple::msp430:
296 return *(TheTargetAttributesSema = new MSP430AttributesSema);
Charles Davis5a0164d2010-02-10 23:06:52 +0000297 case llvm::Triple::x86:
Eli Friedman9afbfbe2011-09-30 18:53:25 +0000298 case llvm::Triple::x86_64:
Charles Davis5a0164d2010-02-10 23:06:52 +0000299 return *(TheTargetAttributesSema = new X86AttributesSema);
Reed Kotler7dfd1822013-01-16 17:10:28 +0000300 case llvm::Triple::mips:
301 case llvm::Triple::mipsel:
302 return *(TheTargetAttributesSema = new MipsAttributesSema);
Eli Friedman9afbfbe2011-09-30 18:53:25 +0000303 default:
304 return *(TheTargetAttributesSema = new TargetAttributesSema);
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000305 }
306}