diff --git a/interpreter/cling/.travis.yml b/interpreter/cling/.travis.yml index 39c3090528c1e..b739dae5479ab 100644 --- a/interpreter/cling/.travis.yml +++ b/interpreter/cling/.travis.yml @@ -200,7 +200,11 @@ install: fi if [ "$COMPILER" == "g++-6" ]; then - export CLING_BUILD_FLAGS="-DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD_REQUIRED=ON -DCXX_EXTENSIONS=OFF" + export CLING_BUILD_FLAGS="-DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD_REQUIRED=ON" + # On OS X force the test to reproduce __float128 issues with libstdc++. + if [ $TRAVIS_OS_NAME != 'osx' ]; then + export CLING_BUILD_FLAGS="$CLING_BUILD_FLAGS -DCXX_EXTENSIONS=OFF" + fi CMAKEREQ="3.8" else CMAKEREQ="3.6" diff --git a/interpreter/cling/include/cling/Interpreter/InvocationOptions.h b/interpreter/cling/include/cling/Interpreter/InvocationOptions.h index e08a68b0044c2..8ace791e7413c 100644 --- a/interpreter/cling/include/cling/Interpreter/InvocationOptions.h +++ b/interpreter/cling/include/cling/Interpreter/InvocationOptions.h @@ -13,6 +13,10 @@ #include #include +namespace clang { + class LangOptions; +}; + namespace cling { ///\brief Class that stores options that are used by both cling and @@ -36,6 +40,14 @@ namespace cling { void Parse(int argc, const char* const argv[], std::vector* Inputs = nullptr); + ///\brief By default clang will try to set up an Interpreter with features + /// that match how it was compiled. There are cases; however, where the + /// client is asking for something so specific (i.e './cling -std=gnu++11' + /// or './cling -x c') that this shouldn't be done. This will return false + /// in those cases. + /// + bool DefaultLanguage(const clang::LangOptions&) const; + unsigned Language : 1; unsigned ResourceDir : 1; unsigned SysRoot : 1; diff --git a/interpreter/cling/lib/Interpreter/CIFactory.cpp b/interpreter/cling/lib/Interpreter/CIFactory.cpp index a4d8ae4007404..989cb2c96c739 100644 --- a/interpreter/cling/lib/Interpreter/CIFactory.cpp +++ b/interpreter/cling/lib/Interpreter/CIFactory.cpp @@ -54,10 +54,6 @@ using namespace cling; namespace { static constexpr unsigned CxxStdCompiledWith() { - // Extracted from Boost/config/compiler. - // SunProCC has no C++11. - // VisualC's support is not obvious to extract from Boost... - // The value of __cplusplus in GCC < 5.0 (e.g. 4.9.3) when // either -std=c++1y or -std=c++14 is specified is 201300L, which fails // the test for C++14 or more (201402L) as previously specified. @@ -360,7 +356,8 @@ namespace { } } - static void SetClingCustomLangOpts(LangOptions& Opts) { + static void SetClingCustomLangOpts(LangOptions& Opts, + const CompilerOptions& CompilerOpts) { Opts.EmitAllDecls = 0; // Otherwise if PCH attached will codegen all decls. #ifdef _MSC_VER #ifdef _DEBUG @@ -395,7 +392,6 @@ namespace { // Except -fexceptions -fcxx-exceptions. Opts.Deprecated = 1; - Opts.GNUKeywords = 0; #ifdef __APPLE__ Opts.Blocks = 1; @@ -417,18 +413,23 @@ namespace { #ifdef _REENTRANT Opts.POSIXThreads = 1; #endif -#ifdef __STRICT_ANSI__ - Opts.GNUMode = 0; -#else - Opts.GNUMode = 1; -#endif #ifdef __FAST_MATH__ Opts.FastMath = 1; #endif + + if (CompilerOpts.DefaultLanguage(Opts)) { +#ifdef __STRICT_ANSI__ + Opts.GNUMode = 0; +#else + Opts.GNUMode = 1; +#endif + Opts.GNUKeywords = 0; + } } static void SetClingTargetLangOpts(LangOptions& Opts, - const TargetInfo& Target) { + const TargetInfo& Target, + const CompilerOptions& CompilerOpts) { if (Target.getTriple().getOS() == llvm::Triple::Win32) { Opts.MicrosoftExt = 1; #ifdef _MSC_VER @@ -439,21 +440,24 @@ namespace { } else { Opts.MicrosoftExt = 0; } + + if (CompilerOpts.DefaultLanguage(Opts)) { #if _GLIBCXX_USE_FLOAT128 - // We are compiling with libstdc++ with __float128 enabled. - if (!Target.hasFloat128Type()) { - // clang currently supports native __float128 only on few targets, and - // this target does not have it. The most visible consequence of this is a - // specialization - // __is_floating_point_helper<__float128> - // in include/c++/6.3.0/type_traits:344 that clang then rejects. The - // specialization is protected by !if _GLIBCXX_USE_FLOAT128 (which is - // unconditionally set in c++config.h) and #if !__STRICT_ANSI__. Tweak the - // latter by disabling GNUMode: + // We are compiling with libstdc++ with __float128 enabled. + if (!Target.hasFloat128Type()) { + // clang currently supports native __float128 only on few targets, and + // this target does not have it. The most visible consequence of this is a + // specialization + // __is_floating_point_helper<__float128> + // in include/c++/6.3.0/type_traits:344 that clang then rejects. The + // specialization is protected by !if _GLIBCXX_USE_FLOAT128 (which is + // unconditionally set in c++config.h) and #if !__STRICT_ANSI__. Tweak the + // latter by disabling GNUMode: # warning "Disabling gnu++: clang has no __float128 support on this target!" - Opts.GNUMode = 0; + Opts.GNUMode = 0; + } +#endif //_GLIBCXX_USE_FLOAT128 } -#endif //__GLIBCXX__ } // This must be a copy of clang::getClangToolFullVersion(). Luckily @@ -628,20 +632,21 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, } static bool - SetupCompiler(CompilerInstance* CI, bool Lang = true, bool Targ = true) { + SetupCompiler(CompilerInstance* CI, const CompilerOptions& CompilerOpts, + bool Lang = true, bool Targ = true) { // Set the language options, which cling needs. // This may have already been done via a precompiled header if (Lang) - SetClingCustomLangOpts(CI->getLangOpts()); + SetClingCustomLangOpts(CI->getLangOpts(), CompilerOpts); PreprocessorOptions& PPOpts = CI->getInvocation().getPreprocessorOpts(); SetPreprocessorFromBinary(PPOpts); PPOpts.addMacroDef("__CLING__"); - if (CI->getLangOpts().CPlusPlus11 == 1) { - // http://llvm.org/bugs/show_bug.cgi?id=13530 + if (CI->getLangOpts().CPlusPlus11 == 1) PPOpts.addMacroDef("__CLING__CXX11"); - } + if (CI->getLangOpts().CPlusPlus14 == 1) + PPOpts.addMacroDef("__CLING__CXX14"); if (CI->getDiagnostics().hasErrorOccurred()) { cling::errs() << "Compiler error to early in initialization.\n"; @@ -659,7 +664,7 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, // This may have already been done via a precompiled header if (Targ) - SetClingTargetLangOpts(CI->getLangOpts(), CI->getTarget()); + SetClingTargetLangOpts(CI->getLangOpts(), CI->getTarget(), CompilerOpts); SetPreprocessorFromTarget(PPOpts, CI->getTarget().getTriple()); return true; @@ -816,7 +821,7 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, "output is supported.\n"; return nullptr; } - if (!SetupCompiler(CI.get())) + if (!SetupCompiler(CI.get(), COpts)) return nullptr; ProcessWarningOptions(*Diags, DiagOpts); @@ -895,7 +900,7 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, Invocation.getFrontendOpts().DisableFree = true; // Set up compiler language and target - if (!SetupCompiler(CI.get(), InitLang, InitTarget)) + if (!SetupCompiler(CI.get(), COpts, InitLang, InitTarget)) return nullptr; // Set up source managers diff --git a/interpreter/cling/lib/Interpreter/InvocationOptions.cpp b/interpreter/cling/lib/Interpreter/InvocationOptions.cpp index c8cdfff3444f8..b40629911a5ed 100644 --- a/interpreter/cling/lib/Interpreter/InvocationOptions.cpp +++ b/interpreter/cling/lib/Interpreter/InvocationOptions.cpp @@ -11,6 +11,7 @@ #include "cling/Interpreter/ClingOptions.h" #include "cling/Utils/Output.h" +#include "clang/Basic/LangOptions.h" #include "clang/Driver/Options.h" #include "llvm/Option/Arg.h" @@ -144,6 +145,20 @@ void CompilerOptions::Parse(int argc, const char* const argv[], } } +bool CompilerOptions::DefaultLanguage(const LangOptions& LangOpts) const { + // When StdVersion is set (-std=c++11, -std=gnu++11, etc.) then definitely + // don't setup the defaults, as they may interfere with what the user is doing + if (StdVersion) + return false; + + // Also don't set up the defaults when language is explicitly set; unless + // the language was set to generate a PCH, in which case definitely do. + if (Language) + return LangOpts.CompilingPCH || HasOutput; + + return true; +} + InvocationOptions::InvocationOptions(int argc, const char* const* argv) : MetaString("."), ErrorOut(false), NoLogo(false), ShowVersion(false), Help(false), NoRuntime(false) { diff --git a/interpreter/cling/test/Driver/Gnu.C b/interpreter/cling/test/Driver/Gnu.C new file mode 100644 index 0000000000000..2f0b149f1ef83 --- /dev/null +++ b/interpreter/cling/test/Driver/Gnu.C @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +// CLING - the C++ LLVM-based InterpreterG :) +// +// This file is dual-licensed: you can choose to license it under the University +// of Illinois Open Source License or the GNU Lesser General Public License. See +// LICENSE.TXT for details. +//------------------------------------------------------------------------------ + +// RUN: cat %s | %cling -std=gnu99 -x c -Xclang -verify 2>&1 | FileCheck %s +// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++11 -Xclang -verify 2>&1 | FileCheck %s +// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++14 -Xclang -verify 2>&1 | FileCheck %s +// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++1z -Xclang -verify 2>&1 | FileCheck %s + +#ifdef __cplusplus +extern "C" int printf(const char*, ...); +#else +int printf(const char*, ...); +#endif + +typeof (int) Val = 22; +typeof (const char*) This = "THIS"; + +printf("TEST: %d '%s'\n", Val, This); +// CHECK: TEST: 22 'THIS' + +// expected-no-diagnostics +.q