void c2ffi::init_ci(config &c, clang::CompilerInstance &ci) { using clang::DiagnosticOptions; using clang::TextDiagnosticPrinter; using clang::TargetOptions; using clang::TargetInfo; DiagnosticOptions *dopt = new DiagnosticOptions; TextDiagnosticPrinter *tpd = new TextDiagnosticPrinter(llvm::errs(), dopt, false); ci.createDiagnostics(tpd); std::shared_ptr<TargetOptions> pto = std::shared_ptr<TargetOptions>(new TargetOptions()); if(c.arch == "") pto->Triple = llvm::sys::getDefaultTargetTriple(); else pto->Triple = c.arch; TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto); clang::LangOptions &lo = ci.getLangOpts(); switch(pti->getTriple().getEnvironment()) { case llvm::Triple::EnvironmentType::GNU: lo.GNUMode = 1; break; case llvm::Triple::EnvironmentType::MSVC: lo.MSVCCompat = 1; lo.MicrosoftExt = 1; break; default: std::cerr << "c2ffi warning: Unhandled environment: '" << pti->getTriple().getEnvironmentName().str() << "' for triple '" << c.arch << "'" << std::endl; } ci.getInvocation().setLangDefaults(lo, c.kind, c.std); ci.setTarget(pti); ci.createFileManager(); ci.createSourceManager(ci.getFileManager()); ci.createPreprocessor(clang::TU_Complete); ci.getPreprocessorOpts().UsePredefines = false; ci.getPreprocessorOutputOpts().ShowCPP = c.preprocess_only; ci.getPreprocessor().setPreprocessedOutput(c.preprocess_only); }
void CIFactory::SetClingTargetLangOpts(LangOptions& Opts, const TargetInfo& Target) { if (Target.getTriple().getOS() == llvm::Triple::Win32) { Opts.MicrosoftExt = 1; Opts.MSCVersion = 1300; // Should fix http://llvm.org/bugs/show_bug.cgi?id=10528 Opts.DelayedTemplateParsing = 1; } else { Opts.MicrosoftExt = 0; } }
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); }
bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { switch (LM.getKind()) { case LengthModifier::None: return true; // Handle most integer flags case LengthModifier::AsShort: if (Target.getTriple().isOSMSVCRT()) { switch (CS.getKind()) { case ConversionSpecifier::cArg: case ConversionSpecifier::CArg: case ConversionSpecifier::sArg: case ConversionSpecifier::SArg: case ConversionSpecifier::ZArg: return true; default: break; } } // Fall through. case LengthModifier::AsChar: case LengthModifier::AsLongLong: case LengthModifier::AsQuad: case LengthModifier::AsIntMax: case LengthModifier::AsSizeT: case LengthModifier::AsPtrDiff: switch (CS.getKind()) { case ConversionSpecifier::dArg: case ConversionSpecifier::DArg: case ConversionSpecifier::iArg: case ConversionSpecifier::oArg: case ConversionSpecifier::OArg: case ConversionSpecifier::uArg: case ConversionSpecifier::UArg: case ConversionSpecifier::xArg: case ConversionSpecifier::XArg: case ConversionSpecifier::nArg: return true; case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: return Target.getTriple().isOSFreeBSD(); default: return false; } // Handle 'l' flag case LengthModifier::AsLong: // or AsWideChar switch (CS.getKind()) { case ConversionSpecifier::dArg: case ConversionSpecifier::DArg: case ConversionSpecifier::iArg: case ConversionSpecifier::oArg: case ConversionSpecifier::OArg: case ConversionSpecifier::uArg: case ConversionSpecifier::UArg: case ConversionSpecifier::xArg: case ConversionSpecifier::XArg: case ConversionSpecifier::aArg: case ConversionSpecifier::AArg: case ConversionSpecifier::fArg: case ConversionSpecifier::FArg: case ConversionSpecifier::eArg: case ConversionSpecifier::EArg: case ConversionSpecifier::gArg: case ConversionSpecifier::GArg: case ConversionSpecifier::nArg: case ConversionSpecifier::cArg: case ConversionSpecifier::sArg: case ConversionSpecifier::ScanListArg: case ConversionSpecifier::ZArg: return true; case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: return Target.getTriple().isOSFreeBSD(); default: return false; } case LengthModifier::AsLongDouble: switch (CS.getKind()) { case ConversionSpecifier::aArg: case ConversionSpecifier::AArg: case ConversionSpecifier::fArg: case ConversionSpecifier::FArg: case ConversionSpecifier::eArg: case ConversionSpecifier::EArg: case ConversionSpecifier::gArg: case ConversionSpecifier::GArg: return true; // GNU libc extension. case ConversionSpecifier::dArg: case ConversionSpecifier::iArg: case ConversionSpecifier::oArg: case ConversionSpecifier::uArg: case ConversionSpecifier::xArg: case ConversionSpecifier::XArg: return !Target.getTriple().isOSDarwin() && !Target.getTriple().isOSWindows(); default: return false; } case LengthModifier::AsAllocate: switch (CS.getKind()) { case ConversionSpecifier::sArg: case ConversionSpecifier::SArg: case ConversionSpecifier::ScanListArg: return true; default: return false; } case LengthModifier::AsMAllocate: switch (CS.getKind()) { case ConversionSpecifier::cArg: case ConversionSpecifier::CArg: case ConversionSpecifier::sArg: case ConversionSpecifier::SArg: case ConversionSpecifier::ScanListArg: return true; default: return false; } case LengthModifier::AsInt32: case LengthModifier::AsInt3264: case LengthModifier::AsInt64: switch (CS.getKind()) { case ConversionSpecifier::dArg: case ConversionSpecifier::iArg: case ConversionSpecifier::oArg: case ConversionSpecifier::uArg: case ConversionSpecifier::xArg: case ConversionSpecifier::XArg: return Target.getTriple().isOSMSVCRT(); default: return false; } case LengthModifier::AsWide: switch (CS.getKind()) { case ConversionSpecifier::cArg: case ConversionSpecifier::CArg: case ConversionSpecifier::sArg: case ConversionSpecifier::SArg: case ConversionSpecifier::ZArg: return Target.getTriple().isOSMSVCRT(); default: return false; } } llvm_unreachable("Invalid LengthModifier Kind!"); }
static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, const char *&Beg, const char *E, unsigned &argIndex, const LangOptions &LO, const TargetInfo &Target, bool Warn, bool isFreeBSDKPrintf) { using namespace clang::analyze_format_string; using namespace clang::analyze_printf; const char *I = Beg; const char *Start = nullptr; UpdateOnReturn <const char*> UpdateBeg(Beg, I); // Look for a '%' character that indicates the start of a format specifier. for ( ; I != E ; ++I) { char c = *I; if (c == '\0') { // Detect spurious null characters, which are likely errors. H.HandleNullChar(I); return true; } if (c == '%') { Start = I++; // Record the start of the format specifier. break; } } // No format specifier found? if (!Start) return false; if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } PrintfSpecifier FS; if (ParseArgPosition(H, FS, Start, I, E)) return true; if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } const char *OSLogVisibilityFlagsStart = nullptr, *OSLogVisibilityFlagsEnd = nullptr; if (*I == '{') { OSLogVisibilityFlagsStart = I++; // Find the end of the modifier. while (I != E && *I != '}') { I++; } if (I == E) { if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } assert(*I == '}'); OSLogVisibilityFlagsEnd = I++; // Just see if 'private' or 'public' is the first word. os_log itself will // do any further parsing. const char *P = OSLogVisibilityFlagsStart + 1; while (P < OSLogVisibilityFlagsEnd && isspace(*P)) P++; const char *WordStart = P; while (P < OSLogVisibilityFlagsEnd && (isalnum(*P) || *P == '_')) P++; const char *WordEnd = P; StringRef Word(WordStart, WordEnd - WordStart); if (Word == "private") { FS.setIsPrivate(WordStart); } else if (Word == "public") { FS.setIsPublic(WordStart); } } // Look for flags (if any). bool hasMore = true; for ( ; I != E; ++I) { switch (*I) { default: hasMore = false; break; case '\'': // FIXME: POSIX specific. Always accept? FS.setHasThousandsGrouping(I); break; case '-': FS.setIsLeftJustified(I); break; case '+': FS.setHasPlusPrefix(I); break; case ' ': FS.setHasSpacePrefix(I); break; case '#': FS.setHasAlternativeForm(I); break; case '0': FS.setHasLeadingZeros(I); break; } if (!hasMore) break; } if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for the field width (if any). if (ParseFieldWidth(H, FS, Start, I, E, FS.usesPositionalArg() ? nullptr : &argIndex)) return true; if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for the precision (if any). if (*I == '.') { ++I; if (I == E) { if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } if (ParsePrecision(H, FS, Start, I, E, FS.usesPositionalArg() ? nullptr : &argIndex)) return true; if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } } // Look for the length modifier. if (ParseLengthModifier(FS, I, E, LO) && I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for the Objective-C modifier flags, if any. // We parse these here, even if they don't apply to // the conversion specifier, and then emit an error // later if the conversion specifier isn't '@'. This // enables better recovery, and we don't know if // these flags are applicable until later. const char *ObjCModifierFlagsStart = nullptr, *ObjCModifierFlagsEnd = nullptr; if (*I == '[') { ObjCModifierFlagsStart = I; ++I; auto flagStart = I; for (;; ++I) { ObjCModifierFlagsEnd = I; if (I == E) { if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Did we find the closing ']'? if (*I == ']') { if (ParseObjCFlags(H, FS, flagStart, I, Warn)) return true; ++I; break; } // There are no separators defined yet for multiple // Objective-C modifier flags. When those are // defined, this is the place to check. } } if (*I == '\0') { // Detect spurious null characters, which are likely errors. H.HandleNullChar(I); return true; } // Finally, look for the conversion specifier. const char *conversionPosition = I++; ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; switch (*conversionPosition) { default: break; // C99: 7.19.6.1 (section 8). case '%': k = ConversionSpecifier::PercentArg; break; case 'A': k = ConversionSpecifier::AArg; break; case 'E': k = ConversionSpecifier::EArg; break; case 'F': k = ConversionSpecifier::FArg; break; case 'G': k = ConversionSpecifier::GArg; break; case 'X': k = ConversionSpecifier::XArg; break; case 'a': k = ConversionSpecifier::aArg; break; case 'c': k = ConversionSpecifier::cArg; break; case 'd': k = ConversionSpecifier::dArg; break; case 'e': k = ConversionSpecifier::eArg; break; case 'f': k = ConversionSpecifier::fArg; break; case 'g': k = ConversionSpecifier::gArg; break; case 'i': k = ConversionSpecifier::iArg; break; case 'n': k = ConversionSpecifier::nArg; break; case 'o': k = ConversionSpecifier::oArg; break; case 'p': k = ConversionSpecifier::pArg; break; case 's': k = ConversionSpecifier::sArg; break; case 'u': k = ConversionSpecifier::uArg; break; case 'x': k = ConversionSpecifier::xArg; break; // POSIX specific. case 'C': k = ConversionSpecifier::CArg; break; case 'S': k = ConversionSpecifier::SArg; break; // Apple extension for os_log case 'P': k = ConversionSpecifier::PArg; break; // Objective-C. case '@': k = ConversionSpecifier::ObjCObjArg; break; // Glibc specific. case 'm': k = ConversionSpecifier::PrintErrno; break; // FreeBSD kernel specific. case 'b': if (isFreeBSDKPrintf) k = ConversionSpecifier::FreeBSDbArg; // int followed by char * break; case 'r': if (isFreeBSDKPrintf) k = ConversionSpecifier::FreeBSDrArg; // int break; case 'y': if (isFreeBSDKPrintf) k = ConversionSpecifier::FreeBSDyArg; // int break; // Apple-specific. case 'D': if (isFreeBSDKPrintf) k = ConversionSpecifier::FreeBSDDArg; // void * followed by char * else if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::DArg; break; case 'O': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::OArg; break; case 'U': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::UArg; break; // MS specific. case 'Z': if (Target.getTriple().isOSMSVCRT()) k = ConversionSpecifier::ZArg; } // Check to see if we used the Objective-C modifier flags with // a conversion specifier other than '@'. if (k != ConversionSpecifier::ObjCObjArg && k != ConversionSpecifier::InvalidSpecifier && ObjCModifierFlagsStart) { H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart, ObjCModifierFlagsEnd + 1, conversionPosition); return true; } PrintfConversionSpecifier CS(conversionPosition, k); FS.setConversionSpecifier(CS); if (CS.consumesDataArgument() && !FS.usesPositionalArg()) FS.setArgIndex(argIndex++); // FreeBSD kernel specific. if (k == ConversionSpecifier::FreeBSDbArg || k == ConversionSpecifier::FreeBSDDArg) argIndex++; if (k == ConversionSpecifier::InvalidSpecifier) { unsigned Len = I - Start; if (ParseUTF8InvalidSpecifier(Start, E, Len)) { CS.setEndScanList(Start + Len); FS.setConversionSpecifier(CS); } // Assume the conversion takes one argument. return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len); } return PrintfSpecifierResult(Start, FS); }
static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, const char *&Beg, const char *E, unsigned &argIndex, const LangOptions &LO, const TargetInfo &Target) { using namespace clang::analyze_format_string; using namespace clang::analyze_printf; const char *I = Beg; const char *Start = 0; UpdateOnReturn <const char*> UpdateBeg(Beg, I); // Look for a '%' character that indicates the start of a format specifier. for ( ; I != E ; ++I) { char c = *I; if (c == '\0') { // Detect spurious null characters, which are likely errors. H.HandleNullChar(I); return true; } if (c == '%') { Start = I++; // Record the start of the format specifier. break; } } // No format specifier found? if (!Start) return false; if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } PrintfSpecifier FS; if (ParseArgPosition(H, FS, Start, I, E)) return true; if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for flags (if any). bool hasMore = true; for ( ; I != E; ++I) { switch (*I) { default: hasMore = false; break; case '\'': // FIXME: POSIX specific. Always accept? FS.setHasThousandsGrouping(I); break; case '-': FS.setIsLeftJustified(I); break; case '+': FS.setHasPlusPrefix(I); break; case ' ': FS.setHasSpacePrefix(I); break; case '#': FS.setHasAlternativeForm(I); break; case '0': FS.setHasLeadingZeros(I); break; } if (!hasMore) break; } if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for the field width (if any). if (ParseFieldWidth(H, FS, Start, I, E, FS.usesPositionalArg() ? 0 : &argIndex)) return true; if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for the precision (if any). if (*I == '.') { ++I; if (I == E) { H.HandleIncompleteSpecifier(Start, E - Start); return true; } if (ParsePrecision(H, FS, Start, I, E, FS.usesPositionalArg() ? 0 : &argIndex)) return true; if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } } // Look for the length modifier. if (ParseLengthModifier(FS, I, E, LO) && I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } if (*I == '\0') { // Detect spurious null characters, which are likely errors. H.HandleNullChar(I); return true; } // Finally, look for the conversion specifier. const char *conversionPosition = I++; ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; switch (*conversionPosition) { default: break; // C99: 7.19.6.1 (section 8). case '%': k = ConversionSpecifier::PercentArg; break; case 'A': k = ConversionSpecifier::AArg; break; case 'E': k = ConversionSpecifier::EArg; break; case 'F': k = ConversionSpecifier::FArg; break; case 'G': k = ConversionSpecifier::GArg; break; case 'X': k = ConversionSpecifier::XArg; break; case 'a': k = ConversionSpecifier::aArg; break; case 'c': k = ConversionSpecifier::cArg; break; case 'd': k = ConversionSpecifier::dArg; break; case 'e': k = ConversionSpecifier::eArg; break; case 'f': k = ConversionSpecifier::fArg; break; case 'g': k = ConversionSpecifier::gArg; break; case 'i': k = ConversionSpecifier::iArg; break; case 'n': k = ConversionSpecifier::nArg; break; case 'o': k = ConversionSpecifier::oArg; break; case 'p': k = ConversionSpecifier::pArg; break; case 's': k = ConversionSpecifier::sArg; break; case 'u': k = ConversionSpecifier::uArg; break; case 'x': k = ConversionSpecifier::xArg; break; // POSIX specific. case 'C': k = ConversionSpecifier::CArg; break; case 'S': k = ConversionSpecifier::SArg; break; // Objective-C. case '@': k = ConversionSpecifier::ObjCObjArg; break; // Glibc specific. case 'm': k = ConversionSpecifier::PrintErrno; break; // Apple-specific case 'D': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::DArg; break; case 'O': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::OArg; break; case 'U': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::UArg; break; } PrintfConversionSpecifier CS(conversionPosition, k); FS.setConversionSpecifier(CS); if (CS.consumesDataArgument() && !FS.usesPositionalArg()) FS.setArgIndex(argIndex++); if (k == ConversionSpecifier::InvalidSpecifier) { // Assume the conversion takes one argument. return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start); } return PrintfSpecifierResult(Start, FS); }
// FIXME: Much of this is copy-paste from ParsePrintfSpecifier. // We can possibly refactor. static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H, const char *&Beg, const char *E, unsigned &argIndex, const LangOptions &LO, const TargetInfo &Target) { using namespace lfort::analyze_scanf; const char *I = Beg; const char *Start = 0; UpdateOnReturn <const char*> UpdateBeg(Beg, I); // Look for a '%' character that indicates the start of a format specifier. for ( ; I != E ; ++I) { char c = *I; if (c == '\0') { // Detect spurious null characters, which are likely errors. H.HandleNullChar(I); return true; } if (c == '%') { Start = I++; // Record the start of the format specifier. break; } } // No format specifier found? if (!Start) return false; if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } ScanfSpecifier FS; if (ParseArgPosition(H, FS, Start, I, E)) return true; if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for '*' flag if it is present. if (*I == '*') { FS.setSuppressAssignment(I); if (++I == E) { H.HandleIncompleteSpecifier(Start, E - Start); return true; } } // Look for the field width (if any). Unlike printf, this is either // a fixed integer or isn't present. const OptionalAmount &Amt = lfort::analyze_format_string::ParseAmount(I, E); if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) { assert(Amt.getHowSpecified() == OptionalAmount::Constant); FS.setFieldWidth(Amt); if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } } // Look for the length modifier. if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Detect spurious null characters, which are likely errors. if (*I == '\0') { H.HandleNullChar(I); return true; } // Finally, look for the conversion specifier. const char *conversionPosition = I++; ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier; switch (*conversionPosition) { default: break; case '%': k = ConversionSpecifier::PercentArg; break; case 'A': k = ConversionSpecifier::AArg; break; case 'E': k = ConversionSpecifier::EArg; break; case 'F': k = ConversionSpecifier::FArg; break; case 'G': k = ConversionSpecifier::GArg; break; case 'X': k = ConversionSpecifier::XArg; break; case 'a': k = ConversionSpecifier::aArg; break; case 'd': k = ConversionSpecifier::dArg; break; case 'e': k = ConversionSpecifier::eArg; break; case 'f': k = ConversionSpecifier::fArg; break; case 'g': k = ConversionSpecifier::gArg; break; case 'i': k = ConversionSpecifier::iArg; break; case 'n': k = ConversionSpecifier::nArg; break; case 'c': k = ConversionSpecifier::cArg; break; case 'C': k = ConversionSpecifier::CArg; break; case 'S': k = ConversionSpecifier::SArg; break; case '[': k = ConversionSpecifier::ScanListArg; break; case 'u': k = ConversionSpecifier::uArg; break; case 'x': k = ConversionSpecifier::xArg; break; case 'o': k = ConversionSpecifier::oArg; break; case 's': k = ConversionSpecifier::sArg; break; case 'p': k = ConversionSpecifier::pArg; break; // Apple extensions // Apple-specific case 'D': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::DArg; break; case 'O': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::OArg; break; case 'U': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::UArg; break; } ScanfConversionSpecifier CS(conversionPosition, k); if (k == ScanfConversionSpecifier::ScanListArg) { if (ParseScanList(H, CS, I, E)) return true; } FS.setConversionSpecifier(CS); if (CS.consumesDataArgument() && !FS.getSuppressAssignment() && !FS.usesPositionalArg()) FS.setArgIndex(argIndex++); // FIXME: '%' and '*' doesn't make sense. Issue a warning. // FIXME: 'ConsumedSoFar' and '*' doesn't make sense. if (k == ScanfConversionSpecifier::InvalidSpecifier) { // Assume the conversion takes one argument. return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, I - Beg); } return ScanfSpecifierResult(Start, FS); }
static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, const char *&Beg, const char *E, unsigned &argIndex, const LangOptions &LO, const TargetInfo &Target, bool Warn, bool isFreeBSDKPrintf) { using namespace clang::analyze_format_string; using namespace clang::analyze_printf; const char *I = Beg; const char *Start = nullptr; UpdateOnReturn <const char*> UpdateBeg(Beg, I); // Look for a '%' character that indicates the start of a format specifier. for ( ; I != E ; ++I) { char c = *I; if (c == '\0') { // Detect spurious null characters, which are likely errors. H.HandleNullChar(I); return true; } if (c == '%') { Start = I++; // Record the start of the format specifier. break; } } // No format specifier found? if (!Start) return false; if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } PrintfSpecifier FS; if (ParseArgPosition(H, FS, Start, I, E)) return true; if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } if (*I == '{') { ++I; unsigned char PrivacyFlags = 0; StringRef MatchedStr; do { StringRef Str(I, E - I); std::string Match = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})"; llvm::Regex R(Match); SmallVector<StringRef, 2> Matches; if (R.match(Str, &Matches)) { MatchedStr = Matches[1]; I += Matches[0].size(); // Set the privacy flag if the privacy annotation in the // comma-delimited segment is at least as strict as the privacy // annotations in previous comma-delimited segments. if (MatchedStr.equals("private")) PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate; else if (PrivacyFlags == 0 && MatchedStr.equals("public")) PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic; } else { size_t CommaOrBracePos = Str.find_if([](char c) { return c == ',' || c == '}'; }); if (CommaOrBracePos == StringRef::npos) { // Neither a comma nor the closing brace was found. if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } I += CommaOrBracePos + 1; } // Continue until the closing brace is found. } while (*(I - 1) == ','); // Set the privacy flag. switch (PrivacyFlags) { case 0: break; case clang::analyze_os_log::OSLogBufferItem::IsPrivate: FS.setIsPrivate(MatchedStr.data()); break; case clang::analyze_os_log::OSLogBufferItem::IsPublic: FS.setIsPublic(MatchedStr.data()); break; default: llvm_unreachable("Unexpected privacy flag value"); } } // Look for flags (if any). bool hasMore = true; for ( ; I != E; ++I) { switch (*I) { default: hasMore = false; break; case '\'': // FIXME: POSIX specific. Always accept? FS.setHasThousandsGrouping(I); break; case '-': FS.setIsLeftJustified(I); break; case '+': FS.setHasPlusPrefix(I); break; case ' ': FS.setHasSpacePrefix(I); break; case '#': FS.setHasAlternativeForm(I); break; case '0': FS.setHasLeadingZeros(I); break; } if (!hasMore) break; } if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for the field width (if any). if (ParseFieldWidth(H, FS, Start, I, E, FS.usesPositionalArg() ? nullptr : &argIndex)) return true; if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for the precision (if any). if (*I == '.') { ++I; if (I == E) { if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } if (ParsePrecision(H, FS, Start, I, E, FS.usesPositionalArg() ? nullptr : &argIndex)) return true; if (I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } } // Look for the length modifier. if (ParseLengthModifier(FS, I, E, LO) && I == E) { // No more characters left? if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Look for the Objective-C modifier flags, if any. // We parse these here, even if they don't apply to // the conversion specifier, and then emit an error // later if the conversion specifier isn't '@'. This // enables better recovery, and we don't know if // these flags are applicable until later. const char *ObjCModifierFlagsStart = nullptr, *ObjCModifierFlagsEnd = nullptr; if (*I == '[') { ObjCModifierFlagsStart = I; ++I; auto flagStart = I; for (;; ++I) { ObjCModifierFlagsEnd = I; if (I == E) { if (Warn) H.HandleIncompleteSpecifier(Start, E - Start); return true; } // Did we find the closing ']'? if (*I == ']') { if (ParseObjCFlags(H, FS, flagStart, I, Warn)) return true; ++I; break; } // There are no separators defined yet for multiple // Objective-C modifier flags. When those are // defined, this is the place to check. } } if (*I == '\0') { // Detect spurious null characters, which are likely errors. H.HandleNullChar(I); return true; } // Finally, look for the conversion specifier. const char *conversionPosition = I++; ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; switch (*conversionPosition) { default: break; // C99: 7.19.6.1 (section 8). case '%': k = ConversionSpecifier::PercentArg; break; case 'A': k = ConversionSpecifier::AArg; break; case 'E': k = ConversionSpecifier::EArg; break; case 'F': k = ConversionSpecifier::FArg; break; case 'G': k = ConversionSpecifier::GArg; break; case 'X': k = ConversionSpecifier::XArg; break; case 'a': k = ConversionSpecifier::aArg; break; case 'c': k = ConversionSpecifier::cArg; break; case 'd': k = ConversionSpecifier::dArg; break; case 'e': k = ConversionSpecifier::eArg; break; case 'f': k = ConversionSpecifier::fArg; break; case 'g': k = ConversionSpecifier::gArg; break; case 'i': k = ConversionSpecifier::iArg; break; case 'n': k = ConversionSpecifier::nArg; break; case 'o': k = ConversionSpecifier::oArg; break; case 'p': k = ConversionSpecifier::pArg; break; case 's': k = ConversionSpecifier::sArg; break; case 'u': k = ConversionSpecifier::uArg; break; case 'x': k = ConversionSpecifier::xArg; break; // POSIX specific. case 'C': k = ConversionSpecifier::CArg; break; case 'S': k = ConversionSpecifier::SArg; break; // Apple extension for os_log case 'P': k = ConversionSpecifier::PArg; break; // Objective-C. case '@': k = ConversionSpecifier::ObjCObjArg; break; // Glibc specific. case 'm': k = ConversionSpecifier::PrintErrno; break; // FreeBSD kernel specific. case 'b': if (isFreeBSDKPrintf) k = ConversionSpecifier::FreeBSDbArg; // int followed by char * break; case 'r': if (isFreeBSDKPrintf) k = ConversionSpecifier::FreeBSDrArg; // int break; case 'y': if (isFreeBSDKPrintf) k = ConversionSpecifier::FreeBSDyArg; // int break; // Apple-specific. case 'D': if (isFreeBSDKPrintf) k = ConversionSpecifier::FreeBSDDArg; // void * followed by char * else if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::DArg; break; case 'O': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::OArg; break; case 'U': if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::UArg; break; // MS specific. case 'Z': if (Target.getTriple().isOSMSVCRT()) k = ConversionSpecifier::ZArg; } // Check to see if we used the Objective-C modifier flags with // a conversion specifier other than '@'. if (k != ConversionSpecifier::ObjCObjArg && k != ConversionSpecifier::InvalidSpecifier && ObjCModifierFlagsStart) { H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart, ObjCModifierFlagsEnd + 1, conversionPosition); return true; } PrintfConversionSpecifier CS(conversionPosition, k); FS.setConversionSpecifier(CS); if (CS.consumesDataArgument() && !FS.usesPositionalArg()) FS.setArgIndex(argIndex++); // FreeBSD kernel specific. if (k == ConversionSpecifier::FreeBSDbArg || k == ConversionSpecifier::FreeBSDDArg) argIndex++; if (k == ConversionSpecifier::InvalidSpecifier) { unsigned Len = I - Start; if (ParseUTF8InvalidSpecifier(Start, E, Len)) { CS.setEndScanList(Start + Len); FS.setConversionSpecifier(CS); } // Assume the conversion takes one argument. return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len); } return PrintfSpecifierResult(Start, FS); }
int main(int argc, const char **argv, char * const *envp) { // Path void *MainAddr = (void*) (intptr_t) GetExecutablePath; llvm::sys::Path Path = GetExecutablePath(argv[0]); // DiagnosticOptions DiagnosticOptions diagnosticOptions; // DiagnosticClient TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::outs(), diagnosticOptions); // Diagnostic llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); Diagnostic diagnostic(DiagID, DiagClient); //DiagnosticOptions DiagOpts; //llvm::IntrusiveRefCntPtr<Diagnostic> diagnostic = CompilerInstance::createDiagnostics(DiagOpts, argc, argv); // LangOptions LangOptions langOptions; langOptions.CPlusPlus = 1; langOptions.CPlusPlus0x = 1; langOptions.Microsoft = 1; langOptions.Bool = 1; langOptions.Exceptions = 1; langOptions.CXXExceptions = 1; langOptions.EmitAllDecls = 1; // FileManager FileSystemOptions fileSystemOptions; FileManager fileManager(fileSystemOptions); // SourceManager SourceManager sourceManager(diagnostic, fileManager); // HeadderSearch HeaderSearch headerSearch(fileManager); // TargetOptions TargetOptions targetOptions; targetOptions.Triple = llvm::sys::getHostTriple(); // TargetInfo TargetInfo *pTargetInfo = TargetInfo::CreateTargetInfo( diagnostic, targetOptions); // HeaderSearchOptions HeaderSearchOptions headerSearchOptions; ApplyHeaderSearchOptions( headerSearch, headerSearchOptions, langOptions, pTargetInfo->getTriple()); // Preprocessor Preprocessor preprocessor( diagnostic, langOptions, *pTargetInfo, sourceManager, headerSearch); // PreprocessorOptions PreprocessorOptions preprocessorOptions; preprocessorOptions.DetailedRecord = true; preprocessor.createPreprocessingRecord(); // FrontendOptions FrontendOptions frontendOptions; // InitializePreprocessor InitializePreprocessor( preprocessor, preprocessorOptions, headerSearchOptions, frontendOptions); //preprocessor.SetCommentRetentionState(true, true); // Tutorial const FileEntry *pFile = fileManager.getFile( "test.cpp", true); sourceManager.createMainFileID(pFile); /*preprocessor.EnterMainSourceFile(); Token Tok; do { preprocessor.Lex(Tok); // read one token //if (context.diags.hasErrorOccurred()) // stop lexing/pp on error // break; preprocessor.DumpToken(Tok); // outputs to cerr std::cerr << std::endl; } while (Tok.isNot(tok::eof));*/ const TargetInfo &targetInfo = *pTargetInfo; IdentifierTable identifierTable(langOptions); SelectorTable selectorTable; Builtin::Context builtinContext(targetInfo); ASTContext astContext( langOptions, sourceManager, targetInfo, identifierTable, selectorTable, builtinContext, 0 /* size_reserve*/); // ASTConsumer astConsumer; MyASTConsumer astConsumer; astConsumer.sourceManager = &sourceManager; astConsumer.html = new ClangDocHTML; astConsumer.html->astConsumer = &astConsumer; preprocessor.addPPCallbacks(astConsumer.html); preprocessor.AddCommentHandler(astConsumer.html); Sema sema( preprocessor, astContext, astConsumer); sema.Initialize(); //MySemanticAnalisys mySema( preprocessor, astContext, astConsumer); //Parser parser( preprocessor, sema); //parser.ParseTranslationUnit(); astConsumer.preprocessor = &sema.PP; ParseAST(preprocessor, &astConsumer, astContext); return 0; }
int main() { //string a; //raw_string_ostream ost(a); const DiagnosticOptions diagOptions; TextDiagnosticPrinter *tdp = new TextDiagnosticPrinter(outs(), diagOptions, true);//, dops); LangOptions lang; DiagnosticIDs *diagID; const llvm::IntrusiveRefCntPtr< DiagnosticIDs > Diags; Diagnostic diag(Diags, tdp, false); FileSystemOptions fsOptions; FileManager fm(fsOptions); SourceManager sm(diag, fm); //tut3 HeaderSearchOptions HSOpts; HSOpts.AddPath("/usr/include/linux/", frontend::System, false, false, true); // for stddef.h HSOpts.AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/", frontend::System, false, false, true); // for stdarg.h HeaderSearch headers(fm); TargetOptions tarOptions; tarOptions.Triple = LLVM_HOSTTRIPLE; TargetInfo *ti = TargetInfo::CreateTargetInfo(diag, tarOptions); //tut3 ApplyHeaderSearchOptions( headers, HSOpts, lang, ti->getTriple()); Preprocessor pp(diag, lang, *ti, sm, headers); //tut2--------------------------------------------------------------- const FileEntry *file = fm.getFile("input01.c"); sm.createMainFileID(file); pp.EnterMainSourceFile(); Token Tok; do { pp.Lex(Tok); if(diag.hasErrorOccurred()) break; pp.DumpToken(Tok); std::cerr << std::endl; } while(Tok.isNot(tok::eof)); //end of tut2--------------------------------------------------------------- //tut4--------------------------------------------------------------- IdentifierTable tab(lang); SelectorTable sels; Builtin::Context builtins(*ti); unsigned size = 0; ASTContext ctxt(lang, sm, *ti, tab, sels, builtins, size); ASTConsumer consumer; CodeCompleteConsumer *codeCompleter; MySemaAction sema(pp, ctxt, consumer, false, codeCompleter); Parser p(pp, sema); p.ParseTranslationUnit(); tab.PrintStats(); //end of tut4--------------------------------------------------------------- //DeclSpec DS; //Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); //sema.ActOnDeclarator(p.getCurScope(), DeclaratorInfo); return 0; }