TargetAttributesSema.cpp revision f0122fe49329cb439d55a6712bfcaad9a6570428
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, warn. This is a special 83 // instance of the warn_attribute_ignored warning that can be turned 84 // off with -Wno-force-align-arg-pointer. 85 ValueDecl* VD = dyn_cast<ValueDecl>(D); 86 if (VD && VD->getType()->isFunctionPointerType()) { 87 S.Diag(Attr.getLoc(), diag::warn_faap_attribute_ignored); 88 return; 89 } 90 // Attribute can only be applied to function types. 91 if (!isa<FunctionDecl>(D)) { 92 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 93 << Attr.getName() << /* function */0; 94 return; 95 } 96 97 D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr()); 98} 99 100static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 101 // check the attribute arguments. 102 if (Attr.getNumArgs() != 0) { 103 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 104 return; 105 } 106 107 // Attribute can be applied only to functions or variables. 108 if (isa<VarDecl>(D)) { 109 D->addAttr(::new (S.Context) DLLImportAttr()); 110 return; 111 } 112 113 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 114 if (!FD) { 115 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 116 << Attr.getName() << 2 /*variable and function*/; 117 return; 118 } 119 120 // Currently, the dllimport attribute is ignored for inlined functions. 121 // Warning is emitted. 122 if (FD->isInlineSpecified()) { 123 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 124 return; 125 } 126 127 // The attribute is also overridden by a subsequent declaration as dllexport. 128 // Warning is emitted. 129 for (AttributeList *nextAttr = Attr.getNext(); nextAttr; 130 nextAttr = nextAttr->getNext()) { 131 if (nextAttr->getKind() == AttributeList::AT_dllexport) { 132 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 133 return; 134 } 135 } 136 137 if (D->getAttr<DLLExportAttr>()) { 138 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 139 return; 140 } 141 142 D->addAttr(::new (S.Context) DLLImportAttr()); 143} 144 145static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 146 // check the attribute arguments. 147 if (Attr.getNumArgs() != 0) { 148 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 149 return; 150 } 151 152 // Attribute can be applied only to functions or variables. 153 if (isa<VarDecl>(D)) { 154 D->addAttr(::new (S.Context) DLLExportAttr()); 155 return; 156 } 157 158 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 159 if (!FD) { 160 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 161 << Attr.getName() << 2 /*variable and function*/; 162 return; 163 } 164 165 // Currently, the dllexport attribute is ignored for inlined functions, unless 166 // the -fkeep-inline-functions flag has been used. Warning is emitted; 167 if (FD->isInlineSpecified()) { 168 // FIXME: ... unless the -fkeep-inline-functions flag has been used. 169 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport"; 170 return; 171 } 172 173 D->addAttr(::new (S.Context) DLLExportAttr()); 174} 175 176namespace { 177 class X86AttributesSema : public TargetAttributesSema { 178 public: 179 X86AttributesSema() { } 180 bool ProcessDeclAttribute(Scope *scope, Decl *D, 181 const AttributeList &Attr, Sema &S) const { 182 const llvm::Triple &Triple(S.Context.Target.getTriple()); 183 if (Triple.getOS() == llvm::Triple::Win32 || 184 Triple.getOS() == llvm::Triple::MinGW32 || 185 Triple.getOS() == llvm::Triple::MinGW64) { 186 switch (Attr.getKind()) { 187 case AttributeList::AT_dllimport: HandleDLLImportAttr(D, Attr, S); 188 return true; 189 case AttributeList::AT_dllexport: HandleDLLExportAttr(D, Attr, S); 190 return true; 191 default: break; 192 } 193 } 194 if (Attr.getName()->getName() == "force_align_arg_pointer") { 195 HandleX86ForceAlignArgPointerAttr(D, Attr, S); 196 return true; 197 } 198 return false; 199 } 200 }; 201} 202 203const TargetAttributesSema &Sema::getTargetAttributesSema() const { 204 if (TheTargetAttributesSema) 205 return *TheTargetAttributesSema; 206 207 const llvm::Triple &Triple(Context.Target.getTriple()); 208 switch (Triple.getArch()) { 209 default: 210 return *(TheTargetAttributesSema = new TargetAttributesSema); 211 212 case llvm::Triple::msp430: 213 return *(TheTargetAttributesSema = new MSP430AttributesSema); 214 case llvm::Triple::x86: 215 return *(TheTargetAttributesSema = new X86AttributesSema); 216 } 217} 218 219