std::string MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const { std::string TripleStr = ToolChain::ComputeEffectiveClangTriple(Args, InputType); llvm::Triple Triple(TripleStr); VersionTuple MSVT = tools::visualstudio::getMSVCVersion(/*D=*/nullptr, *this, Triple, Args, /*IsWindowsMSVC=*/true); if (MSVT.empty()) return TripleStr; MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0), MSVT.getSubminor().getValueOr(0)); if (Triple.getEnvironment() == llvm::Triple::MSVC) { StringRef ObjFmt = Triple.getEnvironmentName().split('-').second; if (ObjFmt.empty()) Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str()); else Triple.setEnvironmentName( (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str()); } return Triple.getTriple(); }
VersionTuple ToolChain::computeMSVCVersion(const Driver *D, const llvm::opt::ArgList &Args) const { const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version); const Arg *MSCompatibilityVersion = Args.getLastArg(options::OPT_fms_compatibility_version); if (MSCVersion && MSCompatibilityVersion) { if (D) D->Diag(diag::err_drv_argument_not_allowed_with) << MSCVersion->getAsString(Args) << MSCompatibilityVersion->getAsString(Args); return VersionTuple(); } if (MSCompatibilityVersion) { VersionTuple MSVT; if (MSVT.tryParse(MSCompatibilityVersion->getValue())) { if (D) D->Diag(diag::err_drv_invalid_value) << MSCompatibilityVersion->getAsString(Args) << MSCompatibilityVersion->getValue(); } else { return MSVT; } } if (MSCVersion) { unsigned Version = 0; if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) { if (D) D->Diag(diag::err_drv_invalid_value) << MSCVersion->getAsString(Args) << MSCVersion->getValue(); } else { return separateMSVCFullVersion(Version); } } return VersionTuple(); }
static void InitializePredefinedMacros(const TargetInfo &TI, const LangOptions &LangOpts, const FrontendOptions &FEOpts, MacroBuilder &Builder) { // Compiler version introspection macros. Builder.defineMacro("__llvm__"); // LLVM Backend Builder.defineMacro("__clang__"); // Clang Frontend #define TOSTR2(X) #X #define TOSTR(X) TOSTR2(X) Builder.defineMacro("__clang_major__", TOSTR(CLANG_VERSION_MAJOR)); Builder.defineMacro("__clang_minor__", TOSTR(CLANG_VERSION_MINOR)); #ifdef CLANG_VERSION_PATCHLEVEL Builder.defineMacro("__clang_patchlevel__", TOSTR(CLANG_VERSION_PATCHLEVEL)); #else Builder.defineMacro("__clang_patchlevel__", "0"); #endif Builder.defineMacro("__clang_version__", "\"" CLANG_VERSION_STRING " " + getClangFullRepositoryVersion() + "\""); #undef TOSTR #undef TOSTR2 if (!LangOpts.MSVCCompat) { // Currently claim to be compatible with GCC 4.2.1-5621, but only if we're // not compiling for MSVC compatibility Builder.defineMacro("__GNUC_MINOR__", "2"); Builder.defineMacro("__GNUC_PATCHLEVEL__", "1"); Builder.defineMacro("__GNUC__", "4"); Builder.defineMacro("__GXX_ABI_VERSION", "1002"); } // Define macros for the C11 / C++11 memory orderings Builder.defineMacro("__ATOMIC_RELAXED", "0"); Builder.defineMacro("__ATOMIC_CONSUME", "1"); Builder.defineMacro("__ATOMIC_ACQUIRE", "2"); Builder.defineMacro("__ATOMIC_RELEASE", "3"); Builder.defineMacro("__ATOMIC_ACQ_REL", "4"); Builder.defineMacro("__ATOMIC_SEQ_CST", "5"); // Support for #pragma redefine_extname (Sun compatibility) Builder.defineMacro("__PRAGMA_REDEFINE_EXTNAME", "1"); // As sad as it is, enough software depends on the __VERSION__ for version // checks that it is necessary to report 4.2.1 (the base GCC version we claim // compatibility with) first. Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible " + Twine(getClangFullCPPVersion()) + "\""); // Initialize language-specific preprocessor defines. // Standard conforming mode? if (!LangOpts.GNUMode && !LangOpts.MSVCCompat) Builder.defineMacro("__STRICT_ANSI__"); if (!LangOpts.MSVCCompat && LangOpts.CPlusPlus11) Builder.defineMacro("__GXX_EXPERIMENTAL_CXX0X__"); if (LangOpts.ObjC1) { if (LangOpts.ObjCRuntime.isNonFragile()) { Builder.defineMacro("__OBJC2__"); if (LangOpts.ObjCExceptions) Builder.defineMacro("OBJC_ZEROCOST_EXCEPTIONS"); } if (LangOpts.getGC() != LangOptions::NonGC) Builder.defineMacro("__OBJC_GC__"); if (LangOpts.ObjCRuntime.isNeXTFamily()) Builder.defineMacro("__NEXT_RUNTIME__"); if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::ObjFW) { VersionTuple tuple = LangOpts.ObjCRuntime.getVersion(); unsigned minor = 0; if (tuple.getMinor().hasValue()) minor = tuple.getMinor().getValue(); unsigned subminor = 0; if (tuple.getSubminor().hasValue()) subminor = tuple.getSubminor().getValue(); Builder.defineMacro("__OBJFW_RUNTIME_ABI__", Twine(tuple.getMajor() * 10000 + minor * 100 + subminor)); } Builder.defineMacro("IBOutlet", "__attribute__((iboutlet))"); Builder.defineMacro("IBOutletCollection(ClassName)", "__attribute__((iboutletcollection(ClassName)))"); Builder.defineMacro("IBAction", "void)__attribute__((ibaction)"); Builder.defineMacro("IBInspectable", ""); Builder.defineMacro("IB_DESIGNABLE", ""); } if (LangOpts.CPlusPlus) InitializeCPlusPlusFeatureTestMacros(LangOpts, Builder); // darwin_constant_cfstrings controls this. This is also dependent // on other things like the runtime I believe. This is set even for C code. if (!LangOpts.NoConstantCFStrings) Builder.defineMacro("__CONSTANT_CFSTRINGS__"); if (LangOpts.ObjC2) Builder.defineMacro("OBJC_NEW_PROPERTIES"); if (LangOpts.PascalStrings) Builder.defineMacro("__PASCAL_STRINGS__"); if (LangOpts.Blocks) { Builder.defineMacro("__block", "__attribute__((__blocks__(byref)))"); Builder.defineMacro("__BLOCKS__"); } if (!LangOpts.MSVCCompat && LangOpts.Exceptions) Builder.defineMacro("__EXCEPTIONS"); if (!LangOpts.MSVCCompat && LangOpts.RTTI) Builder.defineMacro("__GXX_RTTI"); if (LangOpts.SjLjExceptions) Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__"); if (LangOpts.Deprecated) Builder.defineMacro("__DEPRECATED"); if (!LangOpts.MSVCCompat && LangOpts.CPlusPlus) { Builder.defineMacro("__GNUG__", "4"); Builder.defineMacro("__GXX_WEAK__"); Builder.defineMacro("__private_extern__", "extern"); } if (LangOpts.MicrosoftExt) { if (LangOpts.WChar) { // wchar_t supported as a keyword. Builder.defineMacro("_WCHAR_T_DEFINED"); Builder.defineMacro("_NATIVE_WCHAR_T_DEFINED"); } } if (LangOpts.Optimize) Builder.defineMacro("__OPTIMIZE__"); if (LangOpts.OptimizeSize) Builder.defineMacro("__OPTIMIZE_SIZE__"); if (LangOpts.FastMath) Builder.defineMacro("__FAST_MATH__"); // Initialize target-specific preprocessor defines. // __BYTE_ORDER__ was added in GCC 4.6. It's analogous // to the macro __BYTE_ORDER (no trailing underscores) // from glibc's <endian.h> header. // We don't support the PDP-11 as a target, but include // the define so it can still be compared against. Builder.defineMacro("__ORDER_LITTLE_ENDIAN__", "1234"); Builder.defineMacro("__ORDER_BIG_ENDIAN__", "4321"); Builder.defineMacro("__ORDER_PDP_ENDIAN__", "3412"); if (TI.isBigEndian()) { Builder.defineMacro("__BYTE_ORDER__", "__ORDER_BIG_ENDIAN__"); Builder.defineMacro("__BIG_ENDIAN__"); } else { Builder.defineMacro("__BYTE_ORDER__", "__ORDER_LITTLE_ENDIAN__"); Builder.defineMacro("__LITTLE_ENDIAN__"); } if (TI.getPointerWidth(0) == 64 && TI.getLongWidth() == 64 && TI.getIntWidth() == 32) { Builder.defineMacro("_LP64"); Builder.defineMacro("__LP64__"); } if (TI.getPointerWidth(0) == 32 && TI.getLongWidth() == 32 && TI.getIntWidth() == 32) { Builder.defineMacro("_ILP32"); Builder.defineMacro("__ILP32__"); } // Define type sizing macros based on the target properties. assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far"); Builder.defineMacro("__CHAR_BIT__", "8"); DefineTypeSize("__SCHAR_MAX__", TargetInfo::SignedChar, TI, Builder); DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Builder); DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Builder); DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder); DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Builder); DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Builder); DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder); DefineTypeSize("__SIZE_MAX__", TI.getSizeType(), TI, Builder); DefineTypeSize("__UINTMAX_MAX__", TI.getUIntMaxType(), TI, Builder); DefineTypeSize("__PTRDIFF_MAX__", TI.getPtrDiffType(0), TI, Builder); DefineTypeSize("__INTPTR_MAX__", TI.getIntPtrType(), TI, Builder); DefineTypeSize("__UINTPTR_MAX__", TI.getUIntPtrType(), TI, Builder); DefineTypeSizeof("__SIZEOF_DOUBLE__", TI.getDoubleWidth(), TI, Builder); DefineTypeSizeof("__SIZEOF_FLOAT__", TI.getFloatWidth(), TI, Builder); DefineTypeSizeof("__SIZEOF_INT__", TI.getIntWidth(), TI, Builder); DefineTypeSizeof("__SIZEOF_LONG__", TI.getLongWidth(), TI, Builder); DefineTypeSizeof("__SIZEOF_LONG_DOUBLE__",TI.getLongDoubleWidth(),TI,Builder); DefineTypeSizeof("__SIZEOF_LONG_LONG__", TI.getLongLongWidth(), TI, Builder); DefineTypeSizeof("__SIZEOF_POINTER__", TI.getPointerWidth(0), TI, Builder); DefineTypeSizeof("__SIZEOF_SHORT__", TI.getShortWidth(), TI, Builder); DefineTypeSizeof("__SIZEOF_PTRDIFF_T__", TI.getTypeWidth(TI.getPtrDiffType(0)), TI, Builder); DefineTypeSizeof("__SIZEOF_SIZE_T__", TI.getTypeWidth(TI.getSizeType()), TI, Builder); DefineTypeSizeof("__SIZEOF_WCHAR_T__", TI.getTypeWidth(TI.getWCharType()), TI, Builder); DefineTypeSizeof("__SIZEOF_WINT_T__", TI.getTypeWidth(TI.getWIntType()), TI, Builder); if (TI.hasInt128Type()) DefineTypeSizeof("__SIZEOF_INT128__", 128, TI, Builder); DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Builder); DefineFmt("__INTMAX", TI.getIntMaxType(), TI, Builder); Builder.defineMacro("__INTMAX_C_SUFFIX__", TI.getTypeConstantSuffix(TI.getIntMaxType())); DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Builder); DefineFmt("__UINTMAX", TI.getUIntMaxType(), TI, Builder); Builder.defineMacro("__UINTMAX_C_SUFFIX__", TI.getTypeConstantSuffix(TI.getUIntMaxType())); DefineTypeWidth("__INTMAX_WIDTH__", TI.getIntMaxType(), TI, Builder); DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(0), Builder); DefineFmt("__PTRDIFF", TI.getPtrDiffType(0), TI, Builder); DefineTypeWidth("__PTRDIFF_WIDTH__", TI.getPtrDiffType(0), TI, Builder); DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Builder); DefineFmt("__INTPTR", TI.getIntPtrType(), TI, Builder); DefineTypeWidth("__INTPTR_WIDTH__", TI.getIntPtrType(), TI, Builder); DefineType("__SIZE_TYPE__", TI.getSizeType(), Builder); DefineFmt("__SIZE", TI.getSizeType(), TI, Builder); DefineTypeWidth("__SIZE_WIDTH__", TI.getSizeType(), TI, Builder); DefineType("__WCHAR_TYPE__", TI.getWCharType(), Builder); DefineTypeWidth("__WCHAR_WIDTH__", TI.getWCharType(), TI, Builder); DefineType("__WINT_TYPE__", TI.getWIntType(), Builder); DefineTypeWidth("__WINT_WIDTH__", TI.getWIntType(), TI, Builder); DefineTypeWidth("__SIG_ATOMIC_WIDTH__", TI.getSigAtomicType(), TI, Builder); DefineTypeSize("__SIG_ATOMIC_MAX__", TI.getSigAtomicType(), TI, Builder); DefineType("__CHAR16_TYPE__", TI.getChar16Type(), Builder); DefineType("__CHAR32_TYPE__", TI.getChar32Type(), Builder); DefineTypeWidth("__UINTMAX_WIDTH__", TI.getUIntMaxType(), TI, Builder); DefineType("__UINTPTR_TYPE__", TI.getUIntPtrType(), Builder); DefineFmt("__UINTPTR", TI.getUIntPtrType(), TI, Builder); DefineTypeWidth("__UINTPTR_WIDTH__", TI.getUIntPtrType(), TI, Builder); DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F"); DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), ""); DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L"); // Define a __POINTER_WIDTH__ macro for stdint.h. Builder.defineMacro("__POINTER_WIDTH__", Twine((int)TI.getPointerWidth(0))); // Define __BIGGEST_ALIGNMENT__ to be compatible with gcc. Builder.defineMacro("__BIGGEST_ALIGNMENT__", Twine(TI.getSuitableAlign() / TI.getCharWidth()) ); if (!LangOpts.CharIsSigned) Builder.defineMacro("__CHAR_UNSIGNED__"); if (!TargetInfo::isTypeSigned(TI.getWCharType())) Builder.defineMacro("__WCHAR_UNSIGNED__"); if (!TargetInfo::isTypeSigned(TI.getWIntType())) Builder.defineMacro("__WINT_UNSIGNED__"); // Define exact-width integer types for stdint.h DefineExactWidthIntType(TargetInfo::SignedChar, TI, Builder); if (TI.getShortWidth() > TI.getCharWidth()) DefineExactWidthIntType(TargetInfo::SignedShort, TI, Builder); if (TI.getIntWidth() > TI.getShortWidth()) DefineExactWidthIntType(TargetInfo::SignedInt, TI, Builder); if (TI.getLongWidth() > TI.getIntWidth()) DefineExactWidthIntType(TargetInfo::SignedLong, TI, Builder); if (TI.getLongLongWidth() > TI.getLongWidth()) DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Builder); DefineExactWidthIntType(TargetInfo::UnsignedChar, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::UnsignedChar, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::SignedChar, TI, Builder); if (TI.getShortWidth() > TI.getCharWidth()) { DefineExactWidthIntType(TargetInfo::UnsignedShort, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::UnsignedShort, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::SignedShort, TI, Builder); } if (TI.getIntWidth() > TI.getShortWidth()) { DefineExactWidthIntType(TargetInfo::UnsignedInt, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::UnsignedInt, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::SignedInt, TI, Builder); } if (TI.getLongWidth() > TI.getIntWidth()) { DefineExactWidthIntType(TargetInfo::UnsignedLong, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::UnsignedLong, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::SignedLong, TI, Builder); } if (TI.getLongLongWidth() > TI.getLongWidth()) { DefineExactWidthIntType(TargetInfo::UnsignedLongLong, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::UnsignedLongLong, TI, Builder); DefineExactWidthIntTypeSize(TargetInfo::SignedLongLong, TI, Builder); } DefineLeastWidthIntType(8, true, TI, Builder); DefineLeastWidthIntType(8, false, TI, Builder); DefineLeastWidthIntType(16, true, TI, Builder); DefineLeastWidthIntType(16, false, TI, Builder); DefineLeastWidthIntType(32, true, TI, Builder); DefineLeastWidthIntType(32, false, TI, Builder); DefineLeastWidthIntType(64, true, TI, Builder); DefineLeastWidthIntType(64, false, TI, Builder); DefineFastIntType(8, true, TI, Builder); DefineFastIntType(8, false, TI, Builder); DefineFastIntType(16, true, TI, Builder); DefineFastIntType(16, false, TI, Builder); DefineFastIntType(32, true, TI, Builder); DefineFastIntType(32, false, TI, Builder); DefineFastIntType(64, true, TI, Builder); DefineFastIntType(64, false, TI, Builder); char UserLabelPrefix[2] = {TI.getDataLayout().getGlobalPrefix(), 0}; Builder.defineMacro("__USER_LABEL_PREFIX__", UserLabelPrefix); if (LangOpts.FastMath || LangOpts.FiniteMathOnly) Builder.defineMacro("__FINITE_MATH_ONLY__", "1"); else Builder.defineMacro("__FINITE_MATH_ONLY__", "0"); if (!LangOpts.MSVCCompat) { if (LangOpts.GNUInline || LangOpts.CPlusPlus) Builder.defineMacro("__GNUC_GNU_INLINE__"); else Builder.defineMacro("__GNUC_STDC_INLINE__"); // The value written by __atomic_test_and_set. // FIXME: This is target-dependent. Builder.defineMacro("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL", "1"); // Used by libc++ and libstdc++ to implement ATOMIC_<foo>_LOCK_FREE. unsigned InlineWidthBits = TI.getMaxAtomicInlineWidth(); #define DEFINE_LOCK_FREE_MACRO(TYPE, Type) \ Builder.defineMacro("__GCC_ATOMIC_" #TYPE "_LOCK_FREE", \ getLockFreeValue(TI.get##Type##Width(), \ TI.get##Type##Align(), \ InlineWidthBits)); DEFINE_LOCK_FREE_MACRO(BOOL, Bool); DEFINE_LOCK_FREE_MACRO(CHAR, Char); DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16); DEFINE_LOCK_FREE_MACRO(CHAR32_T, Char32); DEFINE_LOCK_FREE_MACRO(WCHAR_T, WChar); DEFINE_LOCK_FREE_MACRO(SHORT, Short); DEFINE_LOCK_FREE_MACRO(INT, Int); DEFINE_LOCK_FREE_MACRO(LONG, Long); DEFINE_LOCK_FREE_MACRO(LLONG, LongLong); Builder.defineMacro("__GCC_ATOMIC_POINTER_LOCK_FREE", getLockFreeValue(TI.getPointerWidth(0), TI.getPointerAlign(0), InlineWidthBits)); #undef DEFINE_LOCK_FREE_MACRO } if (LangOpts.NoInlineDefine) Builder.defineMacro("__NO_INLINE__"); if (unsigned PICLevel = LangOpts.PICLevel) { Builder.defineMacro("__PIC__", Twine(PICLevel)); Builder.defineMacro("__pic__", Twine(PICLevel)); } if (unsigned PIELevel = LangOpts.PIELevel) { Builder.defineMacro("__PIE__", Twine(PIELevel)); Builder.defineMacro("__pie__", Twine(PIELevel)); } // Macros to control C99 numerics and <float.h> Builder.defineMacro("__FLT_EVAL_METHOD__", Twine(TI.getFloatEvalMethod())); Builder.defineMacro("__FLT_RADIX__", "2"); Builder.defineMacro("__DECIMAL_DIG__", "__LDBL_DECIMAL_DIG__"); if (LangOpts.getStackProtector() == LangOptions::SSPOn) Builder.defineMacro("__SSP__"); else if (LangOpts.getStackProtector() == LangOptions::SSPStrong) Builder.defineMacro("__SSP_STRONG__", "2"); else if (LangOpts.getStackProtector() == LangOptions::SSPReq) Builder.defineMacro("__SSP_ALL__", "3"); // Define a macro that exists only when using the static analyzer. if (FEOpts.ProgramAction == frontend::RunAnalysis) Builder.defineMacro("__clang_analyzer__"); if (LangOpts.FastRelaxedMath) Builder.defineMacro("__FAST_RELAXED_MATH__"); if (FEOpts.ProgramAction == frontend::RewriteObjC || LangOpts.getGC() != LangOptions::NonGC) { Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))"); Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))"); Builder.defineMacro("__autoreleasing", ""); Builder.defineMacro("__unsafe_unretained", ""); } else if (LangOpts.ObjC1) { Builder.defineMacro("__weak", "__attribute__((objc_ownership(weak)))"); Builder.defineMacro("__strong", "__attribute__((objc_ownership(strong)))"); Builder.defineMacro("__autoreleasing", "__attribute__((objc_ownership(autoreleasing)))"); Builder.defineMacro("__unsafe_unretained", "__attribute__((objc_ownership(none)))"); } // On Darwin, there are __double_underscored variants of the type // nullability qualifiers. if (TI.getTriple().isOSDarwin()) { Builder.defineMacro("__nonnull", "_Nonnull"); Builder.defineMacro("__null_unspecified", "_Null_unspecified"); Builder.defineMacro("__nullable", "_Nullable"); } // OpenMP definition // OpenMP 2.2: // In implementations that support a preprocessor, the _OPENMP // macro name is defined to have the decimal value yyyymm where // yyyy and mm are the year and the month designations of the // version of the OpenMP API that the implementation support. switch (LangOpts.OpenMP) { case 0: break; case 40: Builder.defineMacro("_OPENMP", "201307"); break; case 45: Builder.defineMacro("_OPENMP", "201511"); break; default: // Default version is OpenMP 3.1 Builder.defineMacro("_OPENMP", "201107"); break; } // CUDA device path compilaton if (LangOpts.CUDAIsDevice) { // The CUDA_ARCH value is set for the GPU target specified in the NVPTX // backend's target defines. Builder.defineMacro("__CUDA_ARCH__"); } // We need to communicate this to our CUDA header wrapper, which in turn // informs the proper CUDA headers of this choice. if (LangOpts.CUDADeviceApproxTranscendentals || LangOpts.FastMath) { Builder.defineMacro("__CLANG_CUDA_APPROX_TRANSCENDENTALS__"); } // OpenCL definitions. if (LangOpts.OpenCL) { #define OPENCLEXT(Ext) \ if (TI.getSupportedOpenCLOpts().is_##Ext##_supported( \ LangOpts.OpenCLVersion)) \ Builder.defineMacro(#Ext); #include "clang/Basic/OpenCLExtensions.def" } // Get other target #defines. TI.getTargetDefines(LangOpts, Builder); }
void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { FullCommentParts Parts(C, Traits); const DeclInfo *DI = C->getDeclInfo(); StringRef RootEndTag; if (DI) { switch (DI->getKind()) { case DeclInfo::OtherKind: RootEndTag = "</Other>"; Result << "<Other"; break; case DeclInfo::FunctionKind: RootEndTag = "</Function>"; Result << "<Function"; switch (DI->TemplateKind) { case DeclInfo::NotTemplate: break; case DeclInfo::Template: Result << " templateKind=\"template\""; break; case DeclInfo::TemplateSpecialization: Result << " templateKind=\"specialization\""; break; case DeclInfo::TemplatePartialSpecialization: llvm_unreachable("partial specializations of functions " "are not allowed in C++"); } if (DI->IsInstanceMethod) Result << " isInstanceMethod=\"1\""; if (DI->IsClassMethod) Result << " isClassMethod=\"1\""; break; case DeclInfo::ClassKind: RootEndTag = "</Class>"; Result << "<Class"; switch (DI->TemplateKind) { case DeclInfo::NotTemplate: break; case DeclInfo::Template: Result << " templateKind=\"template\""; break; case DeclInfo::TemplateSpecialization: Result << " templateKind=\"specialization\""; break; case DeclInfo::TemplatePartialSpecialization: Result << " templateKind=\"partialSpecialization\""; break; } break; case DeclInfo::VariableKind: RootEndTag = "</Variable>"; Result << "<Variable"; break; case DeclInfo::NamespaceKind: RootEndTag = "</Namespace>"; Result << "<Namespace"; break; case DeclInfo::TypedefKind: RootEndTag = "</Typedef>"; Result << "<Typedef"; break; case DeclInfo::EnumKind: RootEndTag = "</Enum>"; Result << "<Enum"; break; } { // Print line and column number. SourceLocation Loc = DI->CurrentDecl->getLocation(); std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); FileID FID = LocInfo.first; unsigned FileOffset = LocInfo.second; if (FID.isValid()) { if (const FileEntry *FE = SM.getFileEntryForID(FID)) { Result << " file=\""; appendToResultWithXMLEscaping(FE->getName()); Result << "\""; } Result << " line=\"" << SM.getLineNumber(FID, FileOffset) << "\" column=\"" << SM.getColumnNumber(FID, FileOffset) << "\""; } } // Finish the root tag. Result << ">"; bool FoundName = false; if (const NamedDecl *ND = dyn_cast<NamedDecl>(DI->CommentDecl)) { if (DeclarationName DeclName = ND->getDeclName()) { Result << "<Name>"; std::string Name = DeclName.getAsString(); appendToResultWithXMLEscaping(Name); FoundName = true; Result << "</Name>"; } } if (!FoundName) Result << "<Name><anonymous></Name>"; { // Print USR. SmallString<128> USR; generateUSRForDecl(DI->CommentDecl, USR); if (!USR.empty()) { Result << "<USR>"; appendToResultWithXMLEscaping(USR); Result << "</USR>"; } } } else { // No DeclInfo -- just emit some root tag and name tag. RootEndTag = "</Other>"; Result << "<Other><Name>unknown</Name>"; } if (Parts.Headerfile) { Result << "<Headerfile>"; visit(Parts.Headerfile); Result << "</Headerfile>"; } { // Pretty-print the declaration. Result << "<Declaration>"; SmallString<128> Declaration; getSourceTextOfDeclaration(DI, Declaration); formatTextOfDeclaration(DI, Declaration); appendToResultWithXMLEscaping(Declaration); Result << "</Declaration>"; } bool FirstParagraphIsBrief = false; if (Parts.Brief) { Result << "<Abstract>"; visit(Parts.Brief); Result << "</Abstract>"; } else if (Parts.FirstParagraph) { Result << "<Abstract>"; visit(Parts.FirstParagraph); Result << "</Abstract>"; FirstParagraphIsBrief = true; } if (Parts.TParams.size() != 0) { Result << "<TemplateParameters>"; for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i) visit(Parts.TParams[i]); Result << "</TemplateParameters>"; } if (Parts.Params.size() != 0) { Result << "<Parameters>"; for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i) visit(Parts.Params[i]); Result << "</Parameters>"; } if (Parts.Exceptions.size() != 0) { Result << "<Exceptions>"; for (unsigned i = 0, e = Parts.Exceptions.size(); i != e; ++i) visit(Parts.Exceptions[i]); Result << "</Exceptions>"; } if (Parts.Returns.size() != 0) { Result << "<ResultDiscussion>"; for (unsigned i = 0, e = Parts.Returns.size(); i != e; ++i) visit(Parts.Returns[i]); Result << "</ResultDiscussion>"; } if (DI->CommentDecl->hasAttrs()) { const AttrVec &Attrs = DI->CommentDecl->getAttrs(); for (unsigned i = 0, e = Attrs.size(); i != e; i++) { const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attrs[i]); if (!AA) { if (const DeprecatedAttr *DA = dyn_cast<DeprecatedAttr>(Attrs[i])) { if (DA->getMessage().empty()) Result << "<Deprecated/>"; else { Result << "<Deprecated>"; appendToResultWithXMLEscaping(DA->getMessage()); Result << "</Deprecated>"; } } else if (const UnavailableAttr *UA = dyn_cast<UnavailableAttr>(Attrs[i])) { if (UA->getMessage().empty()) Result << "<Unavailable/>"; else { Result << "<Unavailable>"; appendToResultWithXMLEscaping(UA->getMessage()); Result << "</Unavailable>"; } } continue; } // 'availability' attribute. Result << "<Availability"; StringRef Distribution; if (AA->getPlatform()) { Distribution = AvailabilityAttr::getPrettyPlatformName( AA->getPlatform()->getName()); if (Distribution.empty()) Distribution = AA->getPlatform()->getName(); } Result << " distribution=\"" << Distribution << "\">"; VersionTuple IntroducedInVersion = AA->getIntroduced(); if (!IntroducedInVersion.empty()) { Result << "<IntroducedInVersion>" << IntroducedInVersion.getAsString() << "</IntroducedInVersion>"; } VersionTuple DeprecatedInVersion = AA->getDeprecated(); if (!DeprecatedInVersion.empty()) { Result << "<DeprecatedInVersion>" << DeprecatedInVersion.getAsString() << "</DeprecatedInVersion>"; } VersionTuple RemovedAfterVersion = AA->getObsoleted(); if (!RemovedAfterVersion.empty()) { Result << "<RemovedAfterVersion>" << RemovedAfterVersion.getAsString() << "</RemovedAfterVersion>"; } StringRef DeprecationSummary = AA->getMessage(); if (!DeprecationSummary.empty()) { Result << "<DeprecationSummary>"; appendToResultWithXMLEscaping(DeprecationSummary); Result << "</DeprecationSummary>"; } if (AA->getUnavailable()) Result << "<Unavailable/>"; Result << "</Availability>"; } } { bool StartTagEmitted = false; for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) { const Comment *C = Parts.MiscBlocks[i]; if (FirstParagraphIsBrief && C == Parts.FirstParagraph) continue; if (!StartTagEmitted) { Result << "<Discussion>"; StartTagEmitted = true; } visit(C); } if (StartTagEmitted) Result << "</Discussion>"; } Result << RootEndTag; }
/// \brief Determine the availability of the given declaration based on /// the target platform. /// /// When it returns an availability result other than \c AR_Available, /// if the \p Message parameter is non-NULL, it will be set to a /// string describing why the entity is unavailable. /// /// FIXME: Make these strings localizable, since they end up in /// diagnostics. static AvailabilityResult CheckAvailability(ASTContext &Context, const AvailabilityAttr *A, std::string *Message) { StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); StringRef PrettyPlatformName = AvailabilityAttr::getPrettyPlatformName(TargetPlatform); if (PrettyPlatformName.empty()) PrettyPlatformName = TargetPlatform; VersionTuple TargetMinVersion = Context.getTargetInfo().getPlatformMinVersion(); if (TargetMinVersion.empty()) return AR_Available; // Match the platform name. if (A->getPlatform()->getName() != TargetPlatform) return AR_Available; std::string HintMessage; if (!A->getMessage().empty()) { HintMessage = " - "; HintMessage += A->getMessage(); } // Make sure that this declaration has not been marked 'unavailable'. if (A->getUnavailable()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); Out << "not available on " << PrettyPlatformName << HintMessage; } return AR_Unavailable; } // Make sure that this declaration has already been introduced. if (!A->getIntroduced().empty() && TargetMinVersion < A->getIntroduced()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); Out << "introduced in " << PrettyPlatformName << ' ' << A->getIntroduced() << HintMessage; } return AR_NotYetIntroduced; } // Make sure that this declaration hasn't been obsoleted. if (!A->getObsoleted().empty() && TargetMinVersion >= A->getObsoleted()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); Out << "obsoleted in " << PrettyPlatformName << ' ' << A->getObsoleted() << HintMessage; } return AR_Unavailable; } // Make sure that this declaration hasn't been deprecated. if (!A->getDeprecated().empty() && TargetMinVersion >= A->getDeprecated()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); Out << "first deprecated in " << PrettyPlatformName << ' ' << A->getDeprecated() << HintMessage; } return AR_Deprecated; } return AR_Available; }