blob: 87e7b9d00b095f55d4f3ca7a5f14e3434541ffa3 [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
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
Charles Davis5a0164d2010-02-10 23:06:52 +000073static 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
Charles Davisab442162010-02-17 00:44:47 +000082 // 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.
Charles Davisbeaf5ed2010-02-18 04:39:19 +000085 ValueDecl *VD = dyn_cast<ValueDecl>(D);
Charles Davisab442162010-02-17 00:44:47 +000086 if (VD && VD->getType()->isFunctionPointerType())
Charles Davis5a0164d2010-02-10 23:06:52 +000087 return;
Charles Davisbeaf5ed2010-02-18 04:39:19 +000088 // Also don't warn on function pointer typedefs.
89 TypedefDecl *TD = dyn_cast<TypedefDecl>(D);
Charles Davise01c0632010-02-18 04:56:59 +000090 if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
91 TD->getUnderlyingType()->isFunctionType()))
Charles Davisbeaf5ed2010-02-18 04:39:19 +000092 return;
Charles Davis5a0164d2010-02-10 23:06:52 +000093 // Attribute can only be applied to function types.
Charles Davis9c00be52010-02-10 23:26:12 +000094 if (!isa<FunctionDecl>(D)) {
Charles Davis5a0164d2010-02-10 23:06:52 +000095 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
Charles Davisf0122fe2010-02-16 18:27:26 +0000103static 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) {
Ted Kremenek240670c2010-02-21 05:12:56 +0000118 // 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*/;
Charles Davisf0122fe2010-02-16 18:27:26 +0000124 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
Charles Davis5a0164d2010-02-10 23:06:52 +0000183namespace {
184 class X86AttributesSema : public TargetAttributesSema {
185 public:
186 X86AttributesSema() { }
187 bool ProcessDeclAttribute(Scope *scope, Decl *D,
188 const AttributeList &Attr, Sema &S) const {
Charles Davisf0122fe2010-02-16 18:27:26 +0000189 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 }
Charles Davisbeaf5ed2010-02-18 04:39:19 +0000201 if (Attr.getName()->getName() == "force_align_arg_pointer" ||
202 Attr.getName()->getName() == "__force_align_arg_pointer__") {
Charles Davis5a0164d2010-02-10 23:06:52 +0000203 HandleX86ForceAlignArgPointerAttr(D, Attr, S);
204 return true;
205 }
206 return false;
207 }
208 };
209}
210
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000211const 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);
Charles Davis5a0164d2010-02-10 23:06:52 +0000222 case llvm::Triple::x86:
223 return *(TheTargetAttributesSema = new X86AttributesSema);
Anton Korobeynikov82d0a412010-01-10 12:58:08 +0000224 }
225}
226