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