clang API Documentation
00001 //===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains semantic analysis implementation for target-specific 00011 // attributes. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "TargetAttributesSema.h" 00016 #include "clang/Sema/SemaInternal.h" 00017 #include "clang/Basic/TargetInfo.h" 00018 #include "clang/AST/DeclCXX.h" 00019 #include "llvm/ADT/Triple.h" 00020 00021 using namespace clang; 00022 00023 TargetAttributesSema::~TargetAttributesSema() {} 00024 bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D, 00025 const AttributeList &Attr, Sema &S) const { 00026 return false; 00027 } 00028 00029 static void HandleMSP430InterruptAttr(Decl *d, 00030 const AttributeList &Attr, Sema &S) { 00031 // Check the attribute arguments. 00032 if (Attr.getNumArgs() != 1) { 00033 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 00034 return; 00035 } 00036 00037 // FIXME: Check for decl - it should be void ()(void). 00038 00039 Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0)); 00040 llvm::APSInt NumParams(32); 00041 if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { 00042 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 00043 << "interrupt" << NumParamsExpr->getSourceRange(); 00044 return; 00045 } 00046 00047 unsigned Num = NumParams.getLimitedValue(255); 00048 if ((Num & 1) || Num > 30) { 00049 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 00050 << "interrupt" << (int)NumParams.getSExtValue() 00051 << NumParamsExpr->getSourceRange(); 00052 return; 00053 } 00054 00055 d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num)); 00056 d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); 00057 } 00058 00059 namespace { 00060 class MSP430AttributesSema : public TargetAttributesSema { 00061 public: 00062 MSP430AttributesSema() { } 00063 bool ProcessDeclAttribute(Scope *scope, Decl *D, 00064 const AttributeList &Attr, Sema &S) const { 00065 if (Attr.getName()->getName() == "interrupt") { 00066 HandleMSP430InterruptAttr(D, Attr, S); 00067 return true; 00068 } 00069 return false; 00070 } 00071 }; 00072 } 00073 00074 static void HandleMBlazeInterruptHandlerAttr(Decl *d, const AttributeList &Attr, 00075 Sema &S) { 00076 // Check the attribute arguments. 00077 if (Attr.getNumArgs() != 0) { 00078 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 00079 return; 00080 } 00081 00082 // FIXME: Check for decl - it should be void ()(void). 00083 00084 d->addAttr(::new (S.Context) MBlazeInterruptHandlerAttr(Attr.getLoc(), 00085 S.Context)); 00086 d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); 00087 } 00088 00089 static void HandleMBlazeSaveVolatilesAttr(Decl *d, const AttributeList &Attr, 00090 Sema &S) { 00091 // Check the attribute arguments. 00092 if (Attr.getNumArgs() != 0) { 00093 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 00094 return; 00095 } 00096 00097 // FIXME: Check for decl - it should be void ()(void). 00098 00099 d->addAttr(::new (S.Context) MBlazeSaveVolatilesAttr(Attr.getLoc(), 00100 S.Context)); 00101 d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); 00102 } 00103 00104 00105 namespace { 00106 class MBlazeAttributesSema : public TargetAttributesSema { 00107 public: 00108 MBlazeAttributesSema() { } 00109 bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, 00110 Sema &S) const { 00111 if (Attr.getName()->getName() == "interrupt_handler") { 00112 HandleMBlazeInterruptHandlerAttr(D, Attr, S); 00113 return true; 00114 } else if (Attr.getName()->getName() == "save_volatiles") { 00115 HandleMBlazeSaveVolatilesAttr(D, Attr, S); 00116 return true; 00117 } 00118 return false; 00119 } 00120 }; 00121 } 00122 00123 static void HandleX86ForceAlignArgPointerAttr(Decl *D, 00124 const AttributeList& Attr, 00125 Sema &S) { 00126 // Check the attribute arguments. 00127 if (Attr.getNumArgs() != 0) { 00128 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 00129 return; 00130 } 00131 00132 // If we try to apply it to a function pointer, don't warn, but don't 00133 // do anything, either. It doesn't matter anyway, because there's nothing 00134 // special about calling a force_align_arg_pointer function. 00135 ValueDecl *VD = dyn_cast<ValueDecl>(D); 00136 if (VD && VD->getType()->isFunctionPointerType()) 00137 return; 00138 // Also don't warn on function pointer typedefs. 00139 TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); 00140 if (TD && (TD->getUnderlyingType()->isFunctionPointerType() || 00141 TD->getUnderlyingType()->isFunctionType())) 00142 return; 00143 // Attribute can only be applied to function types. 00144 if (!isa<FunctionDecl>(D)) { 00145 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 00146 << Attr.getName() << /* function */0; 00147 return; 00148 } 00149 00150 D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(), 00151 S.Context)); 00152 } 00153 00154 DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range) { 00155 if (D->hasAttr<DLLExportAttr>()) { 00156 Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport"; 00157 return NULL; 00158 } 00159 00160 if (D->hasAttr<DLLImportAttr>()) 00161 return NULL; 00162 00163 return ::new (Context) DLLImportAttr(Range, Context); 00164 } 00165 00166 static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 00167 // check the attribute arguments. 00168 if (Attr.getNumArgs() != 0) { 00169 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 00170 return; 00171 } 00172 00173 // Attribute can be applied only to functions or variables. 00174 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 00175 if (!FD && !isa<VarDecl>(D)) { 00176 // Apparently Visual C++ thinks it is okay to not emit a warning 00177 // in this case, so only emit a warning when -fms-extensions is not 00178 // specified. 00179 if (!S.getLangOpts().MicrosoftExt) 00180 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 00181 << Attr.getName() << 2 /*variable and function*/; 00182 return; 00183 } 00184 00185 // Currently, the dllimport attribute is ignored for inlined functions. 00186 // Warning is emitted. 00187 if (FD && FD->isInlineSpecified()) { 00188 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 00189 return; 00190 } 00191 00192 DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange()); 00193 if (NewAttr) 00194 D->addAttr(NewAttr); 00195 } 00196 00197 DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range) { 00198 if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) { 00199 Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport"; 00200 D->dropAttr<DLLImportAttr>(); 00201 } 00202 00203 if (D->hasAttr<DLLExportAttr>()) 00204 return NULL; 00205 00206 return ::new (Context) DLLExportAttr(Range, Context); 00207 } 00208 00209 static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 00210 // check the attribute arguments. 00211 if (Attr.getNumArgs() != 0) { 00212 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 00213 return; 00214 } 00215 00216 // Attribute can be applied only to functions or variables. 00217 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 00218 if (!FD && !isa<VarDecl>(D)) { 00219 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 00220 << Attr.getName() << 2 /*variable and function*/; 00221 return; 00222 } 00223 00224 // Currently, the dllexport attribute is ignored for inlined functions, unless 00225 // the -fkeep-inline-functions flag has been used. Warning is emitted; 00226 if (FD && FD->isInlineSpecified()) { 00227 // FIXME: ... unless the -fkeep-inline-functions flag has been used. 00228 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport"; 00229 return; 00230 } 00231 00232 DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange()); 00233 if (NewAttr) 00234 D->addAttr(NewAttr); 00235 } 00236 00237 namespace { 00238 class X86AttributesSema : public TargetAttributesSema { 00239 public: 00240 X86AttributesSema() { } 00241 bool ProcessDeclAttribute(Scope *scope, Decl *D, 00242 const AttributeList &Attr, Sema &S) const { 00243 const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple()); 00244 if (Triple.getOS() == llvm::Triple::Win32 || 00245 Triple.getOS() == llvm::Triple::MinGW32) { 00246 switch (Attr.getKind()) { 00247 case AttributeList::AT_dllimport: HandleDLLImportAttr(D, Attr, S); 00248 return true; 00249 case AttributeList::AT_dllexport: HandleDLLExportAttr(D, Attr, S); 00250 return true; 00251 default: break; 00252 } 00253 } 00254 if (Triple.getArch() != llvm::Triple::x86_64 && 00255 (Attr.getName()->getName() == "force_align_arg_pointer" || 00256 Attr.getName()->getName() == "__force_align_arg_pointer__")) { 00257 HandleX86ForceAlignArgPointerAttr(D, Attr, S); 00258 return true; 00259 } 00260 return false; 00261 } 00262 }; 00263 } 00264 00265 const TargetAttributesSema &Sema::getTargetAttributesSema() const { 00266 if (TheTargetAttributesSema) 00267 return *TheTargetAttributesSema; 00268 00269 const llvm::Triple &Triple(Context.getTargetInfo().getTriple()); 00270 switch (Triple.getArch()) { 00271 case llvm::Triple::msp430: 00272 return *(TheTargetAttributesSema = new MSP430AttributesSema); 00273 case llvm::Triple::mblaze: 00274 return *(TheTargetAttributesSema = new MBlazeAttributesSema); 00275 case llvm::Triple::x86: 00276 case llvm::Triple::x86_64: 00277 return *(TheTargetAttributesSema = new X86AttributesSema); 00278 default: 00279 return *(TheTargetAttributesSema = new TargetAttributesSema); 00280 } 00281 }