blob: 499e613717fe1b79d2504b544fcec62a0e238ae1 [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)) {
43 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
44 << "interrupt" << NumParamsExpr->getSourceRange();
45 return;
46 }
47
48 unsigned Num = NumParams.getLimitedValue(255);
49 if ((Num & 1) || Num > 30) {
50 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
51 << "interrupt" << (int)NumParams.getSExtValue()
52 << NumParamsExpr->getSourceRange();
53 return;
54 }
55
Sean Huntcf807c42010-08-18 23:23:40 +000056 d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
57 d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
Anton Korobeynikov82d0a412010-01-10 12:58:08 +000058 }
59
60namespace {
61 class MSP430AttributesSema : public TargetAttributesSema {
62 public:
63 MSP430AttributesSema() { }
64 bool ProcessDeclAttribute(Scope *scope, Decl *D,
65 const AttributeList &Attr, Sema &S) const {
66 if (Attr.getName()->getName() == "interrupt") {
67 HandleMSP430InterruptAttr(D, Attr, S);
68 return true;
69 }
70 return false;
71 }
72 };
73}
74
Charles Davis5a0164d2010-02-10 23:06:52 +000075static void HandleX86ForceAlignArgPointerAttr(Decl *D,
76 const AttributeList& Attr,
77 Sema &S) {
78 // Check the attribute arguments.
79 if (Attr.getNumArgs() != 0) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +000080 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
81 << Attr.getName() << 0;
Charles Davis5a0164d2010-02-10 23:06:52 +000082 return;
83 }
84
Charles Davisab442162010-02-17 00:44:47 +000085 // If we try to apply it to a function pointer, don't warn, but don't
86 // do anything, either. It doesn't matter anyway, because there's nothing
87 // special about calling a force_align_arg_pointer function.
Charles Davisbeaf5ed2010-02-18 04:39:19 +000088 ValueDecl *VD = dyn_cast<ValueDecl>(D);
Charles Davisab442162010-02-17 00:44:47 +000089 if (VD && VD->getType()->isFunctionPointerType())
Charles Davis5a0164d2010-02-10 23:06:52 +000090 return;
Charles Davisbeaf5ed2010-02-18 04:39:19 +000091 // Also don't warn on function pointer typedefs.
Richard Smith162e1c12011-04-15 14:24:37 +000092 TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
Charles Davise01c0632010-02-18 04:56:59 +000093 if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
94 TD->getUnderlyingType()->isFunctionType()))
Charles Davisbeaf5ed2010-02-18 04:39:19 +000095 return;
Charles Davis5a0164d2010-02-10 23:06:52 +000096 // Attribute can only be applied to function types.
Charles Davis9c00be52010-02-10 23:26:12 +000097 if (!isa<FunctionDecl>(D)) {
Charles Davis5a0164d2010-02-10 23:06:52 +000098 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
99 << Attr.getName() << /* function */0;
100 return;
101 }
102
Argyrios Kyrtzidis768d6ca2011-09-13 16:05:58 +0000103 D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
104 S.Context));
Charles Davis5a0164d2010-02-10 23:06:52 +0000105}
106
Michael Han51d8c522013-01-24 16:46:58 +0000107DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
108 unsigned AttrSpellingListIndex) {
Rafael Espindola98ae8342012-05-10 02:50:16 +0000109 if (D->hasAttr<DLLExportAttr>()) {
110 Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
Rafael Espindola599f1b72012-05-13 03:25:18 +0000111 return NULL;
Rafael Espindola98ae8342012-05-10 02:50:16 +0000112 }
113
114 if (D->hasAttr<DLLImportAttr>())
Rafael Espindola599f1b72012-05-13 03:25:18 +0000115 return NULL;
Rafael Espindola98ae8342012-05-10 02:50:16 +0000116
Reid Klecknerbeba3e82013-05-20 21:53:29 +0000117 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
118 if (VD->hasDefinition()) {
119 // dllimport cannot be applied to definitions.
120 Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition)
121 << "dllimport";
122 return NULL;
123 }
124 }
125
Michael Han51d8c522013-01-24 16:46:58 +0000126 return ::new (Context) DLLImportAttr(Range, Context,
127 AttrSpellingListIndex);
Rafael Espindola98ae8342012-05-10 02:50:16 +0000128}
129
Charles Davisf0122fe2010-02-16 18:27:26 +0000130static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
131 // check the attribute arguments.
132 if (Attr.getNumArgs() != 0) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +0000133 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
134 << Attr.getName() << 0;
Charles Davisf0122fe2010-02-16 18:27:26 +0000135 return;
136 }
137
138 // Attribute can be applied only to functions or variables.
Charles Davisf0122fe2010-02-16 18:27:26 +0000139 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
Rafael Espindola98ae8342012-05-10 02:50:16 +0000140 if (!FD && !isa<VarDecl>(D)) {
Ted Kremenek240670c2010-02-21 05:12:56 +0000141 // Apparently Visual C++ thinks it is okay to not emit a warning
142 // in this case, so only emit a warning when -fms-extensions is not
143 // specified.
David Blaikie4e4d0842012-03-11 07:00:24 +0000144 if (!S.getLangOpts().MicrosoftExt)
Ted Kremenek240670c2010-02-21 05:12:56 +0000145 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
146 << Attr.getName() << 2 /*variable and function*/;
Charles Davisf0122fe2010-02-16 18:27:26 +0000147 return;
148 }
149
150 // Currently, the dllimport attribute is ignored for inlined functions.
151 // Warning is emitted.
Rafael Espindola98ae8342012-05-10 02:50:16 +0000152 if (FD && FD->isInlineSpecified()) {
Charles Davisf0122fe2010-02-16 18:27:26 +0000153 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
154 return;
155 }
156
Michael Han51d8c522013-01-24 16:46:58 +0000157 unsigned Index = Attr.getAttributeSpellingListIndex();
158 DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
Rafael Espindola599f1b72012-05-13 03:25:18 +0000159 if (NewAttr)
160 D->addAttr(NewAttr);
Rafael Espindola98ae8342012-05-10 02:50:16 +0000161}
162
Michael Han51d8c522013-01-24 16:46:58 +0000163DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
164 unsigned AttrSpellingListIndex) {
Rafael Espindola98ae8342012-05-10 02:50:16 +0000165 if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
166 Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
167 D->dropAttr<DLLImportAttr>();
Charles Davisf0122fe2010-02-16 18:27:26 +0000168 }
169
Rafael Espindola98ae8342012-05-10 02:50:16 +0000170 if (D->hasAttr<DLLExportAttr>())
Rafael Espindola599f1b72012-05-13 03:25:18 +0000171 return NULL;
Rafael Espindola98ae8342012-05-10 02:50:16 +0000172
Michael Han51d8c522013-01-24 16:46:58 +0000173 return ::new (Context) DLLExportAttr(Range, Context,
174 AttrSpellingListIndex);
Charles Davisf0122fe2010-02-16 18:27:26 +0000175}
176
177static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
178 // check the attribute arguments.
179 if (Attr.getNumArgs() != 0) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +0000180 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
181 << Attr.getName() << 0;
Charles Davisf0122fe2010-02-16 18:27:26 +0000182 return;
183 }
184
185 // Attribute can be applied only to functions or variables.
Charles Davisf0122fe2010-02-16 18:27:26 +0000186 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
Rafael Espindola98ae8342012-05-10 02:50:16 +0000187 if (!FD && !isa<VarDecl>(D)) {
Charles Davisf0122fe2010-02-16 18:27:26 +0000188 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
189 << Attr.getName() << 2 /*variable and function*/;
190 return;
191 }
192
193 // Currently, the dllexport attribute is ignored for inlined functions, unless
194 // the -fkeep-inline-functions flag has been used. Warning is emitted;
Rafael Espindola98ae8342012-05-10 02:50:16 +0000195 if (FD && FD->isInlineSpecified()) {
Charles Davisf0122fe2010-02-16 18:27:26 +0000196 // FIXME: ... unless the -fkeep-inline-functions flag has been used.
197 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
198 return;
199 }
200
Michael Han51d8c522013-01-24 16:46:58 +0000201 unsigned Index = Attr.getAttributeSpellingListIndex();
202 DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
Rafael Espindola599f1b72012-05-13 03:25:18 +0000203 if (NewAttr)
204 D->addAttr(NewAttr);
Charles Davisf0122fe2010-02-16 18:27:26 +0000205}
206
Charles Davis5a0164d2010-02-10 23:06:52 +0000207namespace {
208 class X86AttributesSema : public TargetAttributesSema {
209 public:
210 X86AttributesSema() { }
211 bool ProcessDeclAttribute(Scope *scope, Decl *D,
212 const AttributeList &Attr, Sema &S) const {
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000213 const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple());
Charles Davisf0122fe2010-02-16 18:27:26 +0000214 if (Triple.getOS() == llvm::Triple::Win32 ||
NAKAMURA Takumi0aa20572011-02-17 08:51:38 +0000215 Triple.getOS() == llvm::Triple::MinGW32) {
Charles Davisf0122fe2010-02-16 18:27:26 +0000216 switch (Attr.getKind()) {
Sean Hunt8e083e72012-06-19 23:57:03 +0000217 case AttributeList::AT_DLLImport: HandleDLLImportAttr(D, Attr, S);
Charles Davisf0122fe2010-02-16 18:27:26 +0000218 return true;
Sean Hunt8e083e72012-06-19 23:57:03 +0000219 case AttributeList::AT_DLLExport: HandleDLLExportAttr(D, Attr, S);
Charles Davisf0122fe2010-02-16 18:27:26 +0000220 return true;
221 default: break;
222 }
223 }
Eli Friedman9afbfbe2011-09-30 18:53:25 +0000224 if (Triple.getArch() != llvm::Triple::x86_64 &&
Benjamin Kramerf2cee5c2011-09-30 20:32:22 +0000225 (Attr.getName()->getName() == "force_align_arg_pointer" ||
226 Attr.getName()->getName() == "__force_align_arg_pointer__")) {
Charles Davis5a0164d2010-02-10 23:06:52 +0000227 HandleX86ForceAlignArgPointerAttr(D, Attr, S);
228 return true;
229 }
230 return false;
231 }
232 };
233}
234
Reed Kotler7dfd1822013-01-16 17:10:28 +0000235static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
236 // check the attribute arguments.
237 if (Attr.hasParameterOrArguments()) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +0000238 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
239 << Attr.getName() << 0;
Reed Kotler7dfd1822013-01-16 17:10:28 +0000240 return;
241 }
242 // Attribute can only be applied to function types.
243 if (!isa<FunctionDecl>(D)) {
244 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
245 << Attr.getName() << /* function */0;
246 return;
247 }
Michael Han51d8c522013-01-24 16:46:58 +0000248 D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context,
249 Attr.getAttributeSpellingListIndex()));
Reed Kotler7dfd1822013-01-16 17:10:28 +0000250}
251
252static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
253 // check the attribute arguments.
254 if (Attr.hasParameterOrArguments()) {
Aaron Ballmanbaec7782013-07-23 19:30:11 +0000255 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
256 << Attr.getName() << 0;
Reed Kotler7dfd1822013-01-16 17:10:28 +0000257 return;
258 }
259 // Attribute can only be applied to function types.
260 if (!isa<FunctionDecl>(D)) {
261 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
262 << Attr.getName() << /* function */0;
263 return;
264 }
Michael Han51d8c522013-01-24 16:46:58 +0000265 D->addAttr(::new (S.Context)
266 NoMips16Attr(Attr.getRange(), S.Context,
267 Attr.getAttributeSpellingListIndex()));
Reed Kotler7dfd1822013-01-16 17:10:28 +0000268}
269
270namespace {
271 class MipsAttributesSema : public TargetAttributesSema {
272 public:
273 MipsAttributesSema() { }
274 bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
275 Sema &S) const {
276 if (Attr.getName()->getName() == "mips16") {
277 HandleMips16Attr(D, Attr, S);
278 return true;
279 } else if (Attr.getName()->getName() == "nomips16") {
280 HandleNoMips16Attr(D, Attr, S);
281 return true;
282 }
283 return false;
284 }
285 };
286}
287
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000288const TargetAttributesSema &Sema::getTargetAttributesSema() const {
289 if (TheTargetAttributesSema)
290 return *TheTargetAttributesSema;
291
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000292 const llvm::Triple &Triple(Context.getTargetInfo().getTriple());
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000293 switch (Triple.getArch()) {
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000294 case llvm::Triple::msp430:
295 return *(TheTargetAttributesSema = new MSP430AttributesSema);
Charles Davis5a0164d2010-02-10 23:06:52 +0000296 case llvm::Triple::x86:
Eli Friedman9afbfbe2011-09-30 18:53:25 +0000297 case llvm::Triple::x86_64:
Charles Davis5a0164d2010-02-10 23:06:52 +0000298 return *(TheTargetAttributesSema = new X86AttributesSema);
Reed Kotler7dfd1822013-01-16 17:10:28 +0000299 case llvm::Triple::mips:
300 case llvm::Triple::mipsel:
301 return *(TheTargetAttributesSema = new MipsAttributesSema);
Eli Friedman9afbfbe2011-09-30 18:53:25 +0000302 default:
303 return *(TheTargetAttributesSema = new TargetAttributesSema);
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000304 }
305}