2012-09-05 09:37:39 +00:00
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Axel Naumann <axel@cern.ch>
2014-01-07 11:08:37 +01:00
//
// 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.
2012-09-05 09:37:39 +00:00
//------------------------------------------------------------------------------
2015-04-16 03:33:55 -05:00
# include "ClingUtils.h"
2016-11-11 10:21:52 +01:00
# include <cling-compiledata.h>
2012-09-05 09:37:39 +00:00
2016-09-14 15:49:22 -04:00
# include "cling/Interpreter/CIFactory.h"
# include "cling/Interpreter/InvocationOptions.h"
2016-09-10 15:04:39 -04:00
# include "cling/Utils/Output.h"
2016-09-14 15:49:22 -04:00
# include "cling/Utils/Paths.h"
# include "cling/Utils/Platform.h"
2012-09-05 09:37:39 +00:00
# include "clang/AST/ASTContext.h"
# include "clang/Basic/TargetInfo.h"
# include "clang/Basic/Version.h"
# include "clang/Driver/Compilation.h"
# include "clang/Driver/Driver.h"
# include "clang/Driver/Job.h"
# include "clang/Driver/Tool.h"
2018-01-28 21:59:44 +01:00
# include "clang/Frontend/FrontendAction.h"
2016-07-21 18:29:10 -04:00
# include "clang/Frontend/FrontendDiagnostic.h"
2018-01-28 21:59:44 +01:00
# include "clang/Frontend/FrontendPluginRegistry.h"
2017-09-01 09:26:27 +02:00
# include "clang/Frontend/MultiplexConsumer.h"
2012-09-05 09:37:39 +00:00
# include "clang/Frontend/TextDiagnosticPrinter.h"
2014-03-28 12:39:38 +01:00
# include "clang/Frontend/VerifyDiagnosticConsumer.h"
2012-09-05 09:37:39 +00:00
# include "clang/Lex/Preprocessor.h"
2017-05-18 15:16:30 +02:00
# include "clang/Lex/PreprocessorOptions.h"
2013-11-18 16:49:19 +01:00
# include "clang/Sema/Sema.h"
2014-03-27 14:49:01 +01:00
# include "clang/Sema/SemaDiagnostic.h"
2015-07-03 17:42:10 +02:00
# include "clang/Serialization/ASTReader.h"
2017-09-01 09:26:27 +02:00
# include "clang/Serialization/ASTWriter.h"
# include "clang/Serialization/SerializationDiagnostic.h"
2012-09-05 09:37:39 +00:00
2016-06-17 11:23:43 +02:00
# include "llvm/Config/llvm-config.h"
2013-04-24 16:28:08 +00:00
# include "llvm/IR/LLVMContext.h"
2013-09-19 16:57:16 +02:00
# include "llvm/Option/ArgList.h"
2013-09-20 18:20:20 +02:00
# include "llvm/Support/FileSystem.h"
2012-09-05 09:37:39 +00:00
# include "llvm/Support/Host.h"
# include "llvm/Support/MemoryBuffer.h"
2017-05-18 15:16:30 +02:00
# include "llvm/Support/Path.h"
2013-04-24 19:49:12 +00:00
# include "llvm/Support/Process.h"
2017-05-10 08:18:54 +02:00
# include "llvm/Support/TargetSelect.h"
2016-09-14 15:49:22 -04:00
# include "llvm/Target/TargetOptions.h"
2012-09-05 09:37:39 +00:00
2013-12-18 16:19:30 +01:00
# include <cstdio>
2016-09-14 15:49:22 -04:00
# include <ctime>
2020-10-14 15:06:06 +02:00
# include <limits>
2014-08-14 12:29:27 +02:00
# include <memory>
2016-07-05 16:19:41 -04:00
using namespace clang ;
2016-08-08 16:29:06 -04:00
using namespace cling ;
2016-07-05 16:19:41 -04:00
namespace {
2017-06-14 10:49:07 -04:00
static constexpr unsigned CxxStdCompiledWith ( ) {
// 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.
// I would claim that the check should be relaxed to:
2020-03-11 12:40:10 +02:00
# if __cplusplus > 201703L
return 20 ;
# elif __cplusplus > 201402L
2017-06-14 10:49:07 -04:00
return 17 ;
2020-10-05 06:22:33 +00:00
# elif __cplusplus > 201103L || (defined(_WIN32) && _MSC_VER >= 1900)
2017-06-14 10:49:07 -04:00
return 14 ;
2017-07-04 16:48:39 +02:00
# elif __cplusplus >= 201103L
2017-06-14 10:49:07 -04:00
return 11 ;
# else
# error "Unknown __cplusplus version"
# endif
}
2016-08-16 05:46:10 -04:00
// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// GetMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement GetMainExecutable
// without being given the address of a function in the main executable).
std : : string GetExecutablePath ( const char * Argv0 ) {
// This just needs to be some symbol in the binary; C++ doesn't
// allow taking the address of ::main however.
void * MainAddr = ( void * ) intptr_t ( GetExecutablePath ) ;
return llvm : : sys : : fs : : getMainExecutable ( Argv0 , MainAddr ) ;
2016-06-09 04:32:38 -04:00
}
2016-07-05 15:10:04 -04:00
class AdditionalArgList {
typedef std : : vector < std : : pair < const char * , std : : string > > container_t ;
container_t m_Saved ;
public :
void addArgument ( const char * arg , std : : string value = std : : string ( ) ) {
m_Saved . push_back ( std : : make_pair ( arg , std : : move ( value ) ) ) ;
}
container_t : : const_iterator begin ( ) const { return m_Saved . begin ( ) ; }
container_t : : const_iterator end ( ) const { return m_Saved . end ( ) ; }
bool empty ( ) const { return m_Saved . empty ( ) ; }
} ;
2016-06-09 04:32:38 -04:00
# ifndef _MSC_VER
static void ReadCompilerIncludePaths ( const char * Compiler ,
llvm : : SmallVectorImpl < char > & Buf ,
2016-08-16 18:05:45 -04:00
AdditionalArgList & Args ,
bool Verbose ) {
2020-05-06 09:15:33 +02:00
std : : string CppInclQuery ( " LC_ALL=C " ) ;
CppInclQuery . append ( Compiler ) ;
2019-08-14 10:47:04 +02:00
CppInclQuery . append ( " -xc++ -E -v /dev/null 2>&1 | "
" sed -n -e '/^.include/,${' -e '/^ \\ /.*++/p' -e '}' " ) ;
2016-06-09 04:32:38 -04:00
2016-08-16 18:05:45 -04:00
if ( Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Looking for C++ headers with: \n " < < CppInclQuery < < " \n " ;
2016-08-16 18:05:45 -04:00
2016-08-16 10:23:42 -04:00
if ( FILE * PF = : : popen ( CppInclQuery . c_str ( ) , " r " ) ) {
2016-06-09 04:32:38 -04:00
Buf . resize ( Buf . capacity_in_bytes ( ) ) ;
2016-08-16 10:23:42 -04:00
while ( fgets ( & Buf [ 0 ] , Buf . capacity_in_bytes ( ) , PF ) & & Buf [ 0 ] ) {
llvm : : StringRef Path ( & Buf [ 0 ] ) ;
// Skip leading and trailing whitespace
Path = Path . trim ( ) ;
if ( ! Path . empty ( ) ) {
2016-08-16 18:05:45 -04:00
if ( ! llvm : : sys : : fs : : is_directory ( Path ) ) {
if ( Verbose )
cling : : utils : : LogNonExistantDirectory ( Path ) ;
}
else
2017-12-06 04:11:26 +01:00
Args . addArgument ( " -cxx-isystem " , Path . str ( ) ) ;
2016-06-09 04:32:38 -04:00
}
}
2016-08-16 10:23:42 -04:00
: : pclose ( PF ) ;
2016-08-16 18:05:45 -04:00
} else {
2016-07-01 22:50:33 -04:00
: : perror ( " popen failure " ) ;
2016-08-16 18:05:45 -04:00
// Don't be overly verbose, we already printed the command
if ( ! Verbose )
2016-09-10 15:04:39 -04:00
cling : : errs ( ) < < " for ' " < < CppInclQuery < < " ' \n " ;
2016-08-16 18:05:45 -04:00
}
2016-06-09 04:32:38 -04:00
// Return the query in Buf on failure
2016-07-05 15:10:04 -04:00
if ( Args . empty ( ) ) {
2016-06-09 04:32:38 -04:00
Buf . resize ( 0 ) ;
Buf . insert ( Buf . begin ( ) , CppInclQuery . begin ( ) , CppInclQuery . end ( ) ) ;
2016-08-16 18:05:45 -04:00
} else if ( Verbose ) {
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Found: \n " ;
2016-08-16 18:05:45 -04:00
for ( const auto & Arg : Args )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " " < < Arg . second < < " \n " ;
2016-06-09 04:32:38 -04:00
}
}
2016-08-16 18:05:45 -04:00
static bool AddCxxPaths ( llvm : : StringRef PathStr , AdditionalArgList & Args ,
bool Verbose ) {
if ( Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Looking for C++ headers in \" " < < PathStr < < " \" \n " ;
2016-08-16 18:05:45 -04:00
2016-08-18 13:21:40 -04:00
llvm : : SmallVector < llvm : : StringRef , 6 > Paths ;
if ( ! utils : : SplitPaths ( PathStr , Paths , utils : : kFailNonExistant ,
2016-09-19 14:23:17 -04:00
platform : : kEnvDelim , Verbose ) )
2016-08-18 13:21:40 -04:00
return false ;
2016-08-16 18:05:45 -04:00
2016-08-18 13:21:40 -04:00
if ( Verbose ) {
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Found: \n " ;
2016-08-11 06:12:20 -04:00
for ( llvm : : StringRef Path : Paths )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " " < < Path < < " \n " ;
2016-08-11 06:12:20 -04:00
}
2016-08-18 13:21:40 -04:00
for ( llvm : : StringRef Path : Paths )
2017-12-06 04:11:26 +01:00
Args . addArgument ( " -cxx-isystem " , Path . str ( ) ) ;
2016-08-18 13:21:40 -04:00
return true ;
}
2016-06-09 04:32:38 -04:00
# endif
2017-08-30 17:23:20 +02:00
static std : : string getResourceDir ( const char * llvmdir ) {
if ( ! llvmdir ) {
// FIXME: The first arg really does need to be argv[0] on FreeBSD.
//
// Note: The second arg is not used for Apple, FreeBSD, Linux,
// or cygwin, and can only be used on systems which support
// the use of dladdr().
//
// Note: On linux and cygwin this uses /proc/self/exe to find the path
// Note: On Apple it uses _NSGetExecutablePath().
// Note: On FreeBSD it uses getprogpath().
// Note: Otherwise it uses dladdr().
//
return CompilerInvocation : : GetResourcesPath (
" cling " , ( void * ) intptr_t ( GetExecutablePath ) ) ;
} else {
std : : string resourcePath ;
llvm : : SmallString < 512 > tmp ( llvmdir ) ;
llvm : : sys : : path : : append ( tmp , " lib " , " clang " , CLANG_VERSION_STRING ) ;
resourcePath . assign ( & tmp [ 0 ] , tmp . size ( ) ) ;
return resourcePath ;
}
}
2013-12-18 16:19:30 +01:00
///\brief Adds standard library -I used by whatever compiler is found in PATH.
2016-08-16 05:46:10 -04:00
static void AddHostArguments ( llvm : : StringRef clingBin ,
std : : vector < const char * > & args ,
2016-08-08 16:29:06 -04:00
const char * llvmdir , const CompilerOptions & opts ) {
2020-09-30 15:46:22 +00:00
( void ) clingBin ;
2016-07-05 15:10:04 -04:00
static AdditionalArgList sArguments ;
if ( sArguments . empty ( ) ) {
2016-08-16 18:05:45 -04:00
const bool Verbose = opts . Verbose ;
2014-04-15 10:44:27 +02:00
# ifdef _MSC_VER
// When built with access to the proper Windows APIs, try to actually find
2016-09-20 17:54:01 -04:00
// the correct include paths first. Init for UnivSDK.empty check below.
std : : string VSDir , WinSDK ,
UnivSDK ( opts . NoBuiltinInc ? " " : CLING_UCRT_VERSION ) ;
2016-09-14 15:49:22 -04:00
if ( platform : : GetVisualStudioDirs ( VSDir ,
opts . NoBuiltinInc ? nullptr : & WinSDK ,
opts . NoBuiltinInc ? nullptr : & UnivSDK ,
Verbose ) ) {
2016-08-08 16:29:06 -04:00
if ( ! opts . NoCXXInc ) {
2017-10-05 16:36:07 +02:00
// The Visual Studio 2017 path is very different than the previous
// versions (see also GetVisualStudioDirs() in PlatformWin.cpp)
2017-10-05 16:12:50 +02:00
const std : : string VSIncl = VSDir + " \\ include " ;
2016-09-07 04:04:29 -04:00
if ( Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Adding VisualStudio SDK: ' " < < VSIncl < < " ' \n " ;
2016-09-07 04:04:29 -04:00
sArguments . addArgument ( " -I " , std : : move ( VSIncl ) ) ;
2014-04-24 10:33:09 +02:00
}
2016-08-08 16:29:06 -04:00
if ( ! opts . NoBuiltinInc ) {
2016-09-14 15:49:22 -04:00
if ( ! WinSDK . empty ( ) ) {
WinSDK . append ( " \\ include " ) ;
2016-09-07 04:04:29 -04:00
if ( Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Adding Windows SDK: ' " < < WinSDK < < " ' \n " ;
2016-09-14 15:49:22 -04:00
sArguments . addArgument ( " -I " , std : : move ( WinSDK ) ) ;
} else {
2017-10-05 16:12:50 +02:00
// Since Visual Studio 2017, this is not valid anymore...
2016-09-07 04:04:29 -04:00
VSDir . append ( " \\ VC \\ PlatformSDK \\ Include " ) ;
if ( Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Adding Platform SDK: ' " < < VSDir < < " ' \n " ;
2016-09-07 04:04:29 -04:00
sArguments . addArgument ( " -I " , std : : move ( VSDir ) ) ;
2016-06-21 13:51:48 -04:00
}
2014-04-24 10:33:09 +02:00
}
2014-04-15 10:44:27 +02:00
}
2016-09-07 03:30:39 -04:00
# if LLVM_MSC_PREREQ(1900)
2016-09-14 15:49:22 -04:00
if ( ! UnivSDK . empty ( ) ) {
if ( Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Adding UniversalCRT SDK: ' " < < UnivSDK < < " ' \n " ;
2016-09-14 15:49:22 -04:00
sArguments . addArgument ( " -I " , std : : move ( UnivSDK ) ) ;
2016-09-07 04:04:29 -04:00
}
2016-09-07 03:30:39 -04:00
# endif
2016-07-05 15:10:04 -04:00
2016-11-30 12:24:59 -05:00
// Windows headers use '__declspec(dllexport) __cdecl' for most funcs
// causing a lot of warnings for different redeclarations (eg. coming from
// the test suite).
// Do not warn about such cases.
sArguments . addArgument ( " -Wno-dll-attribute-on-redeclaration " ) ;
sArguments . addArgument ( " -Wno-inconsistent-dllimport " ) ;
2017-02-14 20:41:58 -05:00
// Assume Windows.h might be included, and don't spew a ton of warnings
sArguments . addArgument ( " -Wno-ignored-attributes " ) ;
sArguments . addArgument ( " -Wno-nonportable-include-path " ) ;
sArguments . addArgument ( " -Wno-microsoft-enum-value " ) ;
sArguments . addArgument ( " -Wno-expansion-to-defined " ) ;
2017-10-17 13:13:14 +02:00
// silent many warnings (mostly during ROOT compilation)
sArguments . addArgument ( " -Wno-constant-conversion " ) ;
sArguments . addArgument ( " -Wno-unknown-escape-sequence " ) ;
sArguments . addArgument ( " -Wno-microsoft-unqualified-friend " ) ;
sArguments . addArgument ( " -Wno-deprecated-declarations " ) ;
2018-02-08 21:46:13 +01:00
//sArguments.addArgument("-fno-threadsafe-statics");
2018-02-08 11:00:08 +01:00
2016-11-30 12:24:59 -05:00
//sArguments.addArgument("-Wno-dllimport-static-field-def");
//sArguments.addArgument("-Wno-microsoft-template");
2014-04-15 10:44:27 +02:00
# else // _MSC_VER
2016-06-21 13:51:48 -04:00
2015-12-04 18:29:09 +01:00
// Skip LLVM_CXX execution if -nostdinc++ was provided.
2016-08-08 16:29:06 -04:00
if ( ! opts . NoCXXInc ) {
2016-07-05 15:10:04 -04:00
// Need sArguments.empty as a check condition later
assert ( sArguments . empty ( ) & & " Arguments not empty " ) ;
2016-06-21 13:51:48 -04:00
SmallString < 2048 > buffer ;
# ifdef _LIBCPP_VERSION
// Try to use a version of clang that is located next to cling
// in case cling was built with a new/custom libc++
2021-09-11 18:12:30 +00:00
std : : string clang = llvm : : sys : : path : : parent_path ( clingBin ) . str ( ) ;
2016-06-21 13:51:48 -04:00
buffer . assign ( clang ) ;
llvm : : sys : : path : : append ( buffer , " clang " ) ;
clang . assign ( & buffer [ 0 ] , buffer . size ( ) ) ;
2016-07-05 16:19:41 -04:00
2016-08-10 16:04:59 -04:00
if ( llvm : : sys : : fs : : is_regular_file ( clang ) ) {
2016-08-08 16:29:06 -04:00
if ( ! opts . StdLib ) {
2016-08-10 16:04:59 -04:00
# if defined(_LIBCPP_VERSION)
clang . append ( " -stdlib=libc++ " ) ;
# elif defined(__GLIBCXX__)
clang . append ( " -stdlib=libstdc++ " ) ;
2016-06-21 13:51:48 -04:00
# endif
2016-08-10 16:04:59 -04:00
}
2016-08-16 18:05:45 -04:00
ReadCompilerIncludePaths ( clang . c_str ( ) , buffer , sArguments , Verbose ) ;
2016-08-10 16:04:59 -04:00
}
# endif // _LIBCPP_VERSION
2015-12-04 18:29:09 +01:00
2017-09-21 10:58:56 +02:00
// First try the relative path 'g++'
# ifdef CLING_CXX_RLTV
if ( sArguments . empty ( ) )
ReadCompilerIncludePaths ( CLING_CXX_RLTV , buffer , sArguments , Verbose ) ;
# endif
// Then try the include directory cling was built with
2016-08-11 06:12:20 -04:00
# ifdef CLING_CXX_INCL
if ( sArguments . empty ( ) )
2016-08-16 18:05:45 -04:00
AddCxxPaths ( CLING_CXX_INCL , sArguments , Verbose ) ;
2016-08-11 06:12:20 -04:00
# endif
2017-09-21 10:58:56 +02:00
// Finally try the absolute path i.e.: '/usr/bin/g++'
2016-08-11 06:12:20 -04:00
# ifdef CLING_CXX_PATH
2016-07-05 15:10:04 -04:00
if ( sArguments . empty ( ) )
2016-08-16 18:05:45 -04:00
ReadCompilerIncludePaths ( CLING_CXX_PATH , buffer , sArguments , Verbose ) ;
2016-08-11 06:12:20 -04:00
# endif
2016-06-21 13:51:48 -04:00
2016-07-05 15:10:04 -04:00
if ( sArguments . empty ( ) ) {
2016-06-21 13:51:48 -04:00
// buffer is a copy of the query string that failed
2016-09-10 15:04:39 -04:00
cling : : errs ( ) < < " ERROR in cling::CIFactory::createCI(): cannot extract "
2016-08-16 18:05:45 -04:00
" standard library include paths! \n " ;
# if defined(CLING_CXX_PATH) || defined(CLING_CXX_RLTV)
// Only when ReadCompilerIncludePaths called do we have the command
// Verbose has already printed the command
if ( ! Verbose )
2016-09-10 15:04:39 -04:00
cling : : errs ( ) < < " Invoking: \n " < < buffer . c_str ( ) < < " \n " ;
2016-08-16 18:05:45 -04:00
2016-09-10 15:04:39 -04:00
cling : : errs ( ) < < " Results was: \n " ;
2016-08-16 18:05:45 -04:00
const int ExitCode = system ( buffer . c_str ( ) ) ;
2016-09-10 15:04:39 -04:00
cling : : errs ( ) < < " With exit code " < < ExitCode < < " \n " ;
2016-08-16 18:05:45 -04:00
# elif !defined(CLING_CXX_INCL)
// Technically a valid configuration that just wants to use libClangs
// internal header detection, but for now give a hint about why.
2016-09-10 15:04:39 -04:00
cling : : errs ( ) < < " CLING_CXX_INCL, CLING_CXX_PATH, and CLING_CXX_RLTV "
2016-08-16 18:05:45 -04:00
" are undefined, there was probably an error during "
2016-08-18 10:48:21 +02:00
" configuration. \n " ;
2016-08-16 18:05:45 -04:00
# endif
2016-06-21 13:51:48 -04:00
} else
2016-07-05 15:10:04 -04:00
sArguments . addArgument ( " -nostdinc++ " ) ;
2016-06-21 13:51:48 -04:00
}
2016-06-09 04:32:38 -04:00
2018-09-26 17:00:05 +02:00
# ifdef CLING_OSX_SYSROOT
sArguments . addArgument ( " -isysroot " , CLING_OSX_SYSROOT ) ;
# endif
2016-08-12 20:07:55 -04:00
2014-04-15 10:44:27 +02:00
# endif // _MSC_VER
2016-07-05 15:32:13 -04:00
2016-08-08 16:29:06 -04:00
if ( ! opts . ResourceDir & & ! opts . NoBuiltinInc ) {
2017-08-30 17:23:20 +02:00
std : : string resourcePath = getResourceDir ( llvmdir ) ;
2016-07-05 15:32:13 -04:00
// FIXME: Handle cases, where the cling is part of a library/framework.
// There we can't rely on the find executable logic.
if ( ! llvm : : sys : : fs : : is_directory ( resourcePath ) ) {
2016-09-10 15:04:39 -04:00
cling : : errs ( )
2016-07-05 15:32:13 -04:00
< < " ERROR in cling::CIFactory::createCI(): \n resource directory "
< < resourcePath < < " not found! \n " ;
resourcePath = " " ;
} else {
sArguments . addArgument ( " -resource-dir " , std : : move ( resourcePath ) ) ;
}
}
2013-12-18 16:19:30 +01:00
}
2016-07-05 15:10:04 -04:00
for ( auto & arg : sArguments ) {
args . push_back ( arg . first ) ;
args . push_back ( arg . second . c_str ( ) ) ;
}
2013-12-18 16:19:30 +01:00
}
2014-10-14 08:58:40 +02:00
2017-06-26 23:55:40 -04:00
static void SetClingCustomLangOpts ( LangOptions & Opts ,
const CompilerOptions & CompilerOpts ) {
2016-07-05 16:19:41 -04:00
Opts . EmitAllDecls = 0 ; // Otherwise if PCH attached will codegen all decls.
# ifdef _MSC_VER
2016-11-29 16:08:23 +01:00
# ifdef _DEBUG
2016-11-30 17:37:09 -05:00
// FIXME: This requires bufferoverflowu.lib, but adding:
// #pragma comment(lib, "bufferoverflowu.lib") still gives errors!
// Opts.setStackProtector(clang::LangOptions::SSPStrong);
2017-03-03 06:47:34 -05:00
# endif // _DEBUG
# ifdef _CPPRTTI
Opts . RTTIData = 1 ;
2016-07-05 16:19:41 -04:00
# else
2017-03-03 06:47:34 -05:00
Opts . RTTIData = 0 ;
# endif // _CPPRTTI
Opts . Trigraphs = 0 ;
Opts . setDefaultCallingConv ( clang : : LangOptions : : DCC_CDecl ) ;
# else // !_MSC_VER
2016-11-29 16:08:23 +01:00
Opts . Trigraphs = 1 ;
// Opts.RTTIData = 1;
// Opts.DefaultCallingConventions = 1;
// Opts.StackProtector = 0;
2016-07-05 16:19:41 -04:00
# endif // _MSC_VER
2017-03-03 06:47:34 -05:00
2017-03-03 06:55:01 -05:00
Opts . Exceptions = 1 ;
if ( Opts . CPlusPlus ) {
Opts . CXXExceptions = 1 ;
}
2016-07-05 16:19:41 -04:00
//Opts.Modules = 1;
// See test/CodeUnloading/PCH/VTables.cpp which implicitly compares clang
// to cling lang options. They should be the same, we should not have to
// give extra lang options to their invocations on any platform.
// Except -fexceptions -fcxx-exceptions.
Opts . Deprecated = 1 ;
# ifdef __APPLE__
Opts . Blocks = 1 ;
Opts . MathErrno = 0 ;
# endif
# ifdef _REENTRANT
Opts . POSIXThreads = 1 ;
2017-05-18 08:46:22 +02:00
# endif
# ifdef __FAST_MATH__
Opts . FastMath = 1 ;
2016-07-05 16:19:41 -04:00
# endif
2017-06-26 23:55:40 -04:00
2017-07-05 11:59:24 -04:00
if ( CompilerOpts . DefaultLanguage ( & Opts ) ) {
2017-07-04 12:58:05 -04:00
# ifdef __STRICT_ANSI__
2017-06-26 23:55:40 -04:00
Opts . GNUMode = 0 ;
# else
Opts . GNUMode = 1 ;
# endif
Opts . GNUKeywords = 0 ;
}
2016-07-05 16:19:41 -04:00
}
static void SetClingTargetLangOpts ( LangOptions & Opts ,
2017-06-26 23:55:40 -04:00
const TargetInfo & Target ,
const CompilerOptions & CompilerOpts ) {
2016-07-05 16:19:41 -04:00
if ( Target . getTriple ( ) . getOS ( ) = = llvm : : Triple : : Win32 ) {
Opts . MicrosoftExt = 1 ;
# ifdef _MSC_VER
Opts . MSCompatibilityVersion = ( _MSC_VER * 100000 ) ;
2019-10-11 08:44:35 +02:00
Opts . MSVCCompat = 1 ;
Opts . ThreadsafeStatics = 0 ; // FIXME: this is removing the thread guard around static init!
2016-07-05 16:19:41 -04:00
# endif
// Should fix http://llvm.org/bugs/show_bug.cgi?id=10528
Opts . DelayedTemplateParsing = 1 ;
} else {
Opts . MicrosoftExt = 0 ;
}
2017-06-26 23:55:40 -04:00
2017-07-05 11:59:24 -04:00
if ( CompilerOpts . DefaultLanguage ( & Opts ) ) {
2017-06-26 20:52:46 +02:00
# if _GLIBCXX_USE_FLOAT128
2017-06-26 23:55:40 -04:00
// We are compiling with libstdc++ with __float128 enabled.
if ( ! Target . hasFloat128Type ( ) ) {
// clang currently supports native __float128 only on few targets, and
2017-06-28 17:13:23 +02:00
// this target does not have it. The most visible consequence of this is
// a specialization
2017-06-26 23:55:40 -04:00
// __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
2017-06-28 17:13:23 +02:00
// unconditionally set in c++config.h) and #if !__STRICT_ANSI__. Tweak
2019-02-12 10:30:28 +01:00
// the latter by disabling GNUMode.
// the nvptx backend doesn't support 128 bit float
// a error message is not necessary
if ( ! CompilerOpts . CUDADevice ) {
cling : : errs ( )
< < " Disabling gnu++: "
" clang has no __float128 support on this target! \n " ;
}
2017-06-26 23:55:40 -04:00
Opts . GNUMode = 0 ;
}
# endif //_GLIBCXX_USE_FLOAT128
2017-06-26 22:11:01 +02:00
}
2020-10-14 15:06:06 +02:00
// Set char signedness to match how this file is built, i.e. flags like
// -f(no-)(un)signed-char.
Opts . CharIsSigned = std : : numeric_limits < char > : : is_signed ;
2016-07-05 16:19:41 -04:00
}
// This must be a copy of clang::getClangToolFullVersion(). Luckily
// we'll notice quickly if it ever changes! :-)
static std : : string CopyOfClanggetClangToolFullVersion ( StringRef ToolName ) {
2016-12-14 15:32:18 -05:00
cling : : stdstrstream OS ;
2016-07-05 16:19:41 -04:00
# ifdef CLANG_VENDOR
OS < < CLANG_VENDOR ;
# endif
OS < < ToolName < < " version " CLANG_VERSION_STRING " "
< < getClangFullRepositoryVersion ( ) ;
// If vendor supplied, include the base LLVM version as well.
# ifdef CLANG_VENDOR
OS < < " (based on LLVM " < < PACKAGE_VERSION < < " ) " ;
# endif
return OS . str ( ) ;
}
///\brief Check the compile-time clang version vs the run-time clang version,
/// a mismatch could cause havoc. Reports if clang versions differ.
static void CheckClangCompatibility ( ) {
if ( clang : : getClangToolFullVersion ( " cling " )
! = CopyOfClanggetClangToolFullVersion ( " cling " ) )
2016-09-10 15:04:39 -04:00
cling : : errs ( )
2016-07-05 16:19:41 -04:00
< < " Warning in cling::CIFactory::createCI(): \n "
" Using incompatible clang library! "
" Please use the one provided by cling! \n " ;
return ;
}
2014-10-14 08:58:40 +02:00
/// \brief Retrieves the clang CC1 specific flags out of the compilation's
/// jobs. Returns NULL on error.
2016-07-01 22:50:33 -04:00
static const llvm : : opt : : ArgStringList *
GetCC1Arguments ( clang : : driver : : Compilation * Compilation ,
clang : : DiagnosticsEngine * = nullptr ) {
2014-10-14 08:58:40 +02:00
// We expect to get back exactly one Command job, if we didn't something
// failed. Extract that job from the Compilation.
const clang : : driver : : JobList & Jobs = Compilation - > getJobs ( ) ;
if ( ! Jobs . size ( ) | | ! isa < clang : : driver : : Command > ( * Jobs . begin ( ) ) ) {
2016-07-01 22:50:33 -04:00
// diagnose this better...
cling : : errs ( ) < < " No Command jobs were built. \n " ;
return nullptr ;
2014-10-14 08:58:40 +02:00
}
// The one job we find should be to invoke clang again.
const clang : : driver : : Command * Cmd
2015-01-15 15:13:14 +01:00
= cast < clang : : driver : : Command > ( & ( * Jobs . begin ( ) ) ) ;
2014-10-14 08:58:40 +02:00
if ( llvm : : StringRef ( Cmd - > getCreator ( ) . getName ( ) ) ! = " clang " ) {
2016-07-01 22:50:33 -04:00
// diagnose this better...
cling : : errs ( ) < < " Clang wasn't the first job. \n " ;
return nullptr ;
2014-10-14 08:58:40 +02:00
}
return & Cmd - > getArguments ( ) ;
}
2017-09-01 09:26:27 +02:00
/// \brief Splits the given environment variable by the path separator.
/// Can be used to extract the paths from LD_LIBRARY_PATH.
static SmallVector < StringRef , 4 > getPathsFromEnv ( const char * EnvVar ) {
if ( ! EnvVar ) return { } ;
SmallVector < StringRef , 4 > Paths ;
2020-07-16 13:50:05 +05:30
StringRef ( EnvVar ) . split ( Paths , llvm : : sys : : EnvPathSeparator , - 1 , false ) ;
2017-09-01 09:26:27 +02:00
return Paths ;
}
/// \brief Adds all the paths to the prebuilt module paths of the given
/// HeaderSearchOptions.
static void addPrebuiltModulePaths ( clang : : HeaderSearchOptions & Opts ,
const SmallVectorImpl < StringRef > & Paths ) {
2019-06-30 20:30:06 +03:00
for ( StringRef ModulePath : Paths )
Opts . AddPrebuiltModulePath ( ModulePath ) ;
2017-09-01 09:26:27 +02:00
}
2019-11-29 11:47:45 +02:00
static std : : string getIncludePathForHeader ( const clang : : HeaderSearch & HS ,
2019-10-21 15:41:12 +02:00
llvm : : StringRef header ) {
2019-11-29 11:47:45 +02:00
for ( auto Dir = HS . search_dir_begin ( ) , E = HS . search_dir_end ( ) ;
Dir ! = E ; + + Dir ) {
llvm : : SmallString < 512 > headerPath ( Dir - > getName ( ) ) ;
2019-10-21 15:41:12 +02:00
llvm : : sys : : path : : append ( headerPath , header ) ;
if ( llvm : : sys : : fs : : exists ( headerPath . str ( ) ) )
2019-11-29 11:47:45 +02:00
return Dir - > getName ( ) . str ( ) ;
2019-10-21 10:52:24 +02:00
}
2019-10-21 15:41:12 +02:00
return { } ;
2019-10-21 10:52:24 +02:00
}
2019-10-21 15:41:12 +02:00
static void collectModuleMaps ( clang : : CompilerInstance & CI ,
2019-10-21 10:52:24 +02:00
llvm : : SmallVectorImpl < std : : string > & ModuleMapFiles ) {
2019-11-29 11:47:45 +02:00
assert ( CI . getLangOpts ( ) . Modules & & " Using overlay without -fmodules " ) ;
2019-10-21 10:52:24 +02:00
2019-11-29 11:47:45 +02:00
const clang : : HeaderSearch & HS = CI . getPreprocessor ( ) . getHeaderSearchInfo ( ) ;
2019-10-21 15:41:12 +02:00
clang : : HeaderSearchOptions & HSOpts = CI . getHeaderSearchOpts ( ) ;
2019-11-29 11:47:45 +02:00
// We can't use "assert.h" because it is defined in the resource dir, too.
2020-10-05 06:22:33 +00:00
# ifdef _WIN32
2020-05-11 10:19:22 +05:30
llvm : : SmallString < 256 > vcIncLoc ( getIncludePathForHeader ( HS , " vcruntime.h " ) ) ;
2020-05-23 07:39:26 +00:00
llvm : : SmallString < 256 > servIncLoc ( getIncludePathForHeader ( HS , " windows.h " ) ) ;
2020-05-11 10:19:22 +05:30
# endif
2019-11-29 11:47:45 +02:00
llvm : : SmallString < 128 > cIncLoc ( getIncludePathForHeader ( HS , " time.h " ) ) ;
2021-10-01 07:15:36 +00:00
// FIXME: Diagnose this until we teach cling how to work without libc.
if ( ! llvm : : sys : : fs : : exists ( cIncLoc ) )
llvm : : errs ( )
< < " C system headers (glibc/Xcode/Windows SDK) must be installed. \n " ;
2019-10-21 15:41:12 +02:00
2019-11-29 11:47:45 +02:00
llvm : : SmallString < 256 > stdIncLoc ( getIncludePathForHeader ( HS , " cassert " ) ) ;
2020-02-13 18:00:36 +01:00
llvm : : SmallString < 256 > boostIncLoc ( getIncludePathForHeader ( HS , " boost/version.hpp " ) ) ;
llvm : : SmallString < 256 > tinyxml2IncLoc ( getIncludePathForHeader ( HS , " tinyxml2.h " ) ) ;
2019-11-29 11:47:45 +02:00
llvm : : SmallString < 256 > cudaIncLoc ( getIncludePathForHeader ( HS , " cuda.h " ) ) ;
2020-12-19 22:16:25 +00:00
llvm : : SmallString < 256 > vcVcIncLoc ( getIncludePathForHeader ( HS , " Vc/Vc " ) ) ;
2019-11-29 11:47:45 +02:00
llvm : : SmallString < 256 > clingIncLoc ( getIncludePathForHeader ( HS ,
2019-10-21 15:41:12 +02:00
" cling/Interpreter/RuntimeUniverse.h " ) ) ;
// Re-add cling as the modulemap are in cling/*modulemap
llvm : : sys : : path : : append ( clingIncLoc , " cling " ) ;
// Construct a column of modulemap overlay file if needed.
2020-03-29 14:09:13 +03:00
auto maybeAppendOverlayEntry
= [ & HSOpts , & ModuleMapFiles ] ( llvm : : StringRef SystemDir ,
const std : : string & Filename ,
const std : : string & Location ,
2020-06-04 19:47:23 +00:00
std : : string & overlay ,
2020-08-18 17:18:43 +02:00
bool RegisterModuleMap ,
bool AllowModulemapOverride )
2020-07-30 15:34:56 +00:00
- > void {
2019-10-28 22:54:50 +01:00
assert ( llvm : : sys : : fs : : exists ( SystemDir ) & & " Must exist! " ) ;
2019-10-21 15:41:12 +02:00
2020-04-12 16:19:39 +03:00
std : : string modulemapFilename = " module.modulemap " ;
2019-10-21 15:41:12 +02:00
llvm : : SmallString < 512 > systemLoc ( SystemDir ) ;
2020-03-19 09:12:45 +02:00
llvm : : sys : : path : : append ( systemLoc , modulemapFilename ) ;
2019-10-21 15:41:12 +02:00
// Check if we need to mount a custom modulemap. We may have it, for
// instance when we are on osx or using libc++.
2020-07-30 15:34:56 +00:00
if ( AllowModulemapOverride & & llvm : : sys : : fs : : exists ( systemLoc . str ( ) ) ) {
2019-10-21 15:41:12 +02:00
if ( HSOpts . Verbose )
2020-04-12 16:19:39 +03:00
cling : : log ( ) < < " Loading ' " < < systemLoc . str ( ) < < " ' \n " ;
// If the library had its own modulemap file, use it. This should handle
// the case where we use libc++ on Unix.
if ( ! HSOpts . ImplicitModuleMaps )
ModuleMapFiles . push_back ( systemLoc . str ( ) . str ( ) ) ;
2019-10-21 15:41:12 +02:00
return ;
}
2019-10-21 10:52:24 +02:00
2020-04-12 16:19:39 +03:00
llvm : : SmallString < 512 > originalLoc ( Location ) ;
assert ( llvm : : sys : : fs : : exists ( originalLoc . str ( ) ) & & " Must exist! " ) ;
llvm : : sys : : path : : append ( originalLoc , Filename ) ;
assert ( llvm : : sys : : fs : : exists ( originalLoc . str ( ) ) ) ;
if ( HSOpts . Verbose )
cling : : log ( ) < < " ' " < < systemLoc < < " ' does not exist. Mounting ' "
< < originalLoc . str ( ) < < " ' as ' " < < systemLoc < < " ' \n " ;
if ( ! HSOpts . ImplicitModuleMaps ) {
modulemapFilename = Filename ;
llvm : : sys : : path : : remove_filename ( systemLoc ) ;
llvm : : sys : : path : : append ( systemLoc , modulemapFilename ) ;
}
2019-10-21 15:41:12 +02:00
if ( ! overlay . empty ( ) )
overlay + = " , \n " ;
2019-10-21 10:52:24 +02:00
2019-10-21 15:41:12 +02:00
overlay + = " { 'name': ' " + SystemDir . str ( ) + " ', 'type': 'directory', \n " ;
2020-03-19 09:12:45 +02:00
overlay + = " 'contents': [ \n { 'name': ' " + modulemapFilename + " ', " ;
2019-10-21 15:41:12 +02:00
overlay + = " 'type': 'file', \n 'external-contents': ' " ;
overlay + = originalLoc . str ( ) . str ( ) + " ' \n " ;
overlay + = " } \n ] \n } " ;
2020-03-29 14:09:13 +03:00
if ( HSOpts . ImplicitModuleMaps )
2020-06-04 19:47:23 +00:00
return ;
if ( RegisterModuleMap )
ModuleMapFiles . push_back ( systemLoc . str ( ) . str ( ) ) ;
2019-10-21 15:41:12 +02:00
} ;
2019-10-21 10:52:24 +02:00
2020-03-29 14:09:13 +03:00
if ( ! HSOpts . ImplicitModuleMaps ) {
// Register the modulemap files.
llvm : : SmallString < 512 > resourceDirLoc ( HSOpts . ResourceDir ) ;
llvm : : sys : : path : : append ( resourceDirLoc , " include " , " module.modulemap " ) ;
ModuleMapFiles . push_back ( resourceDirLoc . str ( ) . str ( ) ) ;
llvm : : SmallString < 512 > clingModuleMap ( clingIncLoc ) ;
llvm : : sys : : path : : append ( clingModuleMap , " module.modulemap " ) ;
ModuleMapFiles . push_back ( clingModuleMap . str ( ) . str ( ) ) ;
2020-04-06 12:50:38 +03:00
# ifdef __APPLE__
llvm : : SmallString < 512 > libcModuleMap ( cIncLoc ) ;
llvm : : sys : : path : : append ( libcModuleMap , " module.modulemap " ) ;
ModuleMapFiles . push_back ( libcModuleMap . str ( ) . str ( ) ) ;
llvm : : SmallString < 512 > stdModuleMap ( stdIncLoc ) ;
llvm : : sys : : path : : append ( stdModuleMap , " module.modulemap " ) ;
ModuleMapFiles . push_back ( stdModuleMap . str ( ) . str ( ) ) ;
# endif // __APPLE__
2020-03-29 14:09:13 +03:00
}
2019-10-21 15:41:12 +02:00
std : : string MOverlay ;
2020-10-05 06:22:33 +00:00
# ifdef _WIN32
2020-05-11 10:19:22 +05:30
maybeAppendOverlayEntry ( vcIncLoc . str ( ) , " vcruntime.modulemap " ,
2021-09-11 18:12:30 +00:00
clingIncLoc . str ( ) . str ( ) , MOverlay ,
2020-08-18 17:18:43 +02:00
/*RegisterModuleMap=*/ true ,
/*AllowModulemapOverride=*/ false ) ;
2020-05-23 07:39:26 +00:00
maybeAppendOverlayEntry ( servIncLoc . str ( ) , " services_msvc.modulemap " ,
2021-09-11 18:12:30 +00:00
clingIncLoc . str ( ) . str ( ) , MOverlay ,
2020-08-18 17:18:43 +02:00
/*RegisterModuleMap=*/ true ,
/*AllowModulemapOverride=*/ false ) ;
2020-04-04 15:40:48 +03:00
maybeAppendOverlayEntry ( cIncLoc . str ( ) , " libc_msvc.modulemap " ,
2021-09-11 18:12:30 +00:00
clingIncLoc . str ( ) . str ( ) , MOverlay ,
2020-08-18 17:18:43 +02:00
/*RegisterModuleMap=*/ true ,
/*AllowModulemapOverride=*/ false ) ;
2020-04-04 15:40:48 +03:00
maybeAppendOverlayEntry ( stdIncLoc . str ( ) , " std_msvc.modulemap " ,
2021-09-11 18:12:30 +00:00
clingIncLoc . str ( ) . str ( ) , MOverlay ,
2020-08-18 17:18:43 +02:00
/*RegisterModuleMap=*/ true ,
/*AllowModulemapOverride=*/ false ) ;
2020-04-04 15:40:48 +03:00
# else
2021-09-11 18:12:30 +00:00
maybeAppendOverlayEntry ( cIncLoc . str ( ) , " libc.modulemap " ,
clingIncLoc . str ( ) . str ( ) , MOverlay ,
/*RegisterModuleMap=*/ true ,
2020-07-30 15:34:56 +00:00
/*AllowModulemapOverride=*/ true ) ;
2021-09-11 18:12:30 +00:00
maybeAppendOverlayEntry ( stdIncLoc . str ( ) , " std.modulemap " ,
clingIncLoc . str ( ) . str ( ) , MOverlay ,
/*RegisterModuleMap=*/ true ,
2020-07-30 15:34:56 +00:00
/*AllowModulemapOverride=*/ true ) ;
2020-10-05 06:22:33 +00:00
# endif // _WIN32
2020-04-04 15:40:48 +03:00
2020-02-13 18:00:36 +01:00
if ( ! tinyxml2IncLoc . empty ( ) )
maybeAppendOverlayEntry ( tinyxml2IncLoc . str ( ) , " tinyxml2.modulemap " ,
2021-09-11 18:12:30 +00:00
clingIncLoc . str ( ) . str ( ) , MOverlay ,
2020-08-18 17:18:43 +02:00
/*RegisterModuleMap=*/ false ,
/*AllowModulemapOverride=*/ false ) ;
2019-10-28 22:54:50 +01:00
if ( ! cudaIncLoc . empty ( ) )
maybeAppendOverlayEntry ( cudaIncLoc . str ( ) , " cuda.modulemap " ,
2021-09-11 18:12:30 +00:00
clingIncLoc . str ( ) . str ( ) , MOverlay ,
2020-08-18 17:18:43 +02:00
/*RegisterModuleMap=*/ true ,
/*AllowModulemapOverride=*/ false ) ;
2020-12-19 22:16:25 +00:00
if ( ! vcVcIncLoc . empty ( ) )
maybeAppendOverlayEntry ( vcVcIncLoc . str ( ) , " vc.modulemap " ,
2021-09-11 18:12:30 +00:00
clingIncLoc . str ( ) . str ( ) , MOverlay ,
2020-12-19 22:16:25 +00:00
/*RegisterModuleMap=*/ true ,
/*AllowModulemapOverride=*/ false ) ;
2020-05-26 17:35:53 +00:00
if ( ! boostIncLoc . empty ( ) ) {
// Add the modulemap in the include/boost folder not in include.
llvm : : sys : : path : : append ( boostIncLoc , " boost " ) ;
2020-02-13 18:00:36 +01:00
maybeAppendOverlayEntry ( boostIncLoc . str ( ) , " boost.modulemap " ,
2021-09-11 18:12:30 +00:00
clingIncLoc . str ( ) . str ( ) , MOverlay ,
2020-08-18 17:18:43 +02:00
/*RegisterModuleMap=*/ false ,
/*AllowModulemapOverride=*/ false ) ;
2020-05-26 17:35:53 +00:00
}
2019-10-21 15:41:12 +02:00
if ( /*needsOverlay*/ ! MOverlay . empty ( ) ) {
2019-10-21 10:52:24 +02:00
// Virtual modulemap overlay file
2019-10-21 15:41:12 +02:00
MOverlay . insert ( 0 , " { \n 'version': 0, \n 'roots': [ \n " ) ;
2019-10-21 10:52:24 +02:00
MOverlay + = " ] \n } \n ] \n } \n " ;
2019-10-15 18:32:21 +03:00
2019-11-01 01:03:47 +02:00
const std : : string VfsOverlayFileName = " modulemap.overlay.yaml " ;
if ( HSOpts . Verbose )
cling : : log ( ) < < VfsOverlayFileName < < " \n " < < MOverlay ;
2019-10-21 10:52:24 +02:00
// Set up the virtual modulemap overlay file
std : : unique_ptr < llvm : : MemoryBuffer > Buffer =
llvm : : MemoryBuffer : : getMemBuffer ( MOverlay ) ;
2019-10-15 18:32:21 +03:00
2020-03-11 12:40:39 +02:00
IntrusiveRefCntPtr < llvm : : vfs : : FileSystem > FS =
llvm : : vfs : : getVFSFromYAML ( std : : move ( Buffer ) , nullptr ,
VfsOverlayFileName ) ;
2019-10-21 10:52:24 +02:00
if ( ! FS . get ( ) )
llvm : : errs ( ) < < " Error in modulemap.overlay! \n " ;
2019-10-15 18:32:21 +03:00
2019-10-21 10:52:24 +02:00
// Load virtual modulemap overlay file
2019-10-21 15:41:12 +02:00
CI . getInvocation ( ) . addOverlay ( FS ) ;
2019-10-21 10:52:24 +02:00
}
2019-10-15 18:32:21 +03:00
}
2019-10-21 15:41:12 +02:00
static void setupCxxModules ( clang : : CompilerInstance & CI ) {
assert ( CI . getLangOpts ( ) . Modules ) ;
clang : : HeaderSearchOptions & HSOpts = CI . getHeaderSearchOpts ( ) ;
2019-10-15 18:32:21 +03:00
// Register prebuilt module paths where we will lookup module files.
addPrebuiltModulePaths ( HSOpts ,
getPathsFromEnv ( getenv ( " CLING_PREBUILT_MODULE_PATH " ) ) ) ;
// Register all modulemaps necessary for cling to run. If we have specified
// -fno-implicit-module-maps then we have to add them explicitly to the list
// of modulemap files to load.
llvm : : SmallVector < std : : string , 4 > ModuleMaps ;
2019-10-21 15:41:12 +02:00
collectModuleMaps ( CI , ModuleMaps ) ;
2019-10-15 18:32:21 +03:00
2019-10-21 10:52:24 +02:00
assert ( HSOpts . ImplicitModuleMaps = = ModuleMaps . empty ( ) & &
" We must have register the modulemaps by hand! " ) ;
2019-10-15 18:32:21 +03:00
// Prepend the modulemap files we attached so that they will be loaded.
2019-10-21 10:52:24 +02:00
if ( ! HSOpts . ImplicitModuleMaps ) {
2019-10-21 15:41:12 +02:00
FrontendOptions & FrontendOpts = CI . getInvocation ( ) . getFrontendOpts ( ) ;
2019-10-15 18:32:21 +03:00
FrontendOpts . ModuleMapFiles . insert ( FrontendOpts . ModuleMapFiles . begin ( ) ,
ModuleMaps . begin ( ) , ModuleMaps . end ( ) ) ;
2019-10-21 10:52:24 +02:00
}
2019-10-15 18:32:21 +03:00
}
2022-01-10 12:50:44 +01:00
# if defined(_MSC_VER)
static void stringifyPreprocSetting ( PreprocessorOptions & PPOpts ,
const std : : string & Name , int Val ) {
smallstream Strm ;
Strm < < Name < < " = " < < Val ;
if ( std : : find ( PPOpts . Macros . begin ( ) , PPOpts . Macros . end ( ) ,
std : : make_pair ( Name , true ) )
= = PPOpts . Macros . end ( )
& & std : : find ( PPOpts . Macros . begin ( ) , PPOpts . Macros . end ( ) ,
std : : make_pair ( Name , false ) )
= = PPOpts . Macros . end ( ) )
PPOpts . addMacroDef ( Strm . str ( ) ) ;
}
2016-11-29 16:08:23 +01:00
2016-12-14 15:32:18 -05:00
# define STRINGIFY_PREPROC_SETTING(PP, name) \
stringifyPreprocSetting ( PP , # name , name )
2016-12-01 10:03:22 +01:00
# endif
2016-11-29 16:08:23 +01:00
2015-05-07 14:21:14 -05:00
/// Set cling's preprocessor defines to match the cling binary.
static void SetPreprocessorFromBinary ( PreprocessorOptions & PPOpts ) {
# ifdef _MSC_VER
2017-02-07 14:46:58 +01:00
// FIXME: Stay consistent with the _HAS_EXCEPTIONS flag settings in SetClingCustomLangOpts
// STRINGIFY_PREPROC_SETTING(PPOpts, _HAS_EXCEPTIONS);
2016-07-21 11:34:43 +02:00
# ifdef _DEBUG
2016-12-14 15:32:18 -05:00
STRINGIFY_PREPROC_SETTING ( PPOpts , _DEBUG ) ;
2016-11-29 16:08:23 +01:00
# endif
2016-12-14 15:50:39 -05:00
# endif
2022-01-10 12:50:44 +01:00
// cling wants to JIT O1 by default. Might want to revisit once we have
// debug symbols.
PPOpts . addMacroDef ( " NDEBUG=1 " ) ;
2015-05-07 14:21:14 -05:00
// Since cling, uses clang instead, macros always sees __CLANG__ defined
// In addition, clang also defined __GNUC__, we add the following two macros
// to allow scripts, and more important, dictionary generation to know which
// of the two is the underlying compiler.
# ifdef __clang__
PPOpts . addMacroDef ( " __CLING__clang__= " ClingStringify ( __clang__ ) ) ;
# elif defined(__GNUC__)
PPOpts . addMacroDef ( " __CLING__GNUC__= " ClingStringify ( __GNUC__ ) ) ;
2017-03-10 04:34:57 -05:00
PPOpts . addMacroDef ( " __CLING__GNUC_MINOR__= " ClingStringify ( __GNUC_MINOR__ ) ) ;
2017-02-08 01:05:23 -05:00
# elif defined(_MSC_VER)
PPOpts . addMacroDef ( " __CLING__MSVC__= " ClingStringify ( _MSC_VER ) ) ;
2021-07-07 19:32:22 +02:00
# if (_MSC_VER >= 1926)
2020-08-20 17:10:29 +02:00
// FIXME: Silly workaround for cling not being able to parse the STL
// headers anymore after the update of Visual Studio v16.7.0
// To be checked/removed after the upgrade of LLVM & Clang
2021-07-07 19:32:22 +02:00
PPOpts . addMacroDef ( " _HAS_CONDITIONAL_EXPLICIT=0 " ) ;
2020-08-20 17:10:29 +02:00
# endif
2015-05-07 14:21:14 -05:00
# endif
2015-05-07 18:00:15 -05:00
// https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
# ifdef _GLIBCXX_USE_CXX11_ABI
PPOpts . addMacroDef ( " _GLIBCXX_USE_CXX11_ABI= "
ClingStringify ( _GLIBCXX_USE_CXX11_ABI ) ) ;
# endif
2016-09-20 19:59:19 -04:00
2020-10-05 06:22:33 +00:00
# if defined(_WIN32)
2016-09-20 19:59:19 -04:00
PPOpts . addMacroDef ( " CLING_EXPORT=__declspec(dllimport) " ) ;
2018-05-09 10:04:33 +02:00
// prevent compilation error G47C585C4: STL1000: Unexpected compiler
// version, expected Clang 6 or newer.
PPOpts . addMacroDef ( " _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH " ) ;
2016-09-20 19:59:19 -04:00
# else
PPOpts . addMacroDef ( " CLING_EXPORT= " ) ;
# endif
2015-05-07 14:21:14 -05:00
}
/// Set target-specific preprocessor defines.
static void SetPreprocessorFromTarget ( PreprocessorOptions & PPOpts ,
const llvm : : Triple & TTriple ) {
if ( TTriple . getEnvironment ( ) = = llvm : : Triple : : Cygnus ) {
// clang "forgets" the basic arch part needed by winnt.h:
if ( TTriple . getArch ( ) = = llvm : : Triple : : x86 ) {
PPOpts . addMacroDef ( " _X86_=1 " ) ;
} else if ( TTriple . getArch ( ) = = llvm : : Triple : : x86_64 ) {
PPOpts . addMacroDef ( " __x86_64=1 " ) ;
} else {
2016-09-10 15:04:39 -04:00
cling : : errs ( ) < < " Warning in cling::CIFactory::createCI(): \n "
" unhandled target architecture "
< < TTriple . getArchName ( ) < < ' \n ' ;
2015-05-07 14:21:14 -05:00
}
}
}
2016-04-28 14:18:35 +02:00
template < class CONTAINER >
static void insertBehind ( CONTAINER & To , const CONTAINER & From ) {
To . insert ( To . end ( ) , From . begin ( ) , From . end ( ) ) ;
}
2016-08-16 05:46:10 -04:00
static void AddRuntimeIncludePaths ( llvm : : StringRef ClingBin ,
clang : : HeaderSearchOptions & HOpts ) {
2016-08-16 18:05:45 -04:00
if ( HOpts . Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Adding runtime include paths: \n " ;
2016-08-16 05:46:10 -04:00
// Add configuration paths to interpreter's include files.
# ifdef CLING_INCLUDE_PATHS
2016-08-16 18:05:45 -04:00
if ( HOpts . Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " \" " CLING_INCLUDE_PATHS " \" \n " ;
2016-09-19 14:23:17 -04:00
utils : : AddIncludePaths ( CLING_INCLUDE_PATHS , HOpts ) ;
2016-08-16 05:46:10 -04:00
# endif
llvm : : SmallString < 512 > P ( ClingBin ) ;
if ( ! P . empty ( ) ) {
// Remove /cling from foo/bin/clang
llvm : : StringRef ExeIncl = llvm : : sys : : path : : parent_path ( P ) ;
// Remove /bin from foo/bin
ExeIncl = llvm : : sys : : path : : parent_path ( ExeIncl ) ;
P . resize ( ExeIncl . size ( ) ) ;
// Get foo/include
llvm : : sys : : path : : append ( P , " include " ) ;
2018-01-28 22:06:04 +01:00
if ( llvm : : sys : : fs : : is_directory ( P . str ( ) ) ) {
2016-08-08 16:29:06 -04:00
utils : : AddIncludePaths ( P . str ( ) , HOpts , nullptr ) ;
2018-01-28 22:06:04 +01:00
llvm : : sys : : path : : append ( P , " clang " ) ;
if ( ! llvm : : sys : : fs : : is_directory ( P . str ( ) ) ) {
// LLVM is not installed. Try resolving clang from its usual location.
2018-04-25 16:11:17 +02:00
llvm : : SmallString < 512 > PParent = llvm : : sys : : path : : parent_path ( P ) ;
P = PParent ;
2018-01-28 22:06:04 +01:00
llvm : : sys : : path : : append ( P , " .. " , " tools " , " clang " , " include " ) ;
if ( llvm : : sys : : fs : : is_directory ( P . str ( ) ) )
utils : : AddIncludePaths ( P . str ( ) , HOpts , nullptr ) ;
}
}
2016-08-16 05:46:10 -04:00
}
}
2016-07-01 22:50:33 -04:00
static llvm : : IntrusiveRefCntPtr < DiagnosticsEngine >
2021-02-05 10:20:48 +00:00
SetupDiagnostics ( DiagnosticOptions & DiagOpts , const std : : string & ExeName ) {
2016-07-01 22:50:33 -04:00
// The compiler invocation is the owner of the diagnostic options.
// Everything else points to them.
llvm : : IntrusiveRefCntPtr < clang : : DiagnosticIDs > DiagIDs ( new DiagnosticIDs ( ) ) ;
std : : unique_ptr < TextDiagnosticPrinter >
DiagnosticPrinter ( new TextDiagnosticPrinter ( cling : : errs ( ) , & DiagOpts ) ) ;
2019-11-13 09:43:59 +01:00
DiagnosticPrinter - > setPrefix ( ExeName ) ;
2016-07-01 22:50:33 -04:00
llvm : : IntrusiveRefCntPtr < DiagnosticsEngine >
Diags ( new DiagnosticsEngine ( DiagIDs , & DiagOpts ,
DiagnosticPrinter . get ( ) , /*Owns it*/ true ) ) ;
DiagnosticPrinter . release ( ) ;
return Diags ;
}
2017-01-29 18:16:31 -05:00
static bool
2017-06-26 23:55:40 -04:00
SetupCompiler ( CompilerInstance * CI , const CompilerOptions & CompilerOpts ,
bool Lang = true , bool Targ = true ) {
2017-07-04 13:25:21 -04:00
LangOptions & LangOpts = CI - > getLangOpts ( ) ;
2016-07-21 18:29:10 -04:00
// Set the language options, which cling needs.
// This may have already been done via a precompiled header
2017-01-29 18:16:31 -05:00
if ( Lang )
2017-07-04 13:25:21 -04:00
SetClingCustomLangOpts ( LangOpts , CompilerOpts ) ;
2016-07-21 18:29:10 -04:00
PreprocessorOptions & PPOpts = CI - > getInvocation ( ) . getPreprocessorOpts ( ) ;
SetPreprocessorFromBinary ( PPOpts ) ;
2017-07-04 12:58:05 -04:00
// Sanity check that clang delivered the language standard requested
2017-07-05 11:59:24 -04:00
if ( CompilerOpts . DefaultLanguage ( & LangOpts ) ) {
2017-07-04 12:58:05 -04:00
switch ( CxxStdCompiledWith ( ) ) {
2021-09-11 19:21:20 +00:00
case 20 : assert ( LangOpts . CPlusPlus20 & & " Language version mismatch " ) ;
2020-03-11 12:40:10 +02:00
LLVM_FALLTHROUGH ;
case 17 : assert ( LangOpts . CPlusPlus17 & & " Language version mismatch " ) ;
LLVM_FALLTHROUGH ;
2017-07-04 12:58:05 -04:00
case 14 : assert ( LangOpts . CPlusPlus14 & & " Language version mismatch " ) ;
2020-03-11 12:40:10 +02:00
LLVM_FALLTHROUGH ;
2017-07-04 12:58:05 -04:00
case 11 : assert ( LangOpts . CPlusPlus11 & & " Language version mismatch " ) ;
2017-08-22 15:51:17 -07:00
break ;
default : assert ( false & & " You have an unhandled C++ standard! " ) ;
2017-07-04 12:58:05 -04:00
}
}
2016-07-21 18:29:10 -04:00
PPOpts . addMacroDef ( " __CLING__ " ) ;
2017-07-04 13:25:21 -04:00
if ( LangOpts . CPlusPlus11 = = 1 )
2016-07-21 18:29:10 -04:00
PPOpts . addMacroDef ( " __CLING__CXX11 " ) ;
2017-07-04 13:25:21 -04:00
if ( LangOpts . CPlusPlus14 = = 1 )
2017-06-26 23:23:28 -04:00
PPOpts . addMacroDef ( " __CLING__CXX14 " ) ;
2016-07-21 18:29:10 -04:00
if ( CI - > getDiagnostics ( ) . hasErrorOccurred ( ) ) {
2017-11-02 20:09:30 +01:00
cling : : errs ( ) < < " Compiler error too early in initialization. \n " ;
2016-07-21 18:29:10 -04:00
return false ;
}
CI - > setTarget ( TargetInfo : : CreateTargetInfo ( CI - > getDiagnostics ( ) ,
CI - > getInvocation ( ) . TargetOpts ) ) ;
if ( ! CI - > hasTarget ( ) ) {
cling : : errs ( ) < < " Could not determine compiler target. \n " ;
return false ;
}
2017-07-04 13:25:21 -04:00
CI - > getTarget ( ) . adjust ( LangOpts ) ;
2016-07-21 18:29:10 -04:00
// This may have already been done via a precompiled header
2017-01-29 18:16:31 -05:00
if ( Targ )
2017-07-04 13:25:21 -04:00
SetClingTargetLangOpts ( LangOpts , CI - > getTarget ( ) , CompilerOpts ) ;
2016-07-21 18:29:10 -04:00
SetPreprocessorFromTarget ( PPOpts , CI - > getTarget ( ) . getTriple ( ) ) ;
return true ;
}
class ActionScan {
std : : set < const clang : : driver : : Action * > m_Visited ;
2016-08-08 19:02:10 -04:00
llvm : : SmallVector < clang : : driver : : Action : : ActionClass , 2 > m_Kinds ;
2016-07-21 18:29:10 -04:00
bool find ( const clang : : driver : : Action * A ) {
if ( A & & ! m_Visited . count ( A ) ) {
2016-08-08 19:02:10 -04:00
if ( std : : find ( m_Kinds . begin ( ) , m_Kinds . end ( ) , A - > getKind ( ) ) ! =
m_Kinds . end ( ) )
2016-07-21 18:29:10 -04:00
return true ;
m_Visited . insert ( A ) ;
return find ( * A - > input_begin ( ) ) ;
}
return false ;
}
public :
2016-08-08 19:02:10 -04:00
ActionScan ( clang : : driver : : Action : : ActionClass a , int b = - 1 ) {
m_Kinds . push_back ( a ) ;
if ( b ! = - 1 )
m_Kinds . push_back ( clang : : driver : : Action : : ActionClass ( b ) ) ;
}
2016-07-21 18:29:10 -04:00
bool find ( clang : : driver : : Compilation * C ) {
for ( clang : : driver : : Action * A : C - > getActions ( ) ) {
if ( find ( A ) )
return true ;
}
return false ;
}
} ;
2017-05-10 08:18:54 +02:00
2019-12-08 10:51:19 +02:00
static void HandleProgramActions ( CompilerInstance & CI ) {
const clang : : FrontendOptions & FrontendOpts = CI . getFrontendOpts ( ) ;
if ( FrontendOpts . ProgramAction = = clang : : frontend : : ModuleFileInfo ) {
// Copied from FrontendActions.cpp
// FIXME: Remove when we switch to the new driver.
class DumpModuleInfoListener : public ASTReaderListener {
llvm : : raw_ostream & Out ;
public :
2020-09-30 19:32:52 +00:00
DumpModuleInfoListener ( llvm : : raw_ostream & OS ) : Out ( OS ) { }
2019-12-08 10:51:19 +02:00
# define DUMP_BOOLEAN(Value, Text) \
Out . indent ( 4 ) < < Text < < " : " < < ( Value ? " Yes " : " No " ) < < " \n "
bool ReadFullVersionInformation ( StringRef FullVersion ) override {
Out . indent ( 2 )
< < " Generated by "
< < ( FullVersion = = getClangFullRepositoryVersion ( ) ? " this "
: " a different " )
< < " Clang: " < < FullVersion < < " \n " ;
return ASTReaderListener : : ReadFullVersionInformation ( FullVersion ) ;
}
void ReadModuleName ( StringRef ModuleName ) override {
Out . indent ( 2 ) < < " Module name: " < < ModuleName < < " \n " ;
}
void ReadModuleMapFile ( StringRef ModuleMapPath ) override {
Out . indent ( 2 ) < < " Module map file: " < < ModuleMapPath < < " \n " ;
}
2020-09-30 15:46:22 +00:00
bool ReadLanguageOptions ( const LangOptions & LangOpts , bool /*Complain*/ ,
bool /*AllowCompatibleDifferences*/ ) override {
2019-12-08 10:51:19 +02:00
Out . indent ( 2 ) < < " Language options: \n " ;
# define LANGOPT(Name, Bits, Default, Description) \
DUMP_BOOLEAN ( LangOpts . Name , Description ) ;
# define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
Out . indent ( 4 ) < < Description < < " : " \
< < static_cast < unsigned > ( LangOpts . get # # Name ( ) ) < < " \n " ;
# define VALUE_LANGOPT(Name, Bits, Default, Description) \
Out . indent ( 4 ) < < Description < < " : " < < LangOpts . Name < < " \n " ;
# define BENIGN_LANGOPT(Name, Bits, Default, Description)
# define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
# include "clang/Basic/LangOptions.def"
if ( ! LangOpts . ModuleFeatures . empty ( ) ) {
Out . indent ( 4 ) < < " Module features: \n " ;
for ( StringRef Feature : LangOpts . ModuleFeatures )
Out . indent ( 6 ) < < Feature < < " \n " ;
}
return false ;
}
2020-09-30 15:46:22 +00:00
bool ReadTargetOptions ( const TargetOptions & TargetOpts ,
bool /*Complain*/ ,
bool /*AllowCompatibleDifferences*/ ) override {
2019-12-08 10:51:19 +02:00
Out . indent ( 2 ) < < " Target options: \n " ;
Out . indent ( 4 ) < < " Triple: " < < TargetOpts . Triple < < " \n " ;
Out . indent ( 4 ) < < " CPU: " < < TargetOpts . CPU < < " \n " ;
Out . indent ( 4 ) < < " ABI: " < < TargetOpts . ABI < < " \n " ;
if ( ! TargetOpts . FeaturesAsWritten . empty ( ) ) {
Out . indent ( 4 ) < < " Target features: \n " ;
for ( unsigned I = 0 , N = TargetOpts . FeaturesAsWritten . size ( ) ;
I ! = N ; + + I ) {
Out . indent ( 6 ) < < TargetOpts . FeaturesAsWritten [ I ] < < " \n " ;
}
}
return false ;
}
bool ReadDiagnosticOptions ( IntrusiveRefCntPtr < DiagnosticOptions > DiagOpts ,
2020-09-30 15:46:22 +00:00
bool /*Complain*/ ) override {
2019-12-08 10:51:19 +02:00
Out . indent ( 2 ) < < " Diagnostic options: \n " ;
# define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name);
# define ENUM_DIAGOPT(Name, Type, Bits, Default) \
Out . indent ( 4 ) < < # Name < < " : " < < DiagOpts - > get # # Name ( ) < < " \n " ;
# define VALUE_DIAGOPT(Name, Bits, Default) \
Out . indent ( 4 ) < < # Name < < " : " < < DiagOpts - > Name < < " \n " ;
# include "clang/Basic/DiagnosticOptions.def"
Out . indent ( 4 ) < < " Diagnostic flags: \n " ;
for ( const std : : string & Warning : DiagOpts - > Warnings )
Out . indent ( 6 ) < < " -W " < < Warning < < " \n " ;
for ( const std : : string & Remark : DiagOpts - > Remarks )
Out . indent ( 6 ) < < " -R " < < Remark < < " \n " ;
return false ;
}
bool ReadHeaderSearchOptions ( const HeaderSearchOptions & HSOpts ,
StringRef SpecificModuleCachePath ,
2020-09-30 15:46:22 +00:00
bool /*Complain*/ ) override {
2019-12-08 10:51:19 +02:00
Out . indent ( 2 ) < < " Header search options: \n " ;
Out . indent ( 4 ) < < " System root [-isysroot=]: ' "
< < HSOpts . Sysroot < < " ' \n " ;
Out . indent ( 4 ) < < " Resource dir [ -resource-dir=]: ' "
< < HSOpts . ResourceDir < < " ' \n " ;
Out . indent ( 4 ) < < " Module Cache: ' " < < SpecificModuleCachePath
< < " ' \n " ;
DUMP_BOOLEAN ( HSOpts . UseBuiltinIncludes ,
" Use builtin include directories [-nobuiltininc] " ) ;
DUMP_BOOLEAN ( HSOpts . UseStandardSystemIncludes ,
" Use standard system include directories [-nostdinc] " ) ;
DUMP_BOOLEAN ( HSOpts . UseStandardCXXIncludes ,
" Use standard C++ include directories [-nostdinc++] " ) ;
DUMP_BOOLEAN ( HSOpts . UseLibcxx ,
" Use libc++ (rather than libstdc++) [-stdlib=] " ) ;
return false ;
}
bool ReadPreprocessorOptions ( const PreprocessorOptions & PPOpts ,
2020-09-30 15:46:22 +00:00
bool /*Complain*/ ,
std : : string & /*SuggestedPredefines*/ ) override {
2019-12-08 10:51:19 +02:00
Out . indent ( 2 ) < < " Preprocessor options: \n " ;
DUMP_BOOLEAN ( PPOpts . UsePredefines ,
" Uses compiler/target-specific predefines [-undef] " ) ;
DUMP_BOOLEAN ( PPOpts . DetailedRecord ,
" Uses detailed preprocessing record (for indexing) " ) ;
if ( ! PPOpts . Macros . empty ( ) ) {
Out . indent ( 4 ) < < " Predefined macros: \n " ;
}
for ( std : : vector < std : : pair < std : : string , bool /*isUndef*/ > > : : const_iterator
I = PPOpts . Macros . begin ( ) , IEnd = PPOpts . Macros . end ( ) ;
I ! = IEnd ; + + I ) {
Out . indent ( 6 ) ;
if ( I - > second )
Out < < " -U " ;
else
Out < < " -D " ;
Out < < I - > first < < " \n " ;
}
return false ;
}
/// Indicates that a particular module file extension has been read.
void readModuleFileExtension (
const ModuleFileExtensionMetadata & Metadata ) override {
Out . indent ( 2 ) < < " Module file extension ' "
< < Metadata . BlockName < < " ' " < < Metadata . MajorVersion
< < " . " < < Metadata . MinorVersion ;
if ( ! Metadata . UserInfo . empty ( ) ) {
Out < < " : " ;
Out . write_escaped ( Metadata . UserInfo ) ;
}
Out < < " \n " ;
}
/// Tells the \c ASTReaderListener that we want to receive the
/// input files of the AST file via \c visitInputFile.
bool needsInputFileVisitation ( ) override { return true ; }
/// Tells the \c ASTReaderListener that we want to receive the
/// input files of the AST file via \c visitInputFile.
bool needsSystemInputFileVisitation ( ) override { return true ; }
/// Indicates that the AST file contains particular input file.
///
/// \returns true to continue receiving the next input file, false to stop.
bool visitInputFile ( StringRef Filename , bool isSystem ,
bool isOverridden , bool isExplicitModule ) override {
Out . indent ( 2 ) < < " Input file: " < < Filename ;
if ( isSystem | | isOverridden | | isExplicitModule ) {
Out < < " [ " ;
if ( isSystem ) {
Out < < " System " ;
if ( isOverridden | | isExplicitModule )
Out < < " , " ;
}
if ( isOverridden ) {
Out < < " Overridden " ;
if ( isExplicitModule )
Out < < " , " ;
}
if ( isExplicitModule )
Out < < " ExplicitModule " ;
Out < < " ] " ;
}
Out < < " \n " ;
return true ;
}
# undef DUMP_BOOLEAN
} ;
std : : unique_ptr < llvm : : raw_fd_ostream > OutFile ;
StringRef OutputFileName = FrontendOpts . OutputFile ;
if ( ! OutputFileName . empty ( ) & & OutputFileName ! = " - " ) {
std : : error_code EC ;
OutFile . reset ( new llvm : : raw_fd_ostream ( OutputFileName . str ( ) , EC ,
llvm : : sys : : fs : : F_Text ) ) ;
}
llvm : : raw_ostream & Out = OutFile . get ( ) ? * OutFile . get ( ) : llvm : : outs ( ) ;
StringRef CurInput = FrontendOpts . Inputs [ 0 ] . getFile ( ) ;
Out < < " Information for module file ' " < < CurInput < < " ': \n " ;
auto & FileMgr = CI . getFileManager ( ) ;
auto Buffer = FileMgr . getBufferForFile ( CurInput ) ;
StringRef Magic = ( * Buffer ) - > getMemBufferRef ( ) . getBuffer ( ) ;
bool IsRaw = ( Magic . size ( ) > = 4 & & Magic [ 0 ] = = ' C ' & & Magic [ 1 ] = = ' P ' & &
Magic [ 2 ] = = ' C ' & & Magic [ 3 ] = = ' H ' ) ;
Out < < " Module format: " < < ( IsRaw ? " raw " : " obj " ) < < " \n " ;
Preprocessor & PP = CI . getPreprocessor ( ) ;
DumpModuleInfoListener Listener ( Out ) ;
HeaderSearchOptions & HSOpts =
PP . getHeaderSearchInfo ( ) . getHeaderSearchOpts ( ) ;
ASTReader : : readASTFileControlBlock ( CurInput , FileMgr ,
CI . getPCHContainerReader ( ) ,
/*FindModuleFileExtensions=*/ true ,
Listener ,
HSOpts . ModulesValidateDiagnosticOptions ) ;
}
}
2016-08-08 16:29:06 -04:00
static CompilerInstance *
createCIImpl ( std : : unique_ptr < llvm : : MemoryBuffer > Buffer ,
2019-10-21 15:41:12 +02:00
const CompilerOptions & COpts ,
2019-10-15 18:32:21 +03:00
const char * LLVMDir ,
2019-05-24 10:41:17 +03:00
std : : unique_ptr < clang : : ASTConsumer > customConsumer ,
const CIFactory : : ModuleFileExtensions & moduleExtensions ,
bool OnlyLex , bool HasInput = false ) {
2016-08-16 18:05:45 -04:00
// Follow clang -v convention of printing version on first line
if ( COpts . Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " cling version " < < ClingStringify ( CLING_VERSION ) < < ' \n ' ;
2016-08-16 18:05:45 -04:00
2017-05-10 08:18:54 +02:00
llvm : : InitializeAllTargetInfos ( ) ;
llvm : : InitializeAllTargets ( ) ;
llvm : : InitializeAllAsmParsers ( ) ;
llvm : : InitializeAllAsmPrinters ( ) ;
llvm : : InitializeAllTargetMCs ( ) ;
2016-08-08 16:29:06 -04:00
// Create an instance builder, passing the LLVMDir and arguments.
2012-09-05 09:37:39 +00:00
//
2014-03-18 09:14:24 +01:00
CheckClangCompatibility ( ) ;
2016-08-08 16:29:06 -04:00
const size_t argc = COpts . Remaining . size ( ) ;
const char * const * argv = & COpts . Remaining [ 0 ] ;
2016-07-05 15:32:13 -04:00
std : : vector < const char * > argvCompile ( argv , argv + 1 ) ;
2020-08-04 15:59:48 +02:00
argvCompile . reserve ( argc + 32 ) ;
# if __APPLE__ && __arm64__
2021-04-06 17:25:19 +02:00
argvCompile . push_back ( " --target=arm64-apple-darwin20.3.0 " ) ;
2020-08-04 15:59:48 +02:00
# endif
2016-08-08 16:29:06 -04:00
2017-09-01 09:26:27 +02:00
// Variables for storing the memory of the C-string arguments.
// FIXME: We shouldn't use C-strings in the first place, but just use
// std::string for clang arguments.
std : : string overlayArg ;
std : : string cacheArg ;
// If user has enabled C++ modules we add some special module flags to the
// compiler invocation.
if ( COpts . CxxModules ) {
// Enables modules in clang.
argvCompile . push_back ( " -fmodules " ) ;
argvCompile . push_back ( " -fcxx-modules " ) ;
// We want to use modules in local-submodule-visibility mode. This mode
// will probably be the future default mode for C++ modules in clang, so
// we want to start using right now.
// Maybe we have to remove this flag in the future when clang makes this
// mode the default and removes this internal flag.
argvCompile . push_back ( " -Xclang " ) ;
argvCompile . push_back ( " -fmodules-local-submodule-visibility " ) ;
// If we got a cache path, then we are supposed to place any modules
// we have to build in this directory.
if ( ! COpts . CachePath . empty ( ) ) {
cacheArg = std : : string ( " -fmodules-cache-path= " ) + COpts . CachePath ;
argvCompile . push_back ( cacheArg . c_str ( ) ) ;
}
// Disable the module hash. This gives us a flat file layout in the
// modules cache directory. In clang this is used to prevent modules from
// different compiler invocations to not collide, but we only have one
// compiler invocation in cling, so we don't need this.
argvCompile . push_back ( " -Xclang " ) ;
argvCompile . push_back ( " -fdisable-module-hash " ) ;
// Disable the warning when we import a module from extern C. Some headers
// from the STL are doing this and we can't really do anything about this.
argvCompile . push_back ( " -Wno-module-import-in-extern-c " ) ;
2017-11-11 10:18:41 -07:00
// Disable the warning when we import a module in a function body. This
// is a ROOT-specific issue tracked by ROOT-9088.
// FIXME: Remove after merging ROOT's PR1306.
2017-11-13 23:45:35 +01:00
argvCompile . push_back ( " -Wno-modules-import-nested-redundant " ) ;
2017-11-19 08:46:40 -08:00
// FIXME: We get an error "'cling/module.modulemap' from the precompiled
// header has been overridden". This comes from a bug that rootcling
// introduces by adding a lot of garbage in the PCH/PCM files because it
// essentially serializes its current state of the AST. That usually
// includes a few memory buffers which override their own contents.
// We know how to remove this: just implement a callback in clang
// which calls back the interpreter when a module file is built. This is
// a lot of work as it needs fixing rootcling. See RE-0003.
argvCompile . push_back ( " -Xclang " ) ;
argvCompile . push_back ( " -fno-validate-pch " ) ;
2017-09-01 09:26:27 +02:00
}
2016-08-08 16:29:06 -04:00
if ( ! COpts . Language ) {
2016-07-05 15:32:13 -04:00
// We do C++ by default; append right after argv[0] if no "-x" given
argvCompile . push_back ( " -x " ) ;
argvCompile . push_back ( " c++ " ) ;
2017-07-05 11:59:24 -04:00
}
2018-03-14 13:41:11 +01:00
2017-07-05 11:59:24 -04:00
if ( COpts . DefaultLanguage ( ) ) {
// By default, set the standard to what cling was compiled with.
// clang::driver::Compilation will do various things while initializing
// and by enforcing the std version now cling is telling clang what to
// do, rather than after clang has dedcuded a default.
switch ( CxxStdCompiledWith ( ) ) {
2021-09-11 19:21:20 +00:00
case 20 : argvCompile . emplace_back ( " -std=c++20 " ) ; break ;
2020-03-11 12:40:10 +02:00
case 17 : argvCompile . emplace_back ( " -std=c++17 " ) ; break ;
2017-07-05 11:59:24 -04:00
case 14 : argvCompile . emplace_back ( " -std=c++14 " ) ; break ;
case 11 : argvCompile . emplace_back ( " -std=c++11 " ) ; break ;
default : llvm_unreachable ( " Unrecognized C++ version " ) ;
2017-07-04 12:58:05 -04:00
}
2012-09-05 09:37:39 +00:00
}
2018-03-14 13:41:11 +01:00
// This argument starts the cling instance with the x86 target. Otherwise,
// the first job in the joblist starts the cling instance with the nvptx
// target.
2019-01-15 12:21:51 +01:00
if ( COpts . CUDAHost )
2018-03-14 13:41:11 +01:00
argvCompile . push_back ( " --cuda-host-only " ) ;
2016-07-05 15:32:13 -04:00
// argv[0] already inserted, get the rest
argvCompile . insert ( argvCompile . end ( ) , argv + 1 , argv + argc ) ;
2014-10-02 14:39:25 +02:00
2016-07-05 16:19:41 -04:00
// Add host specific includes, -resource-dir if necessary, and -isysroot
2016-08-08 16:29:06 -04:00
std : : string ClingBin = GetExecutablePath ( argv [ 0 ] ) ;
AddHostArguments ( ClingBin , argvCompile , LLVMDir , COpts ) ;
2012-09-05 09:37:39 +00:00
2016-08-10 16:04:59 -04:00
// Be explicit about the stdlib on OS X
// Would be nice on Linux but will warn 'argument unused during compilation'
// when -nostdinc++ is passed
# ifdef __APPLE__
2017-07-04 12:53:27 -04:00
if ( ! COpts . StdLib ) {
2016-08-10 16:04:59 -04:00
# ifdef _LIBCPP_VERSION
2017-07-04 12:53:27 -04:00
argvCompile . push_back ( " -stdlib=libc++ " ) ;
2016-08-10 16:04:59 -04:00
# elif defined(__GLIBCXX__)
2017-07-04 12:53:27 -04:00
argvCompile . push_back ( " -stdlib=libstdc++ " ) ;
2016-08-10 16:04:59 -04:00
# endif
2017-07-04 12:53:27 -04:00
}
2016-08-10 16:04:59 -04:00
# endif
2016-08-08 19:02:10 -04:00
if ( ! COpts . HasOutput | | ! HasInput ) {
2021-02-11 16:20:30 +00:00
// suppress the warning "argument unused during compilation: -c" of the
// device interpreter instance
if ( ! COpts . CUDADevice )
argvCompile . push_back ( " -c " ) ;
2016-07-21 18:29:10 -04:00
argvCompile . push_back ( " - " ) ;
}
2014-10-02 14:39:25 +02:00
2017-05-18 15:16:30 +02:00
auto InvocationPtr = std : : make_shared < clang : : CompilerInvocation > ( ) ;
2016-07-01 22:50:33 -04:00
2014-03-28 10:50:27 +01:00
// The compiler invocation is the owner of the diagnostic options.
// Everything else points to them.
2016-07-01 22:50:33 -04:00
DiagnosticOptions & DiagOpts = InvocationPtr - > getDiagnosticOpts ( ) ;
2021-01-27 19:50:26 +00:00
// add prefix to diagnostic messages if second compiler instance is existing
// e.g. in CUDA mode
2021-02-05 10:20:48 +00:00
std : : string ExeName = " " ;
if ( COpts . CUDAHost )
2021-03-05 17:56:26 +00:00
ExeName = " cling " ;
if ( COpts . CUDADevice )
ExeName = " cling-ptx " ;
2021-02-05 10:20:48 +00:00
llvm : : IntrusiveRefCntPtr < DiagnosticsEngine > Diags =
SetupDiagnostics ( DiagOpts , ExeName ) ;
2016-07-01 22:50:33 -04:00
if ( ! Diags ) {
cling : : errs ( ) < < " Could not setup diagnostic engine. \n " ;
return nullptr ;
}
2017-03-01 17:17:26 +01:00
llvm : : Triple TheTriple ( llvm : : sys : : getProcessTriple ( ) ) ;
2020-10-05 06:22:33 +00:00
# ifdef _WIN32
2017-03-01 17:17:26 +01:00
// COFF format currently needs a few changes in LLVM to function properly.
2017-11-29 14:17:01 +01:00
TheTriple . setObjectFormat ( llvm : : Triple : : COFF ) ;
2017-03-01 17:17:26 +01:00
# endif
clang : : driver : : Driver Drvr ( argv [ 0 ] , TheTriple . getTriple ( ) , * Diags ) ;
2016-07-01 22:50:33 -04:00
//Drvr.setWarnMissingInput(false);
Drvr . setCheckInputsExist ( false ) ; // think foo.C(12)
2012-09-05 09:37:39 +00:00
llvm : : ArrayRef < const char * > RF ( & ( argvCompile [ 0 ] ) , argvCompile . size ( ) ) ;
2014-08-14 12:29:27 +02:00
std : : unique_ptr < clang : : driver : : Compilation >
2016-07-01 22:50:33 -04:00
Compilation ( Drvr . BuildCompilation ( RF ) ) ;
if ( ! Compilation ) {
cling : : errs ( ) < < " Couldn't create clang::driver::Compilation. \n " ;
return nullptr ;
}
2020-03-11 12:41:13 +02:00
const llvm : : opt : : ArgStringList * CC1Args = GetCC1Arguments ( Compilation . get ( ) ) ;
2016-07-01 22:50:33 -04:00
if ( ! CC1Args ) {
cling : : errs ( ) < < " Could not get cc1 arguments. \n " ;
return nullptr ;
2012-09-05 09:37:39 +00:00
}
2015-11-02 16:52:52 -06:00
2021-09-11 19:53:01 +00:00
clang : : CompilerInvocation : : CreateFromArgs ( * InvocationPtr , * CC1Args , * Diags ) ;
2015-11-02 16:52:52 -06:00
// We appreciate the error message about an unknown flag (or do we? if not
// we should switch to a different DiagEngine for parsing the flags).
// But in general we'll happily go on.
Diags - > Reset ( ) ;
2015-07-03 17:42:10 +02:00
// Create and setup a compiler instance.
std : : unique_ptr < CompilerInstance > CI ( new CompilerInstance ( ) ) ;
2017-05-18 15:16:30 +02:00
CI - > setInvocation ( InvocationPtr ) ;
2016-07-01 22:50:33 -04:00
CI - > setDiagnostics ( Diags . get ( ) ) ; // Diags is ref-counted
2017-01-28 19:46:30 -05:00
if ( ! OnlyLex )
2021-09-11 18:13:46 +00:00
CI - > getDiagnosticOpts ( ) . ShowColors =
llvm : : sys : : Process : : StandardOutIsDisplayed ( ) | |
llvm : : sys : : Process : : StandardErrIsDisplayed ( ) ;
2017-01-28 19:46:30 -05:00
2017-01-29 18:00:15 -05:00
// Copied from CompilerInstance::createDiagnostics:
// Chain in -verify checker, if requested.
if ( DiagOpts . VerifyDiagnostics )
Diags - > setClient ( new clang : : VerifyDiagnosticConsumer ( * Diags ) ) ;
// Configure our handling of diagnostics.
ProcessWarningOptions ( * Diags , DiagOpts ) ;
2016-08-08 19:02:10 -04:00
if ( COpts . HasOutput & & ! OnlyLex ) {
ActionScan scan ( clang : : driver : : Action : : PrecompileJobClass ,
clang : : driver : : Action : : PreprocessJobClass ) ;
2016-07-21 18:29:10 -04:00
if ( ! scan . find ( Compilation . get ( ) ) ) {
2016-08-08 19:02:10 -04:00
cling : : errs ( ) < < " Only precompiled header or preprocessor "
" output is supported. \n " ;
2016-07-21 18:29:10 -04:00
return nullptr ;
}
2017-06-26 23:55:40 -04:00
if ( ! SetupCompiler ( CI . get ( ) , COpts ) )
2016-07-21 18:29:10 -04:00
return nullptr ;
ProcessWarningOptions ( * Diags , DiagOpts ) ;
return CI . release ( ) ;
}
2016-07-01 22:50:33 -04:00
CI - > createFileManager ( ) ;
clang : : CompilerInvocation & Invocation = CI - > getInvocation ( ) ;
2017-01-29 18:16:31 -05:00
std : : string & PCHFile = Invocation . getPreprocessorOpts ( ) . ImplicitPCHInclude ;
bool InitLang = true , InitTarget = true ;
if ( ! PCHFile . empty ( ) ) {
if ( cling : : utils : : LookForFile ( argvCompile , PCHFile ,
2016-09-08 17:15:38 -04:00
& CI - > getFileManager ( ) ,
COpts . Verbose ? " Precompiled header " : nullptr ) ) {
// Load target options etc from PCH.
struct PCHListener : public ASTReaderListener {
CompilerInvocation & m_Invocation ;
2017-01-29 18:16:31 -05:00
bool m_ReadLang , m_ReadTarget ;
2016-09-08 17:15:38 -04:00
2017-01-29 18:16:31 -05:00
PCHListener ( CompilerInvocation & I ) :
m_Invocation ( I ) , m_ReadLang ( false ) , m_ReadTarget ( false ) { }
2016-09-08 17:15:38 -04:00
bool ReadLanguageOptions ( const LangOptions & LangOpts ,
bool /*Complain*/ ,
bool /*AllowCompatibleDifferences*/ ) override {
* m_Invocation . getLangOpts ( ) = LangOpts ;
2017-01-29 18:16:31 -05:00
m_ReadLang = true ;
2016-09-08 17:15:38 -04:00
return false ;
}
bool ReadTargetOptions ( const TargetOptions & TargetOpts ,
2015-07-03 17:42:10 +02:00
bool /*Complain*/ ,
bool /*AllowCompatibleDifferences*/ ) override {
2016-09-08 17:15:38 -04:00
m_Invocation . getTargetOpts ( ) = TargetOpts ;
2017-01-29 18:16:31 -05:00
m_ReadTarget = true ;
2016-09-08 17:15:38 -04:00
return false ;
}
bool ReadPreprocessorOptions ( const PreprocessorOptions & PPOpts ,
bool /*Complain*/ ,
std : : string & /*SuggestedPredefines*/ ) override {
// Import selected options, e.g. don't overwrite ImplicitPCHInclude.
PreprocessorOptions & myPP = m_Invocation . getPreprocessorOpts ( ) ;
insertBehind ( myPP . Macros , PPOpts . Macros ) ;
insertBehind ( myPP . Includes , PPOpts . Includes ) ;
insertBehind ( myPP . MacroIncludes , PPOpts . MacroIncludes ) ;
return false ;
}
} ;
2016-07-01 22:50:33 -04:00
PCHListener listener ( Invocation ) ;
2017-01-29 18:16:31 -05:00
if ( ASTReader : : readASTFileControlBlock ( PCHFile ,
CI - > getFileManager ( ) ,
CI - > getPCHContainerReader ( ) ,
false /*FindModuleFileExt*/ ,
2017-05-18 15:16:30 +02:00
listener ,
/*ValidateDiagnosticOptions=*/ false ) ) {
2017-01-29 18:16:31 -05:00
// When running interactively pass on the info that the PCH
// has failed so that IncrmentalParser::Initialize won't try again.
if ( ! HasInput & & llvm : : sys : : Process : : StandardInIsUserInput ( ) ) {
const unsigned ID = Diags - > getCustomDiagID (
clang : : DiagnosticsEngine : : Level : : Error ,
" Problems loading PCH: '%0'. " ) ;
Diags - > Report ( ID ) < < PCHFile ;
// If this was the only error, then don't let it stop anything
if ( Diags - > getClient ( ) - > getNumErrors ( ) = = 1 )
Diags - > Reset ( true ) ;
// Clear the include so no one else uses it.
std : : string ( ) . swap ( PCHFile ) ;
}
}
// All we care about is if Language and Target options were successful.
InitLang = ! listener . m_ReadLang ;
InitTarget = ! listener . m_ReadTarget ;
2016-09-08 17:15:38 -04:00
}
2015-07-03 17:42:10 +02:00
}
2019-05-13 17:25:11 +03:00
FrontendOptions & FrontendOpts = Invocation . getFrontendOpts ( ) ;
2019-05-24 10:41:17 +03:00
// Register the externally constructed extensions.
assert ( FrontendOpts . ModuleFileExtensions . empty ( ) & & " Extensions exist! " ) ;
for ( auto & E : moduleExtensions )
FrontendOpts . ModuleFileExtensions . push_back ( E ) ;
2018-10-26 08:24:39 -07:00
FrontendOpts . DisableFree = true ;
2012-09-05 09:37:39 +00:00
2016-07-21 18:29:10 -04:00
// Set up compiler language and target
2017-06-26 23:55:40 -04:00
if ( ! SetupCompiler ( CI . get ( ) , COpts , InitLang , InitTarget ) )
2016-07-01 22:50:33 -04:00
return nullptr ;
2012-09-05 09:37:39 +00:00
2015-07-03 17:42:10 +02:00
// Set up source managers
2013-09-17 16:25:52 +02:00
SourceManager * SM = new SourceManager ( CI - > getDiagnostics ( ) ,
CI - > getFileManager ( ) ,
2014-01-17 17:20:25 +01:00
/*UserFilesAreVolatile*/ true ) ;
2016-07-01 22:50:33 -04:00
CI - > setSourceManager ( SM ) ; // CI now owns SM
2012-09-05 09:37:39 +00:00
2021-09-11 20:00:17 +00:00
if ( CI - > getCodeGenOpts ( ) . TimePasses )
2018-10-26 08:24:39 -07:00
CI - > createFrontendTimer ( ) ;
if ( FrontendOpts . ModulesEmbedAllFiles )
2017-11-30 12:38:38 +01:00
CI - > getSourceManager ( ) . setAllFilesAreTransient ( true ) ;
2013-11-25 10:57:00 +01:00
// As main file we want
2014-01-17 17:20:25 +01:00
// * a virtual file that is claiming to be huge
2013-11-25 10:57:00 +01:00
// * with an empty memory buffer attached (to bring the content)
FileManager & FM = SM - > getFileManager ( ) ;
2015-03-25 11:55:22 +01:00
// When asking for the input file below (which does not have a directory
// name), clang will call $PWD "." which is terrible if we ever change
// directories (see ROOT-7114). By asking for $PWD (and not ".") it will
// be registered as $PWD instead, which is stable even after chdirs.
2016-09-14 15:49:22 -04:00
FM . getDirectory ( platform : : GetCwd ( ) ) ;
2016-08-10 14:45:17 -04:00
// Build the virtual file, Give it a name that's likely not to ever
2016-12-19 11:57:06 +01:00
// be #included (so we won't get a clash in clang's cache).
2016-08-10 14:45:17 -04:00
const char * Filename = " <<< cling interactive line includer >>> " ;
const FileEntry * FE = FM . getVirtualFile ( Filename , 1U < < 15U , time ( 0 ) ) ;
2016-05-18 16:03:22 +02:00
// Tell ASTReader to create a FileID even if this file does not exist:
SM - > setFileIsTransient ( FE ) ;
2014-06-06 09:38:12 +02:00
FileID MainFileID = SM - > createFileID ( FE , SourceLocation ( ) , SrcMgr : : C_User ) ;
SM - > setMainFileID ( MainFileID ) ;
2013-11-25 10:57:00 +01:00
const SrcMgr : : SLocEntry & MainFileSLocE = SM - > getSLocEntry ( MainFileID ) ;
2020-03-15 14:31:19 +02:00
const SrcMgr : : FileInfo & MainFileFI = MainFileSLocE . getFile ( ) ;
SrcMgr : : ContentCache * MainFileCC
= const_cast < SrcMgr : : ContentCache * > ( MainFileFI . getContentCache ( ) ) ;
2016-08-08 16:29:06 -04:00
if ( ! Buffer )
2016-11-09 17:53:50 +01:00
Buffer = llvm : : MemoryBuffer : : getMemBuffer ( " /*CLING DEFAULT MEMBUF*/; \n " ) ;
2020-03-15 14:31:19 +02:00
MainFileCC - > replaceBuffer ( Buffer . release ( ) , /*DoNotFree*/ false ) ;
2012-09-05 09:37:39 +00:00
2018-03-14 13:25:23 +01:00
// Create TargetInfo for the other side of CUDA and OpenMP compilation.
if ( ( CI - > getLangOpts ( ) . CUDA | | CI - > getLangOpts ( ) . OpenMPIsDevice ) & &
! CI - > getFrontendOpts ( ) . AuxTriple . empty ( ) ) {
auto TO = std : : make_shared < TargetOptions > ( ) ;
TO - > Triple = CI - > getFrontendOpts ( ) . AuxTriple ;
TO - > HostTriple = CI - > getTarget ( ) . getTriple ( ) . str ( ) ;
CI - > setAuxTarget ( TargetInfo : : CreateTargetInfo ( CI - > getDiagnostics ( ) , TO ) ) ;
}
2012-09-05 09:37:39 +00:00
// Set up the preprocessor
2014-06-06 09:38:35 +02:00
CI - > createPreprocessor ( TU_Complete ) ;
2019-11-29 11:47:45 +02:00
// With modules, we now start adding prebuilt module paths to the CI.
// Modules from those paths are treated like they are never out of date
// and we don't update them on demand.
// This mostly helps ROOT where we can't just recompile any out of date
// modules because we would miss the annotations that rootcling creates.
if ( COpts . CxxModules ) {
setupCxxModules ( * CI ) ;
}
2012-09-05 09:37:39 +00:00
Preprocessor & PP = CI - > getPreprocessor ( ) ;
2019-10-15 18:32:21 +03:00
2016-04-22 15:11:18 +02:00
PP . getBuiltinInfo ( ) . initializeBuiltins ( PP . getIdentifierTable ( ) ,
2012-09-05 09:37:39 +00:00
PP . getLangOpts ( ) ) ;
// Set up the ASTContext
2014-06-06 09:38:35 +02:00
CI - > createASTContext ( ) ;
2012-09-05 09:37:39 +00:00
2017-09-01 09:26:27 +02:00
std : : vector < std : : unique_ptr < ASTConsumer > > Consumers ;
if ( ! OnlyLex ) {
2017-09-10 11:59:51 +02:00
assert ( customConsumer & & " Need to specify a custom consumer "
" when not in OnlyLex mode " ) ;
2017-09-01 09:26:27 +02:00
Consumers . push_back ( std : : move ( customConsumer ) ) ;
2013-11-18 16:49:19 +01:00
}
2012-09-05 09:37:39 +00:00
2017-09-01 09:26:27 +02:00
// With C++ modules, we now attach the consumers that will handle the
2017-10-28 17:54:15 +02:00
// generation of the PCM file itself in case we want to generate
// a C++ module with the current interpreter instance.
if ( COpts . CxxModules & & ! COpts . ModuleName . empty ( ) ) {
2017-09-01 09:26:27 +02:00
// Code below from the (private) code in the GenerateModuleAction class.
llvm : : SmallVector < char , 256 > Output ;
llvm : : sys : : path : : append ( Output , COpts . CachePath ,
COpts . ModuleName + " .pcm " ) ;
StringRef ModuleOutputFile = StringRef ( Output . data ( ) , Output . size ( ) ) ;
std : : unique_ptr < raw_pwrite_stream > OS =
CI - > createOutputFile ( ModuleOutputFile , /*Binary=*/ true ,
/*RemoveFileOnSignal=*/ false , " " ,
/*Extension=*/ " " , /*useTemporary=*/ true ,
/*CreateMissingDirectories=*/ true ) ;
assert ( OS ) ;
std : : string Sysroot ;
2020-09-30 19:32:52 +00:00
auto PCHBuff = std : : make_shared < PCHBuffer > ( ) ;
2017-09-01 09:26:27 +02:00
Consumers . push_back ( llvm : : make_unique < PCHGenerator > (
2020-03-15 14:33:55 +02:00
CI - > getPreprocessor ( ) , CI - > getModuleCache ( ) , ModuleOutputFile ,
2020-09-30 19:32:52 +00:00
Sysroot , PCHBuff , CI - > getFrontendOpts ( ) . ModuleFileExtensions ,
2017-09-01 09:26:27 +02:00
/*AllowASTWithErrors=*/ false ,
/*IncludeTimestamps=*/
+ CI - > getFrontendOpts ( ) . BuildingImplicitModule ) ) ;
Consumers . push_back (
CI - > getPCHContainerWriter ( ) . CreatePCHContainerGenerator (
2021-09-11 18:12:30 +00:00
* CI , " " , ModuleOutputFile . str ( ) , std : : move ( OS ) , PCHBuff ) ) ;
2017-09-01 09:26:27 +02:00
// Set the current module name for clang. With that clang doesn't start
// to build the current module on demand when we include a header
// from the current module.
CI - > getLangOpts ( ) . CurrentModule = COpts . ModuleName ;
CI - > getLangOpts ( ) . setCompilingModule ( LangOptions : : CMK_ModuleMap ) ;
// Push the current module to the build stack so that clang knows when
// we have a cyclic dependency.
SM - > pushModuleBuildStack ( COpts . ModuleName ,
FullSourceLoc ( SourceLocation ( ) , * SM ) ) ;
}
std : : unique_ptr < clang : : MultiplexConsumer > multiConsumer (
new clang : : MultiplexConsumer ( std : : move ( Consumers ) ) ) ;
CI - > setASTConsumer ( std : : move ( multiConsumer ) ) ;
2012-09-05 09:37:39 +00:00
// Set up Sema
CodeCompleteConsumer * CCC = 0 ;
2017-09-01 09:26:27 +02:00
// Make sure we inform Sema we compile a Module.
CI - > createSema ( COpts . ModuleName . empty ( ) ? TU_Complete : TU_Module , CCC ) ;
2012-09-05 09:37:39 +00:00
2017-03-27 16:41:26 +02:00
// Set CodeGen options.
CodeGenOptions & CGOpts = CI - > getCodeGenOpts ( ) ;
2016-11-29 16:08:23 +01:00
# ifdef _MSC_VER
2017-03-27 16:41:26 +02:00
CGOpts . MSVolatile = 1 ;
CGOpts . RelaxedAliasing = 1 ;
CGOpts . EmitCodeView = 1 ;
CGOpts . CXXCtorDtorAliases = 1 ;
2016-11-29 16:08:23 +01:00
# endif
2017-10-19 20:55:41 +02:00
// Taken from a -O2 run of clang:
CGOpts . DiscardValueNames = 1 ;
CGOpts . OmitLeafFramePointer = 1 ;
CGOpts . UnrollLoops = 1 ;
CGOpts . VectorizeLoop = 1 ;
CGOpts . VectorizeSLP = 1 ;
2019-01-09 18:47:49 +01:00
CGOpts . DisableO0ImplyOptNone = 1 ; // Enable dynamic opt level switching.
2017-03-27 16:41:26 +02:00
2021-02-03 08:48:59 +01:00
// Set up inlining, even if we switch to O0 later: some transactions' code
// might pass `#pragma cling optimize` levels that require it. This is
// adjusted per transaction in IncrementalParser::codeGenTransaction().
CGOpts . setInlining ( CodeGenOptions : : NormalInlining ) ;
2018-07-25 10:36:29 +02:00
2022-06-13 10:52:11 +02:00
// CGOpts.setDebugInfo(clang::CodeGenOptions::FullDebugInfo);
2017-03-27 16:41:26 +02:00
// CGOpts.EmitDeclMetadata = 1; // For unloading, for later
// aliasing the complete ctor to the base ctor causes the JIT to crash
CGOpts . CXXCtorDtorAliases = 0 ;
CGOpts . VerifyModule = 0 ; // takes too long
2013-06-13 13:57:54 +02:00
2016-08-16 05:46:10 -04:00
if ( ! OnlyLex ) {
// -nobuiltininc
clang : : HeaderSearchOptions & HOpts = CI - > getHeaderSearchOpts ( ) ;
if ( CI - > getHeaderSearchOpts ( ) . UseBuiltinIncludes )
2016-08-08 16:29:06 -04:00
AddRuntimeIncludePaths ( ClingBin , HOpts ) ;
2016-08-16 05:46:10 -04:00
2016-08-16 18:05:45 -04:00
// Write a marker to know the rest of the output is from clang
if ( COpts . Verbose )
2016-09-10 15:04:39 -04:00
cling : : log ( ) < < " Setting up system headers with clang: \n " ;
2016-08-16 18:05:45 -04:00
2016-08-16 05:46:10 -04:00
// ### FIXME:
// Want to update LLVM to 3.9 realease and better testing first, but
// ApplyHeaderSearchOptions shouldn't even be called here:
// 1. It's already been called via CI->createPreprocessor(TU_Complete)
// 2. It could corrupt clang's directory cache
// HeaderSearchOptions.::AddSearchPath is a better alternative
clang : : ApplyHeaderSearchOptions ( PP . getHeaderSearchInfo ( ) , HOpts ,
PP . getLangOpts ( ) ,
PP . getTargetInfo ( ) . getTriple ( ) ) ;
}
2020-03-19 09:05:49 +02:00
// Tell the diagnostic client that we are entering file parsing mode as the
// handling of modulemap files may issue diagnostics.
// FIXME: Consider moving in SetupDiagnostics.
DiagnosticConsumer & DClient = CI - > getDiagnosticClient ( ) ;
DClient . BeginSourceFile ( CI - > getLangOpts ( ) , & PP ) ;
2020-09-30 19:32:52 +00:00
for ( const auto & ModuleMapFile : FrontendOpts . ModuleMapFiles ) {
if ( auto * File = FM . getFile ( ModuleMapFile ) )
2019-05-14 14:12:08 +03:00
PP . getHeaderSearchInfo ( ) . loadModuleMapFile ( File , /*IsSystem*/ false ) ;
else
2020-09-30 19:32:52 +00:00
CI - > getDiagnostics ( ) . Report ( diag : : err_module_map_not_found )
< < ModuleMapFile ;
2019-05-14 14:12:08 +03:00
}
2019-12-08 10:51:19 +02:00
HandleProgramActions ( * CI ) ;
2014-08-14 12:29:27 +02:00
return CI . release ( ) ; // Passes over the ownership to the caller.
2012-09-05 09:37:39 +00:00
}
2015-01-21 13:28:30 +01:00
} // unnamed namespace
2016-08-16 05:53:04 -04:00
namespace cling {
2017-09-10 11:59:51 +02:00
CompilerInstance *
CIFactory : : createCI ( llvm : : StringRef Code , const InvocationOptions & Opts ,
const char * LLVMDir ,
2019-05-24 10:41:17 +03:00
std : : unique_ptr < clang : : ASTConsumer > consumer ,
const ModuleFileExtensions & moduleExtensions ) {
2017-06-29 14:45:07 +02:00
return createCIImpl ( llvm : : MemoryBuffer : : getMemBuffer ( Code ) , Opts . CompilerOpts ,
2019-05-24 10:41:17 +03:00
LLVMDir , std : : move ( consumer ) , moduleExtensions ,
false /*OnlyLex*/ ,
2017-01-29 18:13:48 -05:00
! Opts . IsInteractive ( ) ) ;
2016-08-08 16:29:06 -04:00
}
2015-01-21 13:28:30 +01:00
2017-09-10 11:59:51 +02:00
CompilerInstance * CIFactory : : createCI (
MemBufPtr_t Buffer , int argc , const char * const * argv , const char * LLVMDir ,
2019-05-24 10:41:17 +03:00
std : : unique_ptr < clang : : ASTConsumer > consumer ,
const ModuleFileExtensions & moduleExtensions , bool OnlyLex /*false*/ ) {
2019-10-21 15:41:12 +02:00
return createCIImpl ( std : : move ( Buffer ) , CompilerOptions ( argc , argv ) , LLVMDir ,
2019-05-24 10:41:17 +03:00
std : : move ( consumer ) , moduleExtensions , OnlyLex ) ;
2016-08-08 16:29:06 -04:00
}
2016-08-16 05:53:04 -04:00
2016-08-25 15:35:14 +02:00
} // namespace cling
2016-08-16 05:53:04 -04:00