Compare commits
20 Commits
llvmorg-2.
...
llvmorg-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52a52a9911 | ||
|
|
2eed6e9122 | ||
|
|
44008a16b7 | ||
|
|
6e518e6326 | ||
|
|
f924987081 | ||
|
|
4452c27c9a | ||
|
|
02e054d107 | ||
|
|
9096e27509 | ||
|
|
42260d7716 | ||
|
|
faa1d1f04d | ||
|
|
0d6d28b38f | ||
|
|
4a0f8ad6f1 | ||
|
|
ccb2261ec3 | ||
|
|
b93e94b748 | ||
|
|
8b83d1b419 | ||
|
|
188c951004 | ||
|
|
cf7c329798 | ||
|
|
3d2a2eb218 | ||
|
|
6935fa4016 | ||
|
|
f37a450b62 |
@@ -1,152 +0,0 @@
|
||||
# Clang version information
|
||||
|
||||
set(CLANG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(CLANG_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE )
|
||||
message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite "
|
||||
"the makefiles distributed with LLVM. Please create a directory and run cmake "
|
||||
"from there, passing the path to this source directory as the last argument. "
|
||||
"This process created the file `CMakeCache.txt' and the directory "
|
||||
"`CMakeFiles'. Please delete them.")
|
||||
endif()
|
||||
|
||||
if( NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
|
||||
file(GLOB_RECURSE
|
||||
tablegenned_files_on_include_dir
|
||||
"${CLANG_SOURCE_DIR}/include/clang/*.inc")
|
||||
if( tablegenned_files_on_include_dir )
|
||||
message(FATAL_ERROR "Apparently there is a previous in-source build, "
|
||||
"probably as the result of running `configure' and `make' on "
|
||||
"${CLANG_SOURCE_DIR}. This may cause problems. The suspicious files are:\n"
|
||||
"${tablegenned_files_on_include_dir}\nPlease clean the source directory.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Compute the Clang version from the LLVM version.
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
|
||||
${PACKAGE_VERSION})
|
||||
message(STATUS "Clang version: ${CLANG_VERSION}")
|
||||
|
||||
string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" CLANG_VERSION_MAJOR
|
||||
${CLANG_VERSION})
|
||||
string(REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" CLANG_VERSION_MINOR
|
||||
${CLANG_VERSION})
|
||||
if (${CLANG_VERSION} MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+")
|
||||
set(CLANG_HAS_VERSION_PATCHLEVEL 1)
|
||||
string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" CLANG_VERSION_PATCHLEVEL
|
||||
${CLANG_VERSION})
|
||||
else()
|
||||
set(CLANG_HAS_VERSION_PATCHLEVEL 0)
|
||||
endif()
|
||||
|
||||
# Configure the Version.inc file.
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/clang/Basic/Version.inc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/clang/Basic/Version.inc)
|
||||
|
||||
# Add appropriate flags for GCC
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
# FIXME: Turn off exceptions, RTTI:
|
||||
# -fno-exceptions -fno-rtti
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings")
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "-Wl,-flat_namespace -Wl,-undefined -Wl,suppress")
|
||||
endif ()
|
||||
|
||||
macro(add_clang_library name)
|
||||
set(srcs ${ARGN})
|
||||
if(MSVC_IDE OR XCODE)
|
||||
file( GLOB_RECURSE headers *.h *.td *.def)
|
||||
set(srcs ${srcs} ${headers})
|
||||
string( REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
list( GET split_path -1 dir)
|
||||
file( GLOB_RECURSE headers
|
||||
../../include/clang${dir}/*.h
|
||||
../../include/clang${dir}/*.td
|
||||
../../include/clang${dir}/*.def)
|
||||
set(srcs ${srcs} ${headers})
|
||||
endif(MSVC_IDE OR XCODE)
|
||||
if (MODULE)
|
||||
set(libkind MODULE)
|
||||
elseif (SHARED_LIBRARY)
|
||||
set(libkind SHARED)
|
||||
else()
|
||||
set(libkind)
|
||||
endif()
|
||||
add_library( ${name} ${libkind} ${srcs} )
|
||||
if( LLVM_COMMON_DEPENDS )
|
||||
add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} )
|
||||
endif( LLVM_COMMON_DEPENDS )
|
||||
if( LLVM_USED_LIBS )
|
||||
foreach(lib ${LLVM_USED_LIBS})
|
||||
target_link_libraries( ${name} ${lib} )
|
||||
endforeach(lib)
|
||||
endif( LLVM_USED_LIBS )
|
||||
if( LLVM_LINK_COMPONENTS )
|
||||
llvm_config(${name} ${LLVM_LINK_COMPONENTS})
|
||||
endif( LLVM_LINK_COMPONENTS )
|
||||
get_system_libs(llvm_system_libs)
|
||||
if( llvm_system_libs )
|
||||
target_link_libraries(${name} ${llvm_system_libs})
|
||||
endif( llvm_system_libs )
|
||||
add_dependencies(${name} ClangDiagnosticCommon)
|
||||
if(MSVC)
|
||||
get_target_property(cflag ${name} COMPILE_FLAGS)
|
||||
if(NOT cflag)
|
||||
set(cflag "")
|
||||
endif(NOT cflag)
|
||||
set(cflag "${cflag} /Za")
|
||||
set_target_properties(${name} PROPERTIES COMPILE_FLAGS ${cflag})
|
||||
endif(MSVC)
|
||||
install(TARGETS ${name}
|
||||
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
|
||||
endmacro(add_clang_library)
|
||||
|
||||
macro(add_clang_executable name)
|
||||
set(srcs ${ARGN})
|
||||
if(MSVC_IDE)
|
||||
file( GLOB_RECURSE headers *.h *.td *.def)
|
||||
set(srcs ${srcs} ${headers})
|
||||
endif(MSVC_IDE)
|
||||
add_llvm_executable( ${name} ${srcs} )
|
||||
endmacro(add_clang_executable)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include
|
||||
)
|
||||
|
||||
install(DIRECTORY include/
|
||||
DESTINATION include
|
||||
FILES_MATCHING
|
||||
PATTERN "*.def"
|
||||
PATTERN "*.h"
|
||||
PATTERN "*.td"
|
||||
PATTERN ".svn" EXCLUDE
|
||||
)
|
||||
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/
|
||||
DESTINATION include
|
||||
FILES_MATCHING
|
||||
PATTERN "CMakeFiles" EXCLUDE
|
||||
PATTERN "*.inc"
|
||||
)
|
||||
|
||||
add_definitions( -D_GNU_SOURCE )
|
||||
|
||||
option(CLANG_BUILD_EXAMPLES "Build CLANG example programs." OFF)
|
||||
if(CLANG_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(tools)
|
||||
|
||||
# TODO: docs.
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
@@ -1,51 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cfloat>
|
||||
#include <ciso646>
|
||||
#include <climits>
|
||||
#include <clocale>
|
||||
#include <cmath>
|
||||
#include <complex>
|
||||
#include <csetjmp>
|
||||
#include <csignal>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <cwchar>
|
||||
#include <cwctype>
|
||||
#include <deque>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <iosfwd>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <numeric>
|
||||
#include <ostream>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <stdexcept>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
#include <strstream>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
#include <valarray>
|
||||
#include <vector>
|
||||
@@ -1,639 +0,0 @@
|
||||
/* Test for integer constant types. */
|
||||
|
||||
/* Origin: Joseph Myers <jsm28@cam.ac.uk>. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* Assertion that constant C is of type T. */
|
||||
#define ASSERT_CONST_TYPE(C, T) \
|
||||
do { \
|
||||
typedef T type; \
|
||||
typedef type **typepp; \
|
||||
typedef __typeof__((C)) ctype; \
|
||||
typedef ctype **ctypepp; \
|
||||
typepp x = 0; \
|
||||
ctypepp y = 0; \
|
||||
x = y; \
|
||||
y = x; \
|
||||
} while (0)
|
||||
|
||||
/* (T *) if E is zero, (void *) otherwise. */
|
||||
#define type_if_not(T, E) __typeof__(0 ? (T *)0 : (void *)(E))
|
||||
|
||||
/* (T *) if E is nonzero, (void *) otherwise. */
|
||||
#define type_if(T, E) type_if_not(T, !(E))
|
||||
|
||||
/* Combine pointer types, all but one (void *). */
|
||||
#define type_comb2(T1, T2) __typeof__(0 ? (T1)0 : (T2)0)
|
||||
#define type_comb3(T1, T2, T3) type_comb2(T1, type_comb2(T2, T3))
|
||||
#define type_comb4(T1, T2, T3, T4) \
|
||||
type_comb2(T1, type_comb2(T2, type_comb2(T3, T4)))
|
||||
#define type_comb6(T1, T2, T3, T4, T5, T6) \
|
||||
type_comb2(T1, \
|
||||
type_comb2(T2, \
|
||||
type_comb2(T3, \
|
||||
type_comb2(T4, \
|
||||
type_comb2(T5, T6)))))
|
||||
|
||||
/* (T1 *) if E1, otherwise (T2 *) if E2. */
|
||||
#define first_of2p(T1, E1, T2, E2) type_comb2(type_if(T1, (E1)), \
|
||||
type_if(T2, (!(E1) && (E2))))
|
||||
/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3. */
|
||||
#define first_of3p(T1, E1, T2, E2, T3, E3) \
|
||||
type_comb3(type_if(T1, (E1)), \
|
||||
type_if(T2, (!(E1) && (E2))), \
|
||||
type_if(T3, (!(E1) && !(E2) && (E3))))
|
||||
/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3, otherwise
|
||||
(T4 *) if E4. */
|
||||
#define first_of4p(T1, E1, T2, E2, T3, E3, T4, E4) \
|
||||
type_comb4(type_if(T1, (E1)), \
|
||||
type_if(T2, (!(E1) && (E2))), \
|
||||
type_if(T3, (!(E1) && !(E2) && (E3))), \
|
||||
type_if(T4, (!(E1) && !(E2) && !(E3) && (E4))))
|
||||
/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3, otherwise
|
||||
(T4 *) if E4, otherwise (T5 *) if E5, otherwise (T6 *) if E6. */
|
||||
#define first_of6p(T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6) \
|
||||
type_comb6(type_if(T1, (E1)), \
|
||||
type_if(T2, (!(E1) && (E2))), \
|
||||
type_if(T3, (!(E1) && !(E2) && (E3))), \
|
||||
type_if(T4, (!(E1) && !(E2) && !(E3) && (E4))), \
|
||||
type_if(T5, (!(E1) && !(E2) && !(E3) && !(E4) && (E5))), \
|
||||
type_if(T6, (!(E1) && !(E2) && !(E3) \
|
||||
&& !(E4) && !(E5) && (E6))))
|
||||
|
||||
/* Likewise, but return the original type rather than a pointer type. */
|
||||
#define first_of2(T1, E1, T2, E2) \
|
||||
__typeof__(*((first_of2p(T1, (E1), T2, (E2)))0))
|
||||
#define first_of3(T1, E1, T2, E2, T3, E3) \
|
||||
__typeof__(*((first_of3p(T1, (E1), T2, (E2), T3, (E3)))0))
|
||||
#define first_of4(T1, E1, T2, E2, T3, E3, T4, E4) \
|
||||
__typeof__(*((first_of4p(T1, (E1), T2, (E2), T3, (E3), T4, (E4)))0))
|
||||
#define first_of6(T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6) \
|
||||
__typeof__(*((first_of6p(T1, (E1), T2, (E2), T3, (E3), \
|
||||
T4, (E4), T5, (E5), T6, (E6)))0))
|
||||
|
||||
/* Types of constants according to the C99 rules. */
|
||||
#define C99_UNSUF_DEC_TYPE(C) \
|
||||
first_of3(int, (C) <= INT_MAX, \
|
||||
long int, (C) <= LONG_MAX, \
|
||||
long long int, (C) <= LLONG_MAX)
|
||||
#define C99_UNSUF_OCTHEX_TYPE(C) \
|
||||
first_of6(int, (C) <= INT_MAX, \
|
||||
unsigned int, (C) <= UINT_MAX, \
|
||||
long int, (C) <= LONG_MAX, \
|
||||
unsigned long int, (C) <= ULONG_MAX, \
|
||||
long long int, (C) <= LLONG_MAX, \
|
||||
unsigned long long int, (C) <= ULLONG_MAX)
|
||||
#define C99_SUFu_TYPE(C) \
|
||||
first_of3(unsigned int, (C) <= UINT_MAX, \
|
||||
unsigned long int, (C) <= ULONG_MAX, \
|
||||
unsigned long long int, (C) <= ULLONG_MAX)
|
||||
#define C99_SUFl_DEC_TYPE(C) \
|
||||
first_of2(long int, (C) <= LONG_MAX, \
|
||||
long long int, (C) <= LLONG_MAX)
|
||||
#define C99_SUFl_OCTHEX_TYPE(C) \
|
||||
first_of4(long int, (C) <= LONG_MAX, \
|
||||
unsigned long int, (C) <= ULONG_MAX, \
|
||||
long long int, (C) <= LLONG_MAX, \
|
||||
unsigned long long int, (C) <= ULLONG_MAX)
|
||||
#define C99_SUFul_TYPE(C) \
|
||||
first_of2(unsigned long int, (C) <= ULONG_MAX, \
|
||||
unsigned long long int, (C) <= ULLONG_MAX)
|
||||
#define C99_SUFll_OCTHEX_TYPE(C) \
|
||||
first_of2(long long int, (C) <= LLONG_MAX, \
|
||||
unsigned long long int, (C) <= ULLONG_MAX)
|
||||
|
||||
/* Checks that constants have correct type. */
|
||||
#define CHECK_UNSUF_DEC_TYPE(C) ASSERT_CONST_TYPE((C), C99_UNSUF_DEC_TYPE((C)))
|
||||
#define CHECK_UNSUF_OCTHEX_TYPE(C) \
|
||||
ASSERT_CONST_TYPE((C), C99_UNSUF_OCTHEX_TYPE((C)))
|
||||
#define CHECK_SUFu_TYPE(C) ASSERT_CONST_TYPE((C), C99_SUFu_TYPE((C)))
|
||||
#define CHECK_SUFl_DEC_TYPE(C) ASSERT_CONST_TYPE((C), C99_SUFl_DEC_TYPE((C)))
|
||||
#define CHECK_SUFl_OCTHEX_TYPE(C) \
|
||||
ASSERT_CONST_TYPE((C), C99_SUFl_OCTHEX_TYPE((C)))
|
||||
#define CHECK_SUFul_TYPE(C) ASSERT_CONST_TYPE((C), C99_SUFul_TYPE((C)))
|
||||
#define CHECK_SUFll_DEC_TYPE(C) ASSERT_CONST_TYPE((C), long long int)
|
||||
#define CHECK_SUFll_OCTHEX_TYPE(C) \
|
||||
ASSERT_CONST_TYPE((C), C99_SUFll_OCTHEX_TYPE((C)))
|
||||
#define CHECK_SUFull_TYPE(C) ASSERT_CONST_TYPE((C), unsigned long long int)
|
||||
|
||||
/* Check a decimal value, with all suffixes. */
|
||||
#define CHECK_DEC_CONST(C) \
|
||||
CHECK_UNSUF_DEC_TYPE(C); \
|
||||
CHECK_SUFu_TYPE(C##u); \
|
||||
CHECK_SUFu_TYPE(C##U); \
|
||||
CHECK_SUFl_DEC_TYPE(C##l); \
|
||||
CHECK_SUFl_DEC_TYPE(C##L); \
|
||||
CHECK_SUFul_TYPE(C##ul); \
|
||||
CHECK_SUFul_TYPE(C##uL); \
|
||||
CHECK_SUFul_TYPE(C##Ul); \
|
||||
CHECK_SUFul_TYPE(C##UL); \
|
||||
CHECK_SUFll_DEC_TYPE(C##ll); \
|
||||
CHECK_SUFll_DEC_TYPE(C##LL); \
|
||||
CHECK_SUFull_TYPE(C##ull); \
|
||||
CHECK_SUFull_TYPE(C##uLL); \
|
||||
CHECK_SUFull_TYPE(C##Ull); \
|
||||
CHECK_SUFull_TYPE(C##ULL);
|
||||
|
||||
/* Check an octal or hexadecimal value, with all suffixes. */
|
||||
#define CHECK_OCTHEX_CONST(C) \
|
||||
CHECK_UNSUF_OCTHEX_TYPE(C); \
|
||||
CHECK_SUFu_TYPE(C##u); \
|
||||
CHECK_SUFu_TYPE(C##U); \
|
||||
CHECK_SUFl_OCTHEX_TYPE(C##l); \
|
||||
CHECK_SUFl_OCTHEX_TYPE(C##L); \
|
||||
CHECK_SUFul_TYPE(C##ul); \
|
||||
CHECK_SUFul_TYPE(C##uL); \
|
||||
CHECK_SUFul_TYPE(C##Ul); \
|
||||
CHECK_SUFul_TYPE(C##UL); \
|
||||
CHECK_SUFll_OCTHEX_TYPE(C##ll); \
|
||||
CHECK_SUFll_OCTHEX_TYPE(C##LL); \
|
||||
CHECK_SUFull_TYPE(C##ull); \
|
||||
CHECK_SUFull_TYPE(C##uLL); \
|
||||
CHECK_SUFull_TYPE(C##Ull); \
|
||||
CHECK_SUFull_TYPE(C##ULL);
|
||||
|
||||
#define CHECK_OCT_CONST(C) CHECK_OCTHEX_CONST(C)
|
||||
#define CHECK_HEX_CONST(C) \
|
||||
CHECK_OCTHEX_CONST(0x##C); \
|
||||
CHECK_OCTHEX_CONST(0X##C);
|
||||
|
||||
/* True iff "long long" is at least B bits. This presumes that (B-2)/3 is at
|
||||
most 63. */
|
||||
#define LLONG_AT_LEAST(B) \
|
||||
(LLONG_MAX >> ((B)-2)/3 >> ((B)-2)/3 \
|
||||
>> ((B)-2 - ((B)-2)/3 - ((B)-2)/3))
|
||||
|
||||
#define LLONG_HAS_BITS(B) (LLONG_AT_LEAST((B)) && !LLONG_AT_LEAST((B) + 1))
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
/* Decimal. */
|
||||
/* Check all 2^n and 2^n - 1 up to 2^71 - 1. */
|
||||
CHECK_DEC_CONST(1);
|
||||
CHECK_DEC_CONST(2);
|
||||
CHECK_DEC_CONST(3);
|
||||
CHECK_DEC_CONST(4);
|
||||
CHECK_DEC_CONST(7);
|
||||
CHECK_DEC_CONST(8);
|
||||
CHECK_DEC_CONST(15);
|
||||
CHECK_DEC_CONST(16);
|
||||
CHECK_DEC_CONST(31);
|
||||
CHECK_DEC_CONST(32);
|
||||
CHECK_DEC_CONST(63);
|
||||
CHECK_DEC_CONST(64);
|
||||
CHECK_DEC_CONST(127);
|
||||
CHECK_DEC_CONST(128);
|
||||
CHECK_DEC_CONST(255);
|
||||
CHECK_DEC_CONST(256);
|
||||
CHECK_DEC_CONST(511);
|
||||
CHECK_DEC_CONST(512);
|
||||
CHECK_DEC_CONST(1023);
|
||||
CHECK_DEC_CONST(1024);
|
||||
CHECK_DEC_CONST(2047);
|
||||
CHECK_DEC_CONST(2048);
|
||||
CHECK_DEC_CONST(4095);
|
||||
CHECK_DEC_CONST(4096);
|
||||
CHECK_DEC_CONST(8191);
|
||||
CHECK_DEC_CONST(8192);
|
||||
CHECK_DEC_CONST(16383);
|
||||
CHECK_DEC_CONST(16384);
|
||||
CHECK_DEC_CONST(32767);
|
||||
CHECK_DEC_CONST(32768);
|
||||
CHECK_DEC_CONST(65535);
|
||||
CHECK_DEC_CONST(65536);
|
||||
CHECK_DEC_CONST(131071);
|
||||
CHECK_DEC_CONST(131072);
|
||||
CHECK_DEC_CONST(262143);
|
||||
CHECK_DEC_CONST(262144);
|
||||
CHECK_DEC_CONST(524287);
|
||||
CHECK_DEC_CONST(524288);
|
||||
CHECK_DEC_CONST(1048575);
|
||||
CHECK_DEC_CONST(1048576);
|
||||
CHECK_DEC_CONST(2097151);
|
||||
CHECK_DEC_CONST(2097152);
|
||||
CHECK_DEC_CONST(4194303);
|
||||
CHECK_DEC_CONST(4194304);
|
||||
CHECK_DEC_CONST(8388607);
|
||||
CHECK_DEC_CONST(8388608);
|
||||
CHECK_DEC_CONST(16777215);
|
||||
CHECK_DEC_CONST(16777216);
|
||||
CHECK_DEC_CONST(33554431);
|
||||
CHECK_DEC_CONST(33554432);
|
||||
CHECK_DEC_CONST(67108863);
|
||||
CHECK_DEC_CONST(67108864);
|
||||
CHECK_DEC_CONST(134217727);
|
||||
CHECK_DEC_CONST(134217728);
|
||||
CHECK_DEC_CONST(268435455);
|
||||
CHECK_DEC_CONST(268435456);
|
||||
CHECK_DEC_CONST(536870911);
|
||||
CHECK_DEC_CONST(536870912);
|
||||
CHECK_DEC_CONST(1073741823);
|
||||
CHECK_DEC_CONST(1073741824);
|
||||
CHECK_DEC_CONST(2147483647);
|
||||
CHECK_DEC_CONST(2147483648);
|
||||
CHECK_DEC_CONST(4294967295);
|
||||
CHECK_DEC_CONST(4294967296);
|
||||
CHECK_DEC_CONST(8589934591);
|
||||
CHECK_DEC_CONST(8589934592);
|
||||
CHECK_DEC_CONST(17179869183);
|
||||
CHECK_DEC_CONST(17179869184);
|
||||
CHECK_DEC_CONST(34359738367);
|
||||
CHECK_DEC_CONST(34359738368);
|
||||
CHECK_DEC_CONST(68719476735);
|
||||
CHECK_DEC_CONST(68719476736);
|
||||
CHECK_DEC_CONST(137438953471);
|
||||
CHECK_DEC_CONST(137438953472);
|
||||
CHECK_DEC_CONST(274877906943);
|
||||
CHECK_DEC_CONST(274877906944);
|
||||
CHECK_DEC_CONST(549755813887);
|
||||
CHECK_DEC_CONST(549755813888);
|
||||
CHECK_DEC_CONST(1099511627775);
|
||||
CHECK_DEC_CONST(1099511627776);
|
||||
CHECK_DEC_CONST(2199023255551);
|
||||
CHECK_DEC_CONST(2199023255552);
|
||||
CHECK_DEC_CONST(4398046511103);
|
||||
CHECK_DEC_CONST(4398046511104);
|
||||
CHECK_DEC_CONST(8796093022207);
|
||||
CHECK_DEC_CONST(8796093022208);
|
||||
CHECK_DEC_CONST(17592186044415);
|
||||
CHECK_DEC_CONST(17592186044416);
|
||||
CHECK_DEC_CONST(35184372088831);
|
||||
CHECK_DEC_CONST(35184372088832);
|
||||
CHECK_DEC_CONST(70368744177663);
|
||||
CHECK_DEC_CONST(70368744177664);
|
||||
CHECK_DEC_CONST(140737488355327);
|
||||
CHECK_DEC_CONST(140737488355328);
|
||||
CHECK_DEC_CONST(281474976710655);
|
||||
CHECK_DEC_CONST(281474976710656);
|
||||
CHECK_DEC_CONST(562949953421311);
|
||||
CHECK_DEC_CONST(562949953421312);
|
||||
CHECK_DEC_CONST(1125899906842623);
|
||||
CHECK_DEC_CONST(1125899906842624);
|
||||
CHECK_DEC_CONST(2251799813685247);
|
||||
CHECK_DEC_CONST(2251799813685248);
|
||||
CHECK_DEC_CONST(4503599627370495);
|
||||
CHECK_DEC_CONST(4503599627370496);
|
||||
CHECK_DEC_CONST(9007199254740991);
|
||||
CHECK_DEC_CONST(9007199254740992);
|
||||
CHECK_DEC_CONST(18014398509481983);
|
||||
CHECK_DEC_CONST(18014398509481984);
|
||||
CHECK_DEC_CONST(36028797018963967);
|
||||
CHECK_DEC_CONST(36028797018963968);
|
||||
CHECK_DEC_CONST(72057594037927935);
|
||||
CHECK_DEC_CONST(72057594037927936);
|
||||
CHECK_DEC_CONST(144115188075855871);
|
||||
CHECK_DEC_CONST(144115188075855872);
|
||||
CHECK_DEC_CONST(288230376151711743);
|
||||
CHECK_DEC_CONST(288230376151711744);
|
||||
CHECK_DEC_CONST(576460752303423487);
|
||||
CHECK_DEC_CONST(576460752303423488);
|
||||
CHECK_DEC_CONST(1152921504606846975);
|
||||
CHECK_DEC_CONST(1152921504606846976);
|
||||
CHECK_DEC_CONST(2305843009213693951);
|
||||
CHECK_DEC_CONST(2305843009213693952);
|
||||
CHECK_DEC_CONST(4611686018427387903);
|
||||
CHECK_DEC_CONST(4611686018427387904);
|
||||
CHECK_DEC_CONST(9223372036854775807);
|
||||
#if LLONG_AT_LEAST(65)
|
||||
CHECK_DEC_CONST(9223372036854775808);
|
||||
CHECK_DEC_CONST(18446744073709551615);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(66)
|
||||
CHECK_DEC_CONST(18446744073709551616);
|
||||
CHECK_DEC_CONST(36893488147419103231);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(67)
|
||||
CHECK_DEC_CONST(36893488147419103232);
|
||||
CHECK_DEC_CONST(73786976294838206463);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(68)
|
||||
CHECK_DEC_CONST(73786976294838206464);
|
||||
CHECK_DEC_CONST(147573952589676412927);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(69)
|
||||
CHECK_DEC_CONST(147573952589676412928);
|
||||
CHECK_DEC_CONST(295147905179352825855);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(70)
|
||||
CHECK_DEC_CONST(295147905179352825856);
|
||||
CHECK_DEC_CONST(590295810358705651711);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(71)
|
||||
CHECK_DEC_CONST(590295810358705651712);
|
||||
CHECK_DEC_CONST(1180591620717411303423);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(72)
|
||||
CHECK_DEC_CONST(1180591620717411303424);
|
||||
CHECK_DEC_CONST(2361183241434822606847);
|
||||
#endif
|
||||
/* Octal and hexadecimal. */
|
||||
/* Check all 2^n and 2^n - 1 up to 2^72 - 1. */
|
||||
CHECK_OCT_CONST(0);
|
||||
CHECK_HEX_CONST(0);
|
||||
CHECK_OCT_CONST(01);
|
||||
CHECK_HEX_CONST(1);
|
||||
CHECK_OCT_CONST(02);
|
||||
CHECK_HEX_CONST(2);
|
||||
CHECK_OCT_CONST(03);
|
||||
CHECK_HEX_CONST(3);
|
||||
CHECK_OCT_CONST(04);
|
||||
CHECK_HEX_CONST(4);
|
||||
CHECK_OCT_CONST(07);
|
||||
CHECK_HEX_CONST(7);
|
||||
CHECK_OCT_CONST(010);
|
||||
CHECK_HEX_CONST(8);
|
||||
CHECK_OCT_CONST(017);
|
||||
CHECK_HEX_CONST(f);
|
||||
CHECK_OCT_CONST(020);
|
||||
CHECK_HEX_CONST(10);
|
||||
CHECK_OCT_CONST(037);
|
||||
CHECK_HEX_CONST(1f);
|
||||
CHECK_OCT_CONST(040);
|
||||
CHECK_HEX_CONST(20);
|
||||
CHECK_OCT_CONST(077);
|
||||
CHECK_HEX_CONST(3f);
|
||||
CHECK_OCT_CONST(0100);
|
||||
CHECK_HEX_CONST(40);
|
||||
CHECK_OCT_CONST(0177);
|
||||
CHECK_HEX_CONST(7f);
|
||||
CHECK_OCT_CONST(0200);
|
||||
CHECK_HEX_CONST(80);
|
||||
CHECK_OCT_CONST(0377);
|
||||
CHECK_HEX_CONST(ff);
|
||||
CHECK_OCT_CONST(0400);
|
||||
CHECK_HEX_CONST(100);
|
||||
CHECK_OCT_CONST(0777);
|
||||
CHECK_HEX_CONST(1ff);
|
||||
CHECK_OCT_CONST(01000);
|
||||
CHECK_HEX_CONST(200);
|
||||
CHECK_OCT_CONST(01777);
|
||||
CHECK_HEX_CONST(3ff);
|
||||
CHECK_OCT_CONST(02000);
|
||||
CHECK_HEX_CONST(400);
|
||||
CHECK_OCT_CONST(03777);
|
||||
CHECK_HEX_CONST(7ff);
|
||||
CHECK_OCT_CONST(04000);
|
||||
CHECK_HEX_CONST(800);
|
||||
CHECK_OCT_CONST(07777);
|
||||
CHECK_HEX_CONST(fff);
|
||||
CHECK_OCT_CONST(010000);
|
||||
CHECK_HEX_CONST(1000);
|
||||
CHECK_OCT_CONST(017777);
|
||||
CHECK_HEX_CONST(1fff);
|
||||
CHECK_OCT_CONST(020000);
|
||||
CHECK_HEX_CONST(2000);
|
||||
CHECK_OCT_CONST(037777);
|
||||
CHECK_HEX_CONST(3fff);
|
||||
CHECK_OCT_CONST(040000);
|
||||
CHECK_HEX_CONST(4000);
|
||||
CHECK_OCT_CONST(077777);
|
||||
CHECK_HEX_CONST(7fff);
|
||||
CHECK_OCT_CONST(0100000);
|
||||
CHECK_HEX_CONST(8000);
|
||||
CHECK_OCT_CONST(0177777);
|
||||
CHECK_HEX_CONST(ffff);
|
||||
CHECK_OCT_CONST(0200000);
|
||||
CHECK_HEX_CONST(10000);
|
||||
CHECK_OCT_CONST(0377777);
|
||||
CHECK_HEX_CONST(1ffff);
|
||||
CHECK_OCT_CONST(0400000);
|
||||
CHECK_HEX_CONST(20000);
|
||||
CHECK_OCT_CONST(0777777);
|
||||
CHECK_HEX_CONST(3ffff);
|
||||
CHECK_OCT_CONST(01000000);
|
||||
CHECK_HEX_CONST(40000);
|
||||
CHECK_OCT_CONST(01777777);
|
||||
CHECK_HEX_CONST(7ffff);
|
||||
CHECK_OCT_CONST(02000000);
|
||||
CHECK_HEX_CONST(80000);
|
||||
CHECK_OCT_CONST(03777777);
|
||||
CHECK_HEX_CONST(fffff);
|
||||
CHECK_OCT_CONST(04000000);
|
||||
CHECK_HEX_CONST(100000);
|
||||
CHECK_OCT_CONST(07777777);
|
||||
CHECK_HEX_CONST(1fffff);
|
||||
CHECK_OCT_CONST(010000000);
|
||||
CHECK_HEX_CONST(200000);
|
||||
CHECK_OCT_CONST(017777777);
|
||||
CHECK_HEX_CONST(3fffff);
|
||||
CHECK_OCT_CONST(020000000);
|
||||
CHECK_HEX_CONST(400000);
|
||||
CHECK_OCT_CONST(037777777);
|
||||
CHECK_HEX_CONST(7fffff);
|
||||
CHECK_OCT_CONST(040000000);
|
||||
CHECK_HEX_CONST(800000);
|
||||
CHECK_OCT_CONST(077777777);
|
||||
CHECK_HEX_CONST(ffffff);
|
||||
CHECK_OCT_CONST(0100000000);
|
||||
CHECK_HEX_CONST(1000000);
|
||||
CHECK_OCT_CONST(0177777777);
|
||||
CHECK_HEX_CONST(1ffffff);
|
||||
CHECK_OCT_CONST(0200000000);
|
||||
CHECK_HEX_CONST(2000000);
|
||||
CHECK_OCT_CONST(0377777777);
|
||||
CHECK_HEX_CONST(3ffffff);
|
||||
CHECK_OCT_CONST(0400000000);
|
||||
CHECK_HEX_CONST(4000000);
|
||||
CHECK_OCT_CONST(0777777777);
|
||||
CHECK_HEX_CONST(7ffffff);
|
||||
CHECK_OCT_CONST(01000000000);
|
||||
CHECK_HEX_CONST(8000000);
|
||||
CHECK_OCT_CONST(01777777777);
|
||||
CHECK_HEX_CONST(fffffff);
|
||||
CHECK_OCT_CONST(02000000000);
|
||||
CHECK_HEX_CONST(10000000);
|
||||
CHECK_OCT_CONST(03777777777);
|
||||
CHECK_HEX_CONST(1fffffff);
|
||||
CHECK_OCT_CONST(04000000000);
|
||||
CHECK_HEX_CONST(20000000);
|
||||
CHECK_OCT_CONST(07777777777);
|
||||
CHECK_HEX_CONST(3fffffff);
|
||||
CHECK_OCT_CONST(010000000000);
|
||||
CHECK_HEX_CONST(40000000);
|
||||
CHECK_OCT_CONST(017777777777);
|
||||
CHECK_HEX_CONST(7fffffff);
|
||||
CHECK_OCT_CONST(020000000000);
|
||||
CHECK_HEX_CONST(80000000);
|
||||
CHECK_OCT_CONST(037777777777);
|
||||
CHECK_HEX_CONST(ffffffff);
|
||||
CHECK_OCT_CONST(040000000000);
|
||||
CHECK_HEX_CONST(100000000);
|
||||
CHECK_OCT_CONST(077777777777);
|
||||
CHECK_HEX_CONST(1ffffffff);
|
||||
CHECK_OCT_CONST(0100000000000);
|
||||
CHECK_HEX_CONST(200000000);
|
||||
CHECK_OCT_CONST(0177777777777);
|
||||
CHECK_HEX_CONST(3ffffffff);
|
||||
CHECK_OCT_CONST(0200000000000);
|
||||
CHECK_HEX_CONST(400000000);
|
||||
CHECK_OCT_CONST(0377777777777);
|
||||
CHECK_HEX_CONST(7ffffffff);
|
||||
CHECK_OCT_CONST(0400000000000);
|
||||
CHECK_HEX_CONST(800000000);
|
||||
CHECK_OCT_CONST(0777777777777);
|
||||
CHECK_HEX_CONST(fffffffff);
|
||||
CHECK_OCT_CONST(01000000000000);
|
||||
CHECK_HEX_CONST(1000000000);
|
||||
CHECK_OCT_CONST(01777777777777);
|
||||
CHECK_HEX_CONST(1fffffffff);
|
||||
CHECK_OCT_CONST(02000000000000);
|
||||
CHECK_HEX_CONST(2000000000);
|
||||
CHECK_OCT_CONST(03777777777777);
|
||||
CHECK_HEX_CONST(3fffffffff);
|
||||
CHECK_OCT_CONST(04000000000000);
|
||||
CHECK_HEX_CONST(4000000000);
|
||||
CHECK_OCT_CONST(07777777777777);
|
||||
CHECK_HEX_CONST(7fffffffff);
|
||||
CHECK_OCT_CONST(010000000000000);
|
||||
CHECK_HEX_CONST(8000000000);
|
||||
CHECK_OCT_CONST(017777777777777);
|
||||
CHECK_HEX_CONST(ffffffffff);
|
||||
CHECK_OCT_CONST(020000000000000);
|
||||
CHECK_HEX_CONST(10000000000);
|
||||
CHECK_OCT_CONST(037777777777777);
|
||||
CHECK_HEX_CONST(1ffffffffff);
|
||||
CHECK_OCT_CONST(040000000000000);
|
||||
CHECK_HEX_CONST(20000000000);
|
||||
CHECK_OCT_CONST(077777777777777);
|
||||
CHECK_HEX_CONST(3ffffffffff);
|
||||
CHECK_OCT_CONST(0100000000000000);
|
||||
CHECK_HEX_CONST(40000000000);
|
||||
CHECK_OCT_CONST(0177777777777777);
|
||||
CHECK_HEX_CONST(7ffffffffff);
|
||||
CHECK_OCT_CONST(0200000000000000);
|
||||
CHECK_HEX_CONST(80000000000);
|
||||
CHECK_OCT_CONST(0377777777777777);
|
||||
CHECK_HEX_CONST(fffffffffff);
|
||||
CHECK_OCT_CONST(0400000000000000);
|
||||
CHECK_HEX_CONST(100000000000);
|
||||
CHECK_OCT_CONST(0777777777777777);
|
||||
CHECK_HEX_CONST(1fffffffffff);
|
||||
CHECK_OCT_CONST(01000000000000000);
|
||||
CHECK_HEX_CONST(200000000000);
|
||||
CHECK_OCT_CONST(01777777777777777);
|
||||
CHECK_HEX_CONST(3fffffffffff);
|
||||
CHECK_OCT_CONST(02000000000000000);
|
||||
CHECK_HEX_CONST(400000000000);
|
||||
CHECK_OCT_CONST(03777777777777777);
|
||||
CHECK_HEX_CONST(7fffffffffff);
|
||||
CHECK_OCT_CONST(04000000000000000);
|
||||
CHECK_HEX_CONST(800000000000);
|
||||
CHECK_OCT_CONST(07777777777777777);
|
||||
CHECK_HEX_CONST(ffffffffffff);
|
||||
CHECK_OCT_CONST(010000000000000000);
|
||||
CHECK_HEX_CONST(1000000000000);
|
||||
CHECK_OCT_CONST(017777777777777777);
|
||||
CHECK_HEX_CONST(1ffffffffffff);
|
||||
CHECK_OCT_CONST(020000000000000000);
|
||||
CHECK_HEX_CONST(2000000000000);
|
||||
CHECK_OCT_CONST(037777777777777777);
|
||||
CHECK_HEX_CONST(3ffffffffffff);
|
||||
CHECK_OCT_CONST(040000000000000000);
|
||||
CHECK_HEX_CONST(4000000000000);
|
||||
CHECK_OCT_CONST(077777777777777777);
|
||||
CHECK_HEX_CONST(7ffffffffffff);
|
||||
CHECK_OCT_CONST(0100000000000000000);
|
||||
CHECK_HEX_CONST(8000000000000);
|
||||
CHECK_OCT_CONST(0177777777777777777);
|
||||
CHECK_HEX_CONST(fffffffffffff);
|
||||
CHECK_OCT_CONST(0200000000000000000);
|
||||
CHECK_HEX_CONST(10000000000000);
|
||||
CHECK_OCT_CONST(0377777777777777777);
|
||||
CHECK_HEX_CONST(1fffffffffffff);
|
||||
CHECK_OCT_CONST(0400000000000000000);
|
||||
CHECK_HEX_CONST(20000000000000);
|
||||
CHECK_OCT_CONST(0777777777777777777);
|
||||
CHECK_HEX_CONST(3fffffffffffff);
|
||||
CHECK_OCT_CONST(01000000000000000000);
|
||||
CHECK_HEX_CONST(40000000000000);
|
||||
CHECK_OCT_CONST(01777777777777777777);
|
||||
CHECK_HEX_CONST(7fffffffffffff);
|
||||
CHECK_OCT_CONST(02000000000000000000);
|
||||
CHECK_HEX_CONST(80000000000000);
|
||||
CHECK_OCT_CONST(03777777777777777777);
|
||||
CHECK_HEX_CONST(ffffffffffffff);
|
||||
CHECK_OCT_CONST(04000000000000000000);
|
||||
CHECK_HEX_CONST(100000000000000);
|
||||
CHECK_OCT_CONST(07777777777777777777);
|
||||
CHECK_HEX_CONST(1ffffffffffffff);
|
||||
CHECK_OCT_CONST(010000000000000000000);
|
||||
CHECK_HEX_CONST(200000000000000);
|
||||
CHECK_OCT_CONST(017777777777777777777);
|
||||
CHECK_HEX_CONST(3ffffffffffffff);
|
||||
CHECK_OCT_CONST(020000000000000000000);
|
||||
CHECK_HEX_CONST(400000000000000);
|
||||
CHECK_OCT_CONST(037777777777777777777);
|
||||
CHECK_HEX_CONST(7ffffffffffffff);
|
||||
CHECK_OCT_CONST(040000000000000000000);
|
||||
CHECK_HEX_CONST(800000000000000);
|
||||
CHECK_OCT_CONST(077777777777777777777);
|
||||
CHECK_HEX_CONST(fffffffffffffff);
|
||||
CHECK_OCT_CONST(0100000000000000000000);
|
||||
CHECK_HEX_CONST(1000000000000000);
|
||||
CHECK_OCT_CONST(0177777777777777777777);
|
||||
CHECK_HEX_CONST(1fffffffffffffff);
|
||||
CHECK_OCT_CONST(0200000000000000000000);
|
||||
CHECK_HEX_CONST(2000000000000000);
|
||||
CHECK_OCT_CONST(0377777777777777777777);
|
||||
CHECK_HEX_CONST(3fffffffffffffff);
|
||||
CHECK_OCT_CONST(0400000000000000000000);
|
||||
CHECK_HEX_CONST(4000000000000000);
|
||||
CHECK_OCT_CONST(0777777777777777777777);
|
||||
CHECK_HEX_CONST(7fffffffffffffff);
|
||||
CHECK_OCT_CONST(01000000000000000000000);
|
||||
CHECK_HEX_CONST(8000000000000000);
|
||||
CHECK_OCT_CONST(01777777777777777777777);
|
||||
CHECK_HEX_CONST(ffffffffffffffff);
|
||||
#if LLONG_AT_LEAST(65)
|
||||
CHECK_OCT_CONST(02000000000000000000000);
|
||||
CHECK_HEX_CONST(10000000000000000);
|
||||
CHECK_OCT_CONST(03777777777777777777777);
|
||||
CHECK_HEX_CONST(1ffffffffffffffff);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(66)
|
||||
CHECK_OCT_CONST(04000000000000000000000);
|
||||
CHECK_HEX_CONST(20000000000000000);
|
||||
CHECK_OCT_CONST(07777777777777777777777);
|
||||
CHECK_HEX_CONST(3ffffffffffffffff);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(67)
|
||||
CHECK_OCT_CONST(010000000000000000000000);
|
||||
CHECK_HEX_CONST(40000000000000000);
|
||||
CHECK_OCT_CONST(017777777777777777777777);
|
||||
CHECK_HEX_CONST(7ffffffffffffffff);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(68)
|
||||
CHECK_OCT_CONST(020000000000000000000000);
|
||||
CHECK_HEX_CONST(80000000000000000);
|
||||
CHECK_OCT_CONST(037777777777777777777777);
|
||||
CHECK_HEX_CONST(fffffffffffffffff);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(69)
|
||||
CHECK_OCT_CONST(040000000000000000000000);
|
||||
CHECK_HEX_CONST(100000000000000000);
|
||||
CHECK_OCT_CONST(077777777777777777777777);
|
||||
CHECK_HEX_CONST(1fffffffffffffffff);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(70)
|
||||
CHECK_OCT_CONST(0100000000000000000000000);
|
||||
CHECK_HEX_CONST(200000000000000000);
|
||||
CHECK_OCT_CONST(0177777777777777777777777);
|
||||
CHECK_HEX_CONST(3fffffffffffffffff);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(71)
|
||||
CHECK_OCT_CONST(0200000000000000000000000);
|
||||
CHECK_HEX_CONST(400000000000000000);
|
||||
CHECK_OCT_CONST(0377777777777777777777777);
|
||||
CHECK_HEX_CONST(7fffffffffffffffff);
|
||||
#endif
|
||||
#if LLONG_AT_LEAST(72)
|
||||
CHECK_OCT_CONST(0400000000000000000000000);
|
||||
CHECK_HEX_CONST(800000000000000000);
|
||||
CHECK_OCT_CONST(0777777777777777777777777);
|
||||
CHECK_HEX_CONST(ffffffffffffffffff);
|
||||
#endif
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
//#import<vecLib/vecLib.h>
|
||||
@@ -1,5 +0,0 @@
|
||||
// clang -I/usr/include/c++/4.0.0 -I/usr/include/c++/4.0.0/powerpc-apple-darwin8 -I/usr/include/c++/4.0.0/backward INPUTS/iostream.cc -Eonly
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
// This pounds on macro expansion for performance reasons. This is currently
|
||||
// heavily constrained by darwin's malloc.
|
||||
|
||||
// Function-like macros.
|
||||
#define A0(A, B) A B
|
||||
#define A1(A, B) A0(A,B) A0(A,B) A0(A,B) A0(A,B) A0(A,B) A0(A,B)
|
||||
#define A2(A, B) A1(A,B) A1(A,B) A1(A,B) A1(A,B) A1(A,B) A1(A,B)
|
||||
#define A3(A, B) A2(A,B) A2(A,B) A2(A,B) A2(A,B) A2(A,B) A2(A,B)
|
||||
#define A4(A, B) A3(A,B) A3(A,B) A3(A,B) A3(A,B) A3(A,B) A3(A,B)
|
||||
#define A5(A, B) A4(A,B) A4(A,B) A4(A,B) A4(A,B) A4(A,B) A4(A,B)
|
||||
#define A6(A, B) A5(A,B) A5(A,B) A5(A,B) A5(A,B) A5(A,B) A5(A,B)
|
||||
#define A7(A, B) A6(A,B) A6(A,B) A6(A,B) A6(A,B) A6(A,B) A6(A,B)
|
||||
#define A8(A, B) A7(A,B) A7(A,B) A7(A,B) A7(A,B) A7(A,B) A7(A,B)
|
||||
|
||||
A8(a, b)
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
// This pounds on macro expansion for performance reasons. This is currently
|
||||
// heavily constrained by darwin's malloc.
|
||||
|
||||
// Object-like expansions
|
||||
#define A0 a b
|
||||
#define A1 A0 A0 A0 A0 A0 A0
|
||||
#define A2 A1 A1 A1 A1 A1 A1
|
||||
#define A3 A2 A2 A2 A2 A2 A2
|
||||
#define A4 A3 A3 A3 A3 A3 A3
|
||||
#define A5 A4 A4 A4 A4 A4 A4
|
||||
#define A6 A5 A5 A5 A5 A5 A5
|
||||
#define A7 A6 A6 A6 A6 A6 A6
|
||||
#define A8 A7 A7 A7 A7 A7 A7
|
||||
|
||||
A8
|
||||
@@ -1,47 +0,0 @@
|
||||
#define __extension__
|
||||
|
||||
#define __stpcpy(dest, src) (__extension__ (__builtin_constant_p (src) ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 ? __stpcpy_small (dest, __stpcpy_args (src), strlen (src) + 1) : ((char *) __mempcpy (dest, src, strlen (src) + 1) - 1)) : __stpcpy (dest, src)))
|
||||
#define stpcpy(dest, src) __stpcpy (dest, src)
|
||||
#define __stpcpy_args(src) __extension__ __STRING2_SMALL_GET16 (src, 0), __extension__ __STRING2_SMALL_GET16 (src, 4), __extension__ __STRING2_SMALL_GET32 (src, 0), __extension__ __STRING2_SMALL_GET32 (src, 4)
|
||||
|
||||
#define __mempcpy(dest, src, n) (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) && __string2_1bptr_p (src) && n <= 8 ? __mempcpy_small (dest, __mempcpy_args (src), n) : __mempcpy (dest, src, n)))
|
||||
#define mempcpy(dest, src, n) __mempcpy (dest, src, n)
|
||||
#define __mempcpy_args(src) ((char *) (src))[0], ((char *) (src))[2], ((char *) (src))[4], ((char *) (src))[6], __extension__ __STRING2_SMALL_GET16 (src, 0), __extension__ __STRING2_SMALL_GET16 (src, 4), __extension__ __STRING2_SMALL_GET32 (src, 0), __extension__ __STRING2_SMALL_GET32 (src, 4)
|
||||
|
||||
#define __STRING2_SMALL_GET16(src, idx) (((__const unsigned char *) (__const char *) (src))[idx + 1] << 8 | ((__const unsigned char *) (__const char *) (src))[idx])
|
||||
|
||||
#define __STRING2_SMALL_GET32(src, idx) (((((__const unsigned char *) (__const char *) (src))[idx + 3] << 8 | ((__const unsigned char *) (__const char *) (src))[idx + 2]) << 8 | ((__const unsigned char *) (__const char *) (src))[idx + 1]) << 8 | ((__const unsigned char *) (__const char *) (src))[idx])
|
||||
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
|
||||
@@ -1,49 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Clang Installation Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
These instructions describe how to build and install Clang.
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Step 1: Organization
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Clang is designed to be built as part of an LLVM build. Assuming that the LLVM
|
||||
source code is located at $LLVM_SRC_ROOT, then the clang source code should be
|
||||
installed as:
|
||||
|
||||
$LLVM_SRC_ROOT/tools/clang
|
||||
|
||||
The directory is not required to be called clang, but doing so will allow the
|
||||
LLVM build system to automatically recognize it and build it along with LLVM.
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Step 2: Configure and Build LLVM
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Configure and build your copy of LLVM (see $LLVM_SRC_ROOT/GettingStarted.html
|
||||
for more information).
|
||||
|
||||
Assuming you installed clang at $LLVM_SRC_ROOT/tools/clang then Clang will
|
||||
automatically be built with LLVM. Otherwise, run 'make' in the Clang source
|
||||
directory to build Clang.
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Step 3: (Optional) Verify Your Build
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
It is a good idea to run the Clang tests to make sure your build works
|
||||
correctly. From inside the Clang build directory, run 'make test' to run the
|
||||
tests.
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Step 4: Install Clang
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
From inside the Clang build directory, run 'make install' to install the Clang
|
||||
compiler and header files into the prefix directory selected when LLVM was
|
||||
configured.
|
||||
|
||||
The Clang compiler is available as 'clang' and supports a gcc like command line
|
||||
interface. See the man page for clang (installed into $prefix/share/man/man1)
|
||||
for more information.
|
||||
@@ -1,63 +0,0 @@
|
||||
==============================================================================
|
||||
LLVM Release License
|
||||
==============================================================================
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2007-2010 University of Illinois at Urbana-Champaign.
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLVM Team
|
||||
|
||||
University of Illinois at Urbana-Champaign
|
||||
|
||||
http://llvm.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLVM Team, University of Illinois at
|
||||
Urbana-Champaign, nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this Software without specific
|
||||
prior written permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
The LLVM software contains code written by third parties. Such software will
|
||||
have its own individual LICENSE.TXT file in the directory in which it appears.
|
||||
This file will describe the copyrights, license, and restrictions which apply
|
||||
to that code.
|
||||
|
||||
The disclaimer of warranty in the University of Illinois Open Source License
|
||||
applies to all code in the LLVM Distribution, and nothing in any of the
|
||||
other licenses gives permission to use the names of the LLVM Team or the
|
||||
University of Illinois to endorse or promote products derived from this
|
||||
Software.
|
||||
|
||||
The following pieces of software have additional or alternate copyrights,
|
||||
licenses, and/or restrictions:
|
||||
|
||||
Program Directory
|
||||
------- ---------
|
||||
<none yet>
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
##===- Makefile --------------------------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
# If CLANG_LEVEL is not set, then we are the top-level Makefile. Otherwise, we
|
||||
# are being included from a subdirectory makefile.
|
||||
|
||||
ifndef CLANG_LEVEL
|
||||
|
||||
IS_TOP_LEVEL := 1
|
||||
CLANG_LEVEL := .
|
||||
DIRS := include lib tools runtime docs
|
||||
|
||||
PARALLEL_DIRS :=
|
||||
|
||||
ifeq ($(BUILD_EXAMPLES),1)
|
||||
PARALLEL_DIRS += examples
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),libs-only)
|
||||
DIRS := $(filter-out tools docs, $(DIRS))
|
||||
OPTIONAL_DIRS :=
|
||||
endif
|
||||
|
||||
###
|
||||
# Common Makefile code, shared by all Clang Makefiles.
|
||||
|
||||
# Set LLVM source root level.
|
||||
LEVEL := $(CLANG_LEVEL)/../..
|
||||
|
||||
# Include LLVM common makefile.
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
# Set common Clang build flags.
|
||||
CPP.Flags += -I$(PROJ_SRC_DIR)/$(CLANG_LEVEL)/include -I$(PROJ_OBJ_DIR)/$(CLANG_LEVEL)/include
|
||||
ifdef CLANG_VENDOR
|
||||
CPP.Flags += -DCLANG_VENDOR='"$(CLANG_VENDOR) "'
|
||||
endif
|
||||
|
||||
# Disable -fstrict-aliasing. Darwin disables it by default (and LLVM doesn't
|
||||
# work with it enabled with GCC), Clang/llvm-gc don't support it yet, and newer
|
||||
# GCC's have false positive warnings with it on Linux (which prove a pain to
|
||||
# fix). For example:
|
||||
# http://gcc.gnu.org/PR41874
|
||||
# http://gcc.gnu.org/PR41838
|
||||
#
|
||||
# We can revisit this when LLVM/Clang support it.
|
||||
CXX.Flags += -fno-strict-aliasing
|
||||
|
||||
###
|
||||
# Clang Top Level specific stuff.
|
||||
|
||||
ifeq ($(IS_TOP_LEVEL),1)
|
||||
|
||||
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
|
||||
$(RecursiveTargets)::
|
||||
$(Verb) if [ ! -f test/Makefile ]; then \
|
||||
$(MKDIR) test; \
|
||||
$(CP) $(PROJ_SRC_DIR)/test/Makefile test/Makefile; \
|
||||
fi
|
||||
endif
|
||||
|
||||
test::
|
||||
@ $(MAKE) -C test
|
||||
|
||||
report::
|
||||
@ $(MAKE) -C test report
|
||||
|
||||
clean::
|
||||
@ $(MAKE) -C test clean
|
||||
|
||||
libs-only: all
|
||||
|
||||
tags::
|
||||
$(Verb) etags `find . -type f -name '*.h' -or -name '*.cpp' | \
|
||||
grep -v /lib/Headers | grep -v /test/`
|
||||
|
||||
cscope.files:
|
||||
find tools lib include -name '*.cpp' \
|
||||
-or -name '*.def' \
|
||||
-or -name '*.td' \
|
||||
-or -name '*.h' > cscope.files
|
||||
|
||||
.PHONY: test report clean cscope.files
|
||||
|
||||
endif
|
||||
@@ -1,5 +0,0 @@
|
||||
# This file provides information for llvm-top
|
||||
DepModule: llvm
|
||||
ConfigCmd:
|
||||
ConfigTest:
|
||||
BuildCmd:
|
||||
@@ -1,85 +0,0 @@
|
||||
//===---------------------------------------------------------------------===//
|
||||
// Random Notes
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
C90/C99/C++ Comparisons:
|
||||
http://david.tribble.com/text/cdiffs.htm
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
To time GCC preprocessing speed without output, use:
|
||||
"time gcc -MM file"
|
||||
This is similar to -Eonly.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
Creating and using a PTH file for performance measurement (use a release build).
|
||||
|
||||
$ clang -ccc-pch-is-pth -x objective-c-header INPUTS/Cocoa_h.m -o /tmp/tokencache
|
||||
$ clang -cc1 -token-cache /tmp/tokencache INPUTS/Cocoa_h.m
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
C++ Template Instantiation benchmark:
|
||||
http://users.rcn.com/abrahams/instantiation_speed/index.html
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
TODO: File Manager Speedup:
|
||||
|
||||
We currently do a lot of stat'ing for files that don't exist, particularly
|
||||
when lots of -I paths exist (e.g. see the <iostream> example, check for
|
||||
failures in stat in FileManager::getFile). It would be far better to make
|
||||
the following changes:
|
||||
1. FileEntry contains a sys::Path instead of a std::string for Name.
|
||||
2. sys::Path contains timestamp and size, lazily computed. Eliminate from
|
||||
FileEntry.
|
||||
3. File UIDs are created on request, not when files are opened.
|
||||
These changes make it possible to efficiently have FileEntry objects for
|
||||
files that exist on the file system, but have not been used yet.
|
||||
|
||||
Once this is done:
|
||||
1. DirectoryEntry gets a boolean value "has read entries". When false, not
|
||||
all entries in the directory are in the file mgr, when true, they are.
|
||||
2. Instead of stat'ing the file in FileManager::getFile, check to see if
|
||||
the dir has been read. If so, fail immediately, if not, read the dir,
|
||||
then retry.
|
||||
3. Reading the dir uses the getdirentries syscall, creating an FileEntry
|
||||
for all files found.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
// Specifying targets: -triple and -arch
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
The clang supports "-triple" and "-arch" options. At most one -triple and one
|
||||
-arch option may be specified. Both are optional.
|
||||
|
||||
The "selection of target" behavior is defined as follows:
|
||||
|
||||
(1) If the user does not specify -triple, we default to the host triple.
|
||||
(2) If the user specifies a -arch, that overrides the arch in the host or
|
||||
specified triple.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
|
||||
verifyInputConstraint and verifyOutputConstraint should not return bool.
|
||||
|
||||
Instead we should return something like:
|
||||
|
||||
enum VerifyConstraintResult {
|
||||
Valid,
|
||||
|
||||
// Output only
|
||||
OutputOperandConstraintLacksEqualsCharacter,
|
||||
MatchingConstraintNotValidInOutputOperand,
|
||||
|
||||
// Input only
|
||||
InputOperandConstraintContainsEqualsCharacter,
|
||||
MatchingConstraintReferencesInvalidOperandNumber,
|
||||
|
||||
// Both
|
||||
PercentConstraintUsedWithLastOperand
|
||||
};
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
@@ -1,26 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// C Language Family Front-end
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Welcome to Clang. This is a compiler front-end for the C family of languages
|
||||
(C, C++, Objective-C, and Objective-C++) which is built as part of the LLVM
|
||||
compiler infrastructure project.
|
||||
|
||||
Unlike many other compiler frontends, Clang is useful for a number of things
|
||||
beyond just compiling code: we intend for Clang to be host to a number of
|
||||
different source level tools. One example of this is the Clang Static Analyzer.
|
||||
|
||||
If you're interested in more (including how to build Clang) it is best to read
|
||||
the relevant web sites. Here are some pointers:
|
||||
|
||||
Information on Clang: http://clang.llvm.org/
|
||||
Building and using Clang: http://clang.llvm.org/get_started.html
|
||||
Clang Static Analyzer: http://clang-analyzer.llvm.org/
|
||||
Information on the LLVM project: http://llvm.org/
|
||||
|
||||
If you have questions or comments about Clang, a great place to discuss them is
|
||||
on the Clang development mailing list:
|
||||
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
|
||||
|
||||
If you find a bug in Clang, please file it in the LLVM bug tracker:
|
||||
http://llvm.org/bugs/
|
||||
@@ -1,75 +0,0 @@
|
||||
//===---------------------------------------------------------------------===//
|
||||
// Minor random things that can be improved
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
|
||||
Warn about "X && 0x1000" saying that the user may mean "X & 0x1000".
|
||||
We should do this for any immediate except zero, so long as it doesn't come
|
||||
from a macro expansion. Likewise for ||.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
Lexer-related diagnostics should point to the problematic character, not the
|
||||
start of the token. For example:
|
||||
|
||||
int y = 0000\
|
||||
00080;
|
||||
|
||||
diag.c:4:9: error: invalid digit '8' in octal constant
|
||||
int y = 0000\
|
||||
^
|
||||
|
||||
should be:
|
||||
|
||||
diag.c:4:9: error: invalid digit '8' in octal constant
|
||||
00080;
|
||||
^
|
||||
|
||||
This specific diagnostic is implemented, but others should be updated.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
C++ (checker): For iterators, warn of the use of "iterator++" instead
|
||||
of "++iterator" when when the value returned by operator++(int) is
|
||||
ignored.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
We want to keep more source range information in Declarator to help
|
||||
produce better diagnostics. Declarator::getSourceRange() should be
|
||||
implemented to give a range for the whole declarator with all of its
|
||||
specifiers, and DeclaratorChunk::ParamInfo should also have a source
|
||||
range covering the whole parameter, so that an error message like this:
|
||||
|
||||
overloaded-operator-decl.cpp:37:23: error: parameter of overloaded post-increment operator must have type 'int' (not 'float')
|
||||
X operator++(X&, const float& f);
|
||||
^
|
||||
can be turned into something like this:
|
||||
|
||||
overloaded-operator-decl.cpp:37:23: error: parameter of overloaded post-increment operator must have type 'int' (not 'float')
|
||||
X operator++(X&, const float& f);
|
||||
^ ~~~~~~~~~~~~~~
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
For terminal output, we should consider limiting the amount of
|
||||
diagnostic text we print once the first error has been
|
||||
encountered. For example, once we have produced an error diagnostic,
|
||||
we should only continue producing diagnostics until we have produced a
|
||||
page full of results (say, 50 lines of text). Beyond that, (1) the
|
||||
remaining errors are likely to be less interesting, and (2) the poor
|
||||
user has to scroll his terminal to find out where things went wrong.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
More ideas for code modification hints:
|
||||
- If no member of a given name is found in a class/struct, search through the names of entities that do exist in the class and suggest the closest candidate. e.g., if I write "DS.setTypeSpecType", it would suggest "DS.SetTypeSpecType" (edit distance = 1).
|
||||
- If a class member is defined out-of-line but isn't in the class declaration (and there are no close matches!), provide the option to add an in-class declaration.
|
||||
- Fix-it hints for the inclusion of headers when needed for particular features (e.g., <typeinfo> for typeid)
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
Options to support:
|
||||
-ftabstop=width
|
||||
-fpreprocessed mode.
|
||||
-nostdinc++
|
||||
-imultilib
|
||||
@@ -1,17 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Clang Python Bindings
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
This directory implements Python bindings for Clang.
|
||||
|
||||
You may need to alter LD_LIBRARY_PATH so that the Clang library can be
|
||||
found. The unit tests are designed to be run with 'nosetests'. For example:
|
||||
--
|
||||
$ env PYTHONPATH=$(echo ~/llvm/tools/clang/bindings/python/) \
|
||||
LD_LIBRARY_PATH=$(llvm-config --libdir) \
|
||||
nosetests -v
|
||||
tests.cindex.test_index.test_create ... ok
|
||||
...
|
||||
|
||||
OK
|
||||
--
|
||||
@@ -1,24 +0,0 @@
|
||||
#===- __init__.py - Clang Python Bindings --------------------*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
r"""
|
||||
Clang Library Bindings
|
||||
======================
|
||||
|
||||
This package provides access to the Clang compiler and libraries.
|
||||
|
||||
The available modules are:
|
||||
|
||||
cindex
|
||||
|
||||
Bindings for the Clang indexing library.
|
||||
"""
|
||||
|
||||
__all__ = ['cindex']
|
||||
|
||||
@@ -1,935 +0,0 @@
|
||||
#===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
r"""
|
||||
Clang Indexing Library Bindings
|
||||
===============================
|
||||
|
||||
This module provides an interface to the Clang indexing library. It is a
|
||||
low-level interface to the indexing library which attempts to match the Clang
|
||||
API directly while also being "pythonic". Notable differences from the C API
|
||||
are:
|
||||
|
||||
* string results are returned as Python strings, not CXString objects.
|
||||
|
||||
* null cursors are translated to None.
|
||||
|
||||
* access to child cursors is done via iteration, not visitation.
|
||||
|
||||
The major indexing objects are:
|
||||
|
||||
Index
|
||||
|
||||
The top-level object which manages some global library state.
|
||||
|
||||
TranslationUnit
|
||||
|
||||
High-level object encapsulating the AST for a single translation unit. These
|
||||
can be loaded from .ast files or parsed on the fly.
|
||||
|
||||
Cursor
|
||||
|
||||
Generic object for representing a node in the AST.
|
||||
|
||||
SourceRange, SourceLocation, and File
|
||||
|
||||
Objects representing information about the input source.
|
||||
|
||||
Most object information is exposed using properties, when the underlying API
|
||||
call is efficient.
|
||||
"""
|
||||
|
||||
# TODO
|
||||
# ====
|
||||
#
|
||||
# o API support for invalid translation units. Currently we can't even get the
|
||||
# diagnostics on failure because they refer to locations in an object that
|
||||
# will have been invalidated.
|
||||
#
|
||||
# o fix memory management issues (currently client must hold on to index and
|
||||
# translation unit, or risk crashes).
|
||||
#
|
||||
# o expose code completion APIs.
|
||||
#
|
||||
# o cleanup ctypes wrapping, would be nice to separate the ctypes details more
|
||||
# clearly, and hide from the external interface (i.e., help(cindex)).
|
||||
#
|
||||
# o implement additional SourceLocation, SourceRange, and File methods.
|
||||
|
||||
from ctypes import *
|
||||
|
||||
def get_cindex_library():
|
||||
# FIXME: It's probably not the case that the library is actually found in
|
||||
# this location. We need a better system of identifying and loading the
|
||||
# CIndex library. It could be on path or elsewhere, or versioned, etc.
|
||||
import platform
|
||||
name = platform.system()
|
||||
if name == 'Darwin':
|
||||
return cdll.LoadLibrary('libclang.dylib')
|
||||
elif name == 'Windows':
|
||||
return cdll.LoadLibrary('libclang.dll')
|
||||
else:
|
||||
return cdll.LoadLibrary('libclang.so')
|
||||
|
||||
# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
|
||||
# object. This is a problem, because it means that from_parameter will see an
|
||||
# integer and pass the wrong value on platforms where int != void*. Work around
|
||||
# this by marshalling object arguments as void**.
|
||||
c_object_p = POINTER(c_void_p)
|
||||
|
||||
lib = get_cindex_library()
|
||||
|
||||
### Structures and Utility Classes ###
|
||||
|
||||
class _CXString(Structure):
|
||||
"""Helper for transforming CXString results."""
|
||||
|
||||
_fields_ = [("spelling", c_char_p), ("free", c_int)]
|
||||
|
||||
def __del__(self):
|
||||
_CXString_dispose(self)
|
||||
|
||||
@staticmethod
|
||||
def from_result(res, fn, args):
|
||||
assert isinstance(res, _CXString)
|
||||
return _CXString_getCString(res)
|
||||
|
||||
class SourceLocation(Structure):
|
||||
"""
|
||||
A SourceLocation represents a particular location within a source file.
|
||||
"""
|
||||
_fields_ = [("ptr_data", c_void_p * 2), ("int_data", c_uint)]
|
||||
_data = None
|
||||
|
||||
def _get_instantiation(self):
|
||||
if self._data is None:
|
||||
f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint()
|
||||
SourceLocation_loc(self, byref(f), byref(l), byref(c), byref(o))
|
||||
f = File(f) if f else None
|
||||
self._data = (f, int(l.value), int(c.value), int(c.value))
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def file(self):
|
||||
"""Get the file represented by this source location."""
|
||||
return self._get_instantiation()[0]
|
||||
|
||||
@property
|
||||
def line(self):
|
||||
"""Get the line represented by this source location."""
|
||||
return self._get_instantiation()[1]
|
||||
|
||||
@property
|
||||
def column(self):
|
||||
"""Get the column represented by this source location."""
|
||||
return self._get_instantiation()[2]
|
||||
|
||||
@property
|
||||
def offset(self):
|
||||
"""Get the file offset represented by this source location."""
|
||||
return self._get_instantiation()[3]
|
||||
|
||||
def __repr__(self):
|
||||
return "<SourceLocation file %r, line %r, column %r>" % (
|
||||
self.file.name if self.file else None, self.line, self.column)
|
||||
|
||||
class SourceRange(Structure):
|
||||
"""
|
||||
A SourceRange describes a range of source locations within the source
|
||||
code.
|
||||
"""
|
||||
_fields_ = [
|
||||
("ptr_data", c_void_p * 2),
|
||||
("begin_int_data", c_uint),
|
||||
("end_int_data", c_uint)]
|
||||
|
||||
# FIXME: Eliminate this and make normal constructor? Requires hiding ctypes
|
||||
# object.
|
||||
@staticmethod
|
||||
def from_locations(start, end):
|
||||
return SourceRange_getRange(start, end)
|
||||
|
||||
@property
|
||||
def start(self):
|
||||
"""
|
||||
Return a SourceLocation representing the first character within a
|
||||
source range.
|
||||
"""
|
||||
return SourceRange_start(self)
|
||||
|
||||
@property
|
||||
def end(self):
|
||||
"""
|
||||
Return a SourceLocation representing the last character within a
|
||||
source range.
|
||||
"""
|
||||
return SourceRange_end(self)
|
||||
|
||||
def __repr__(self):
|
||||
return "<SourceRange start %r, end %r>" % (self.start, self.end)
|
||||
|
||||
class Diagnostic(object):
|
||||
"""
|
||||
A Diagnostic is a single instance of a Clang diagnostic. It includes the
|
||||
diagnostic severity, the message, the location the diagnostic occurred, as
|
||||
well as additional source ranges and associated fix-it hints.
|
||||
"""
|
||||
|
||||
Ignored = 0
|
||||
Note = 1
|
||||
Warning = 2
|
||||
Error = 3
|
||||
Fatal = 4
|
||||
|
||||
def __init__(self, ptr):
|
||||
self.ptr = ptr
|
||||
|
||||
def __del__(self):
|
||||
_clang_disposeDiagnostic(self.ptr)
|
||||
|
||||
@property
|
||||
def severity(self):
|
||||
return _clang_getDiagnosticSeverity(self.ptr)
|
||||
|
||||
@property
|
||||
def location(self):
|
||||
return _clang_getDiagnosticLocation(self.ptr)
|
||||
|
||||
@property
|
||||
def spelling(self):
|
||||
return _clang_getDiagnosticSpelling(self.ptr)
|
||||
|
||||
@property
|
||||
def ranges(self):
|
||||
class RangeIterator:
|
||||
def __init__(self, diag):
|
||||
self.diag = diag
|
||||
|
||||
def __len__(self):
|
||||
return int(_clang_getDiagnosticNumRanges(self.diag))
|
||||
|
||||
def __getitem__(self, key):
|
||||
return _clang_getDiagnosticRange(self.diag, key)
|
||||
|
||||
return RangeIterator(self.ptr)
|
||||
|
||||
@property
|
||||
def fixits(self):
|
||||
class FixItIterator:
|
||||
def __init__(self, diag):
|
||||
self.diag = diag
|
||||
|
||||
def __len__(self):
|
||||
return int(_clang_getDiagnosticNumFixIts(self.diag))
|
||||
|
||||
def __getitem__(self, key):
|
||||
range = SourceRange()
|
||||
value = _clang_getDiagnosticFixIt(self.diag, key, byref(range))
|
||||
if len(value) == 0:
|
||||
raise IndexError
|
||||
|
||||
return FixIt(range, value)
|
||||
|
||||
return FixItIterator(self.ptr)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Diagnostic severity %r, location %r, spelling %r>" % (
|
||||
self.severity, self.location, self.spelling)
|
||||
|
||||
class FixIt(object):
|
||||
"""
|
||||
A FixIt represents a transformation to be applied to the source to
|
||||
"fix-it". The fix-it shouldbe applied by replacing the given source range
|
||||
with the given value.
|
||||
"""
|
||||
|
||||
def __init__(self, range, value):
|
||||
self.range = range
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return "<FixIt range %r, value %r>" % (self.range, self.value)
|
||||
|
||||
### Cursor Kinds ###
|
||||
|
||||
class CursorKind(object):
|
||||
"""
|
||||
A CursorKind describes the kind of entity that a cursor points to.
|
||||
"""
|
||||
|
||||
# The unique kind objects, indexed by id.
|
||||
_kinds = []
|
||||
_name_map = None
|
||||
|
||||
def __init__(self, value):
|
||||
if value >= len(CursorKind._kinds):
|
||||
CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1)
|
||||
if CursorKind._kinds[value] is not None:
|
||||
raise ValueError,'CursorKind already loaded'
|
||||
self.value = value
|
||||
CursorKind._kinds[value] = self
|
||||
CursorKind._name_map = None
|
||||
|
||||
def from_param(self):
|
||||
return self.value
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Get the enumeration name of this cursor kind."""
|
||||
if self._name_map is None:
|
||||
self._name_map = {}
|
||||
for key,value in CursorKind.__dict__.items():
|
||||
if isinstance(value,CursorKind):
|
||||
self._name_map[value] = key
|
||||
return self._name_map[self]
|
||||
|
||||
@staticmethod
|
||||
def from_id(id):
|
||||
if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None:
|
||||
raise ValueError,'Unknown cursor kind'
|
||||
return CursorKind._kinds[id]
|
||||
|
||||
@staticmethod
|
||||
def get_all_kinds():
|
||||
"""Return all CursorKind enumeration instances."""
|
||||
return filter(None, CursorKind._kinds)
|
||||
|
||||
def is_declaration(self):
|
||||
"""Test if this is a declaration kind."""
|
||||
return CursorKind_is_decl(self)
|
||||
|
||||
def is_reference(self):
|
||||
"""Test if this is a reference kind."""
|
||||
return CursorKind_is_ref(self)
|
||||
|
||||
def is_expression(self):
|
||||
"""Test if this is an expression kind."""
|
||||
return CursorKind_is_expr(self)
|
||||
|
||||
def is_statement(self):
|
||||
"""Test if this is a statement kind."""
|
||||
return CursorKind_is_stmt(self)
|
||||
|
||||
def is_invalid(self):
|
||||
"""Test if this is an invalid kind."""
|
||||
return CursorKind_is_inv(self)
|
||||
|
||||
def __repr__(self):
|
||||
return 'CursorKind.%s' % (self.name,)
|
||||
|
||||
# FIXME: Is there a nicer way to expose this enumeration? We could potentially
|
||||
# represent the nested structure, or even build a class hierarchy. The main
|
||||
# things we want for sure are (a) simple external access to kinds, (b) a place
|
||||
# to hang a description and name, (c) easy to keep in sync with Index.h.
|
||||
|
||||
###
|
||||
# Declaration Kinds
|
||||
|
||||
# A declaration whose specific kind is not exposed via this interface.
|
||||
#
|
||||
# Unexposed declarations have the same operations as any other kind of
|
||||
# declaration; one can extract their location information, spelling, find their
|
||||
# definitions, etc. However, the specific kind of the declaration is not
|
||||
# reported.
|
||||
CursorKind.UNEXPOSED_DECL = CursorKind(1)
|
||||
|
||||
# A C or C++ struct.
|
||||
CursorKind.STRUCT_DECL = CursorKind(2)
|
||||
|
||||
# A C or C++ union.
|
||||
CursorKind.UNION_DECL = CursorKind(3)
|
||||
|
||||
# A C++ class.
|
||||
CursorKind.CLASS_DECL = CursorKind(4)
|
||||
|
||||
# An enumeration.
|
||||
CursorKind.ENUM_DECL = CursorKind(5)
|
||||
|
||||
# A field (in C) or non-static data member (in C++) in a struct, union, or C++
|
||||
# class.
|
||||
CursorKind.FIELD_DECL = CursorKind(6)
|
||||
|
||||
# An enumerator constant.
|
||||
CursorKind.ENUM_CONSTANT_DECL = CursorKind(7)
|
||||
|
||||
# A function.
|
||||
CursorKind.FUNCTION_DECL = CursorKind(8)
|
||||
|
||||
# A variable.
|
||||
CursorKind.VAR_DECL = CursorKind(9)
|
||||
|
||||
# A function or method parameter.
|
||||
CursorKind.PARM_DECL = CursorKind(10)
|
||||
|
||||
# An Objective-C @interface.
|
||||
CursorKind.OBJC_INTERFACE_DECL = CursorKind(11)
|
||||
|
||||
# An Objective-C @interface for a category.
|
||||
CursorKind.OBJC_CATEGORY_DECL = CursorKind(12)
|
||||
|
||||
# An Objective-C @protocol declaration.
|
||||
CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13)
|
||||
|
||||
# An Objective-C @property declaration.
|
||||
CursorKind.OBJC_PROPERTY_DECL = CursorKind(14)
|
||||
|
||||
# An Objective-C instance variable.
|
||||
CursorKind.OBJC_IVAR_DECL = CursorKind(15)
|
||||
|
||||
# An Objective-C instance method.
|
||||
CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16)
|
||||
|
||||
# An Objective-C class method.
|
||||
CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17)
|
||||
|
||||
# An Objective-C @implementation.
|
||||
CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18)
|
||||
|
||||
# An Objective-C @implementation for a category.
|
||||
CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19)
|
||||
|
||||
# A typedef.
|
||||
CursorKind.TYPEDEF_DECL = CursorKind(20)
|
||||
|
||||
###
|
||||
# Reference Kinds
|
||||
|
||||
CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40)
|
||||
CursorKind.OBJC_PROTOCOL_REF = CursorKind(41)
|
||||
CursorKind.OBJC_CLASS_REF = CursorKind(42)
|
||||
|
||||
# A reference to a type declaration.
|
||||
#
|
||||
# A type reference occurs anywhere where a type is named but not
|
||||
# declared. For example, given:
|
||||
# typedef unsigned size_type;
|
||||
# size_type size;
|
||||
#
|
||||
# The typedef is a declaration of size_type (CXCursor_TypedefDecl),
|
||||
# while the type of the variable "size" is referenced. The cursor
|
||||
# referenced by the type of size is the typedef for size_type.
|
||||
CursorKind.TYPE_REF = CursorKind(43)
|
||||
|
||||
###
|
||||
# Invalid/Error Kinds
|
||||
|
||||
CursorKind.INVALID_FILE = CursorKind(70)
|
||||
CursorKind.NO_DECL_FOUND = CursorKind(71)
|
||||
CursorKind.NOT_IMPLEMENTED = CursorKind(72)
|
||||
|
||||
###
|
||||
# Expression Kinds
|
||||
|
||||
# An expression whose specific kind is not exposed via this interface.
|
||||
#
|
||||
# Unexposed expressions have the same operations as any other kind of
|
||||
# expression; one can extract their location information, spelling, children,
|
||||
# etc. However, the specific kind of the expression is not reported.
|
||||
CursorKind.UNEXPOSED_EXPR = CursorKind(100)
|
||||
|
||||
# An expression that refers to some value declaration, such as a function,
|
||||
# varible, or enumerator.
|
||||
CursorKind.DECL_REF_EXPR = CursorKind(101)
|
||||
|
||||
# An expression that refers to a member of a struct, union, class, Objective-C
|
||||
# class, etc.
|
||||
CursorKind.MEMBER_REF_EXPR = CursorKind(102)
|
||||
|
||||
# An expression that calls a function.
|
||||
CursorKind.CALL_EXPR = CursorKind(103)
|
||||
|
||||
# An expression that sends a message to an Objective-C object or class.
|
||||
CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104)
|
||||
|
||||
# A statement whose specific kind is not exposed via this interface.
|
||||
#
|
||||
# Unexposed statements have the same operations as any other kind of statement;
|
||||
# one can extract their location information, spelling, children, etc. However,
|
||||
# the specific kind of the statement is not reported.
|
||||
CursorKind.UNEXPOSED_STMT = CursorKind(200)
|
||||
|
||||
###
|
||||
# Other Kinds
|
||||
|
||||
# Cursor that represents the translation unit itself.
|
||||
#
|
||||
# The translation unit cursor exists primarily to act as the root cursor for
|
||||
# traversing the contents of a translation unit.
|
||||
CursorKind.TRANSLATION_UNIT = CursorKind(300)
|
||||
|
||||
### Cursors ###
|
||||
|
||||
class Cursor(Structure):
|
||||
"""
|
||||
The Cursor class represents a reference to an element within the AST. It
|
||||
acts as a kind of iterator.
|
||||
"""
|
||||
_fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)]
|
||||
|
||||
def __eq__(self, other):
|
||||
return Cursor_eq(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not Cursor_eq(self, other)
|
||||
|
||||
def is_definition(self):
|
||||
"""
|
||||
Returns true if the declaration pointed at by the cursor is also a
|
||||
definition of that entity.
|
||||
"""
|
||||
return Cursor_is_def(self)
|
||||
|
||||
def get_definition(self):
|
||||
"""
|
||||
If the cursor is a reference to a declaration or a declaration of
|
||||
some entity, return a cursor that points to the definition of that
|
||||
entity.
|
||||
"""
|
||||
# TODO: Should probably check that this is either a reference or
|
||||
# declaration prior to issuing the lookup.
|
||||
return Cursor_def(self)
|
||||
|
||||
def get_usr(self):
|
||||
"""Return the Unified Symbol Resultion (USR) for the entity referenced
|
||||
by the given cursor (or None).
|
||||
|
||||
A Unified Symbol Resolution (USR) is a string that identifies a
|
||||
particular entity (function, class, variable, etc.) within a
|
||||
program. USRs can be compared across translation units to determine,
|
||||
e.g., when references in one translation refer to an entity defined in
|
||||
another translation unit."""
|
||||
return Cursor_usr(self)
|
||||
|
||||
@property
|
||||
def kind(self):
|
||||
"""Return the kind of this cursor."""
|
||||
return CursorKind.from_id(self._kind_id)
|
||||
|
||||
@property
|
||||
def spelling(self):
|
||||
"""Return the spelling of the entity pointed at by the cursor."""
|
||||
if not self.kind.is_declaration():
|
||||
# FIXME: clang_getCursorSpelling should be fixed to not assert on
|
||||
# this, for consistency with clang_getCursorUSR.
|
||||
return None
|
||||
return Cursor_spelling(self)
|
||||
|
||||
@property
|
||||
def location(self):
|
||||
"""
|
||||
Return the source location (the starting character) of the entity
|
||||
pointed at by the cursor.
|
||||
"""
|
||||
return Cursor_loc(self)
|
||||
|
||||
@property
|
||||
def extent(self):
|
||||
"""
|
||||
Return the source range (the range of text) occupied by the entity
|
||||
pointed at by the cursor.
|
||||
"""
|
||||
return Cursor_extent(self)
|
||||
|
||||
def get_children(self):
|
||||
"""Return an iterator for accessing the children of this cursor."""
|
||||
|
||||
# FIXME: Expose iteration from CIndex, PR6125.
|
||||
def visitor(child, parent, children):
|
||||
# FIXME: Document this assertion in API.
|
||||
# FIXME: There should just be an isNull method.
|
||||
assert child != Cursor_null()
|
||||
children.append(child)
|
||||
return 1 # continue
|
||||
children = []
|
||||
Cursor_visit(self, Cursor_visit_callback(visitor), children)
|
||||
return iter(children)
|
||||
|
||||
@staticmethod
|
||||
def from_result(res, fn, args):
|
||||
assert isinstance(res, Cursor)
|
||||
# FIXME: There should just be an isNull method.
|
||||
if res == Cursor_null():
|
||||
return None
|
||||
return res
|
||||
|
||||
## CIndex Objects ##
|
||||
|
||||
# CIndex objects (derived from ClangObject) are essentially lightweight
|
||||
# wrappers attached to some underlying object, which is exposed via CIndex as
|
||||
# a void*.
|
||||
|
||||
class ClangObject(object):
|
||||
"""
|
||||
A helper for Clang objects. This class helps act as an intermediary for
|
||||
the ctypes library and the Clang CIndex library.
|
||||
"""
|
||||
def __init__(self, obj):
|
||||
assert isinstance(obj, c_object_p) and obj
|
||||
self.obj = self._as_parameter_ = obj
|
||||
|
||||
def from_param(self):
|
||||
return self._as_parameter_
|
||||
|
||||
|
||||
class _CXUnsavedFile(Structure):
|
||||
"""Helper for passing unsaved file arguments."""
|
||||
_fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)]
|
||||
|
||||
## Diagnostic Conversion ##
|
||||
|
||||
_clang_getNumDiagnostics = lib.clang_getNumDiagnostics
|
||||
_clang_getNumDiagnostics.argtypes = [c_object_p]
|
||||
_clang_getNumDiagnostics.restype = c_uint
|
||||
|
||||
_clang_getDiagnostic = lib.clang_getDiagnostic
|
||||
_clang_getDiagnostic.argtypes = [c_object_p, c_uint]
|
||||
_clang_getDiagnostic.restype = c_object_p
|
||||
|
||||
_clang_disposeDiagnostic = lib.clang_disposeDiagnostic
|
||||
_clang_disposeDiagnostic.argtypes = [c_object_p]
|
||||
|
||||
_clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity
|
||||
_clang_getDiagnosticSeverity.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticSeverity.restype = c_int
|
||||
|
||||
_clang_getDiagnosticLocation = lib.clang_getDiagnosticLocation
|
||||
_clang_getDiagnosticLocation.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticLocation.restype = SourceLocation
|
||||
|
||||
_clang_getDiagnosticSpelling = lib.clang_getDiagnosticSpelling
|
||||
_clang_getDiagnosticSpelling.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticSpelling.restype = _CXString
|
||||
_clang_getDiagnosticSpelling.errcheck = _CXString.from_result
|
||||
|
||||
_clang_getDiagnosticNumRanges = lib.clang_getDiagnosticNumRanges
|
||||
_clang_getDiagnosticNumRanges.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticNumRanges.restype = c_uint
|
||||
|
||||
_clang_getDiagnosticRange = lib.clang_getDiagnosticRange
|
||||
_clang_getDiagnosticRange.argtypes = [c_object_p, c_uint]
|
||||
_clang_getDiagnosticRange.restype = SourceRange
|
||||
|
||||
_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts
|
||||
_clang_getDiagnosticNumFixIts.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticNumFixIts.restype = c_uint
|
||||
|
||||
_clang_getDiagnosticFixIt = lib.clang_getDiagnosticFixIt
|
||||
_clang_getDiagnosticFixIt.argtypes = [c_object_p, c_uint, POINTER(SourceRange)]
|
||||
_clang_getDiagnosticFixIt.restype = _CXString
|
||||
_clang_getDiagnosticFixIt.errcheck = _CXString.from_result
|
||||
|
||||
###
|
||||
|
||||
class Index(ClangObject):
|
||||
"""
|
||||
The Index type provides the primary interface to the Clang CIndex library,
|
||||
primarily by providing an interface for reading and parsing translation
|
||||
units.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def create(excludeDecls=False):
|
||||
"""
|
||||
Create a new Index.
|
||||
Parameters:
|
||||
excludeDecls -- Exclude local declarations from translation units.
|
||||
"""
|
||||
return Index(Index_create(excludeDecls, 0))
|
||||
|
||||
def __del__(self):
|
||||
Index_dispose(self)
|
||||
|
||||
def read(self, path):
|
||||
"""Load the translation unit from the given AST file."""
|
||||
ptr = TranslationUnit_read(self, path)
|
||||
return TranslationUnit(ptr) if ptr else None
|
||||
|
||||
def parse(self, path, args = [], unsaved_files = []):
|
||||
"""
|
||||
Load the translation unit from the given source code file by running
|
||||
clang and generating the AST before loading. Additional command line
|
||||
parameters can be passed to clang via the args parameter.
|
||||
|
||||
In-memory contents for files can be provided by passing a list of pairs
|
||||
to as unsaved_files, the first item should be the filenames to be mapped
|
||||
and the second should be the contents to be substituted for the
|
||||
file. The contents may be passed as strings or file objects.
|
||||
"""
|
||||
arg_array = 0
|
||||
if len(args):
|
||||
arg_array = (c_char_p * len(args))(* args)
|
||||
unsaved_files_array = 0
|
||||
if len(unsaved_files):
|
||||
unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
|
||||
for i,(name,value) in enumerate(unsaved_files):
|
||||
if not isinstance(value, str):
|
||||
# FIXME: It would be great to support an efficient version
|
||||
# of this, one day.
|
||||
value = value.read()
|
||||
print value
|
||||
if not isinstance(value, str):
|
||||
raise TypeError,'Unexpected unsaved file contents.'
|
||||
unsaved_files_array[i].name = name
|
||||
unsaved_files_array[i].contents = value
|
||||
unsaved_files_array[i].length = len(value)
|
||||
ptr = TranslationUnit_parse(self, path, len(args), arg_array,
|
||||
len(unsaved_files), unsaved_files_array)
|
||||
return TranslationUnit(ptr) if ptr else None
|
||||
|
||||
|
||||
class TranslationUnit(ClangObject):
|
||||
"""
|
||||
The TranslationUnit class represents a source code translation unit and
|
||||
provides read-only access to its top-level declarations.
|
||||
"""
|
||||
|
||||
def __init__(self, ptr):
|
||||
ClangObject.__init__(self, ptr)
|
||||
|
||||
def __del__(self):
|
||||
TranslationUnit_dispose(self)
|
||||
|
||||
@property
|
||||
def cursor(self):
|
||||
"""Retrieve the cursor that represents the given translation unit."""
|
||||
return TranslationUnit_cursor(self)
|
||||
|
||||
@property
|
||||
def spelling(self):
|
||||
"""Get the original translation unit source file name."""
|
||||
return TranslationUnit_spelling(self)
|
||||
|
||||
def get_includes(self):
|
||||
"""
|
||||
Return an iterable sequence of FileInclusion objects that describe the
|
||||
sequence of inclusions in a translation unit. The first object in
|
||||
this sequence is always the input file. Note that this method will not
|
||||
recursively iterate over header files included through precompiled
|
||||
headers.
|
||||
"""
|
||||
def visitor(fobj, lptr, depth, includes):
|
||||
loc = lptr.contents
|
||||
includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
|
||||
|
||||
# Automatically adapt CIndex/ctype pointers to python objects
|
||||
includes = []
|
||||
TranslationUnit_includes(self,
|
||||
TranslationUnit_includes_callback(visitor),
|
||||
includes)
|
||||
return iter(includes)
|
||||
|
||||
@property
|
||||
def diagnostics(self):
|
||||
"""
|
||||
Return an iterable (and indexable) object containing the diagnostics.
|
||||
"""
|
||||
class DiagIterator:
|
||||
def __init__(self, tu):
|
||||
self.tu = tu
|
||||
|
||||
def __len__(self):
|
||||
return int(_clang_getNumDiagnostics(self.tu))
|
||||
|
||||
def __getitem__(self, key):
|
||||
diag = _clang_getDiagnostic(self.tu, key)
|
||||
if not diag:
|
||||
raise IndexError
|
||||
return Diagnostic(diag)
|
||||
|
||||
return DiagIterator(self)
|
||||
|
||||
class File(ClangObject):
|
||||
"""
|
||||
The File class represents a particular source file that is part of a
|
||||
translation unit.
|
||||
"""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the complete file and path name of the file."""
|
||||
return File_name(self)
|
||||
|
||||
@property
|
||||
def time(self):
|
||||
"""Return the last modification time of the file."""
|
||||
return File_time(self)
|
||||
|
||||
class FileInclusion(object):
|
||||
"""
|
||||
The FileInclusion class represents the inclusion of one source file by
|
||||
another via a '#include' directive or as the input file for the translation
|
||||
unit. This class provides information about the included file, the including
|
||||
file, the location of the '#include' directive and the depth of the included
|
||||
file in the stack. Note that the input file has depth 0.
|
||||
"""
|
||||
|
||||
def __init__(self, src, tgt, loc, depth):
|
||||
self.source = src
|
||||
self.include = tgt
|
||||
self.location = loc
|
||||
self.depth = depth
|
||||
|
||||
@property
|
||||
def is_input_file(self):
|
||||
"""True if the included file is the input file."""
|
||||
return self.depth == 0
|
||||
|
||||
# Additional Functions and Types
|
||||
|
||||
# String Functions
|
||||
_CXString_dispose = lib.clang_disposeString
|
||||
_CXString_dispose.argtypes = [_CXString]
|
||||
|
||||
_CXString_getCString = lib.clang_getCString
|
||||
_CXString_getCString.argtypes = [_CXString]
|
||||
_CXString_getCString.restype = c_char_p
|
||||
|
||||
# Source Location Functions
|
||||
SourceLocation_loc = lib.clang_getInstantiationLocation
|
||||
SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p),
|
||||
POINTER(c_uint), POINTER(c_uint),
|
||||
POINTER(c_uint)]
|
||||
|
||||
# Source Range Functions
|
||||
SourceRange_getRange = lib.clang_getRange
|
||||
SourceRange_getRange.argtypes = [SourceLocation, SourceLocation]
|
||||
SourceRange_getRange.restype = SourceRange
|
||||
|
||||
SourceRange_start = lib.clang_getRangeStart
|
||||
SourceRange_start.argtypes = [SourceRange]
|
||||
SourceRange_start.restype = SourceLocation
|
||||
|
||||
SourceRange_end = lib.clang_getRangeEnd
|
||||
SourceRange_end.argtypes = [SourceRange]
|
||||
SourceRange_end.restype = SourceLocation
|
||||
|
||||
# CursorKind Functions
|
||||
CursorKind_is_decl = lib.clang_isDeclaration
|
||||
CursorKind_is_decl.argtypes = [CursorKind]
|
||||
CursorKind_is_decl.restype = bool
|
||||
|
||||
CursorKind_is_ref = lib.clang_isReference
|
||||
CursorKind_is_ref.argtypes = [CursorKind]
|
||||
CursorKind_is_ref.restype = bool
|
||||
|
||||
CursorKind_is_expr = lib.clang_isExpression
|
||||
CursorKind_is_expr.argtypes = [CursorKind]
|
||||
CursorKind_is_expr.restype = bool
|
||||
|
||||
CursorKind_is_stmt = lib.clang_isStatement
|
||||
CursorKind_is_stmt.argtypes = [CursorKind]
|
||||
CursorKind_is_stmt.restype = bool
|
||||
|
||||
CursorKind_is_inv = lib.clang_isInvalid
|
||||
CursorKind_is_inv.argtypes = [CursorKind]
|
||||
CursorKind_is_inv.restype = bool
|
||||
|
||||
# Cursor Functions
|
||||
# TODO: Implement this function
|
||||
Cursor_get = lib.clang_getCursor
|
||||
Cursor_get.argtypes = [TranslationUnit, SourceLocation]
|
||||
Cursor_get.restype = Cursor
|
||||
|
||||
Cursor_null = lib.clang_getNullCursor
|
||||
Cursor_null.restype = Cursor
|
||||
|
||||
Cursor_usr = lib.clang_getCursorUSR
|
||||
Cursor_usr.argtypes = [Cursor]
|
||||
Cursor_usr.restype = _CXString
|
||||
Cursor_usr.errcheck = _CXString.from_result
|
||||
|
||||
Cursor_is_def = lib.clang_isCursorDefinition
|
||||
Cursor_is_def.argtypes = [Cursor]
|
||||
Cursor_is_def.restype = bool
|
||||
|
||||
Cursor_def = lib.clang_getCursorDefinition
|
||||
Cursor_def.argtypes = [Cursor]
|
||||
Cursor_def.restype = Cursor
|
||||
Cursor_def.errcheck = Cursor.from_result
|
||||
|
||||
Cursor_eq = lib.clang_equalCursors
|
||||
Cursor_eq.argtypes = [Cursor, Cursor]
|
||||
Cursor_eq.restype = c_uint
|
||||
|
||||
Cursor_spelling = lib.clang_getCursorSpelling
|
||||
Cursor_spelling.argtypes = [Cursor]
|
||||
Cursor_spelling.restype = _CXString
|
||||
Cursor_spelling.errcheck = _CXString.from_result
|
||||
|
||||
Cursor_loc = lib.clang_getCursorLocation
|
||||
Cursor_loc.argtypes = [Cursor]
|
||||
Cursor_loc.restype = SourceLocation
|
||||
|
||||
Cursor_extent = lib.clang_getCursorExtent
|
||||
Cursor_extent.argtypes = [Cursor]
|
||||
Cursor_extent.restype = SourceRange
|
||||
|
||||
Cursor_ref = lib.clang_getCursorReferenced
|
||||
Cursor_ref.argtypes = [Cursor]
|
||||
Cursor_ref.restype = Cursor
|
||||
Cursor_ref.errcheck = Cursor.from_result
|
||||
|
||||
Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
|
||||
Cursor_visit = lib.clang_visitChildren
|
||||
Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
|
||||
Cursor_visit.restype = c_uint
|
||||
|
||||
# Index Functions
|
||||
Index_create = lib.clang_createIndex
|
||||
Index_create.argtypes = [c_int, c_int]
|
||||
Index_create.restype = c_object_p
|
||||
|
||||
Index_dispose = lib.clang_disposeIndex
|
||||
Index_dispose.argtypes = [Index]
|
||||
|
||||
# Translation Unit Functions
|
||||
TranslationUnit_read = lib.clang_createTranslationUnit
|
||||
TranslationUnit_read.argtypes = [Index, c_char_p]
|
||||
TranslationUnit_read.restype = c_object_p
|
||||
|
||||
TranslationUnit_parse = lib.clang_createTranslationUnitFromSourceFile
|
||||
TranslationUnit_parse.argtypes = [Index, c_char_p, c_int, c_void_p,
|
||||
c_int, c_void_p]
|
||||
TranslationUnit_parse.restype = c_object_p
|
||||
|
||||
TranslationUnit_cursor = lib.clang_getTranslationUnitCursor
|
||||
TranslationUnit_cursor.argtypes = [TranslationUnit]
|
||||
TranslationUnit_cursor.restype = Cursor
|
||||
TranslationUnit_cursor.errcheck = Cursor.from_result
|
||||
|
||||
TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling
|
||||
TranslationUnit_spelling.argtypes = [TranslationUnit]
|
||||
TranslationUnit_spelling.restype = _CXString
|
||||
TranslationUnit_spelling.errcheck = _CXString.from_result
|
||||
|
||||
TranslationUnit_dispose = lib.clang_disposeTranslationUnit
|
||||
TranslationUnit_dispose.argtypes = [TranslationUnit]
|
||||
|
||||
TranslationUnit_includes_callback = CFUNCTYPE(None,
|
||||
c_object_p,
|
||||
POINTER(SourceLocation),
|
||||
c_uint, py_object)
|
||||
TranslationUnit_includes = lib.clang_getInclusions
|
||||
TranslationUnit_includes.argtypes = [TranslationUnit,
|
||||
TranslationUnit_includes_callback,
|
||||
py_object]
|
||||
|
||||
# File Functions
|
||||
File_name = lib.clang_getFileName
|
||||
File_name.argtypes = [File]
|
||||
File_name.restype = c_char_p
|
||||
|
||||
File_time = lib.clang_getFileTime
|
||||
File_time.argtypes = [File]
|
||||
File_time.restype = c_uint
|
||||
|
||||
###
|
||||
|
||||
__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
|
||||
'Diagnostic', 'FixIt', 'SourceRange', 'SourceLocation', 'File']
|
||||
@@ -1,87 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#===- cindex-dump.py - cindex/Python Source Dump -------------*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
"""
|
||||
A simple command line tool for dumping a source file using the Clang Index
|
||||
Library.
|
||||
"""
|
||||
|
||||
def get_diag_info(diag):
|
||||
return { 'severity' : diag.severity,
|
||||
'location' : diag.location,
|
||||
'spelling' : diag.spelling,
|
||||
'ranges' : diag.ranges,
|
||||
'fixits' : diag.fixits }
|
||||
|
||||
def get_cursor_id(cursor, cursor_list = []):
|
||||
if not opts.showIDs:
|
||||
return None
|
||||
|
||||
if cursor is None:
|
||||
return None
|
||||
|
||||
# FIXME: This is really slow. It would be nice if the index API exposed
|
||||
# something that let us hash cursors.
|
||||
for i,c in enumerate(cursor_list):
|
||||
if cursor == c:
|
||||
return i
|
||||
cursor_list.append(cursor)
|
||||
return len(cursor_list) - 1
|
||||
|
||||
def get_info(node, depth=0):
|
||||
if opts.maxDepth is not None and depth >= opts.maxDepth:
|
||||
children = None
|
||||
else:
|
||||
children = [get_info(c, depth+1)
|
||||
for c in node.get_children()]
|
||||
return { 'id' : get_cursor_id(node),
|
||||
'kind' : node.kind,
|
||||
'usr' : node.get_usr(),
|
||||
'spelling' : node.spelling,
|
||||
'location' : node.location,
|
||||
'extent.start' : node.extent.start,
|
||||
'extent.end' : node.extent.end,
|
||||
'is_definition' : node.is_definition(),
|
||||
'definition id' : get_cursor_id(node.get_definition()),
|
||||
'children' : children }
|
||||
|
||||
def main():
|
||||
from clang.cindex import Index
|
||||
from pprint import pprint
|
||||
|
||||
from optparse import OptionParser, OptionGroup
|
||||
|
||||
global opts
|
||||
|
||||
parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
|
||||
parser.add_option("", "--show-ids", dest="showIDs",
|
||||
help="Don't compute cursor IDs (very slow)",
|
||||
default=False)
|
||||
parser.add_option("", "--max-depth", dest="maxDepth",
|
||||
help="Limit cursor expansion to depth N",
|
||||
metavar="N", type=int, default=None)
|
||||
parser.disable_interspersed_args()
|
||||
(opts, args) = parser.parse_args()
|
||||
|
||||
if len(args) == 0:
|
||||
parser.error('invalid number arguments')
|
||||
|
||||
index = Index.create()
|
||||
tu = index.parse(None, args)
|
||||
if not tu:
|
||||
parser.error("unable to load input")
|
||||
|
||||
pprint(('diags', map(get_diag_info, tu.diagnostics)))
|
||||
pprint(('nodes', get_info(tu.cursor)))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#===- cindex-includes.py - cindex/Python Inclusion Graph -----*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
"""
|
||||
A simple command line tool for dumping a Graphviz description (dot) that
|
||||
describes include dependencies.
|
||||
"""
|
||||
|
||||
def main():
|
||||
import sys
|
||||
from clang.cindex import Index
|
||||
|
||||
from optparse import OptionParser, OptionGroup
|
||||
|
||||
parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
|
||||
parser.disable_interspersed_args()
|
||||
(opts, args) = parser.parse_args()
|
||||
if len(args) == 0:
|
||||
parser.error('invalid number arguments')
|
||||
|
||||
# FIXME: Add an output file option
|
||||
out = sys.stdout
|
||||
|
||||
index = Index.create()
|
||||
tu = index.parse(None, args)
|
||||
if not tu:
|
||||
parser.error("unable to load input")
|
||||
|
||||
# A helper function for generating the node name.
|
||||
def name(f):
|
||||
if f:
|
||||
return "\"" + f.name + "\""
|
||||
|
||||
# Generate the include graph
|
||||
out.write("digraph G {\n")
|
||||
for i in tu.get_includes():
|
||||
line = " ";
|
||||
if i.is_input_file:
|
||||
# Always write the input file as a node just in case it doesn't
|
||||
# actually include anything. This would generate a 1 node graph.
|
||||
line += name(i.include)
|
||||
else:
|
||||
line += '%s->%s' % (name(i.source), name(i.include))
|
||||
line += "\n";
|
||||
out.write(line)
|
||||
out.write("}\n")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#ifndef HEADER1
|
||||
#define HEADER1
|
||||
|
||||
#include "header3.h"
|
||||
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
#ifndef HEADER2
|
||||
#define HEADER2
|
||||
|
||||
#include "header3.h"
|
||||
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
// Not a guarded header!
|
||||
|
||||
void f();
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
printf("hello world\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#include "header1.h"
|
||||
#include "header2.h"
|
||||
#include "header1.h"
|
||||
|
||||
int main() { }
|
||||
@@ -1,2 +0,0 @@
|
||||
int DECL_ONE = 1;
|
||||
int DECL_TWO = 2;
|
||||
@@ -1,59 +0,0 @@
|
||||
from clang.cindex import Index, CursorKind
|
||||
|
||||
kInput = """\
|
||||
// FIXME: Find nicer way to drop builtins and other cruft.
|
||||
int start_decl;
|
||||
|
||||
struct s0 {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct s1;
|
||||
|
||||
void f0(int a0, int a1) {
|
||||
int l0, l1;
|
||||
|
||||
if (a0)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
def test_get_children():
|
||||
index = Index.create()
|
||||
tu = index.parse('t.c', unsaved_files = [('t.c',kInput)])
|
||||
|
||||
# Skip until past start_decl.
|
||||
it = tu.cursor.get_children()
|
||||
while it.next().spelling != 'start_decl':
|
||||
pass
|
||||
|
||||
tu_nodes = list(it)
|
||||
|
||||
assert len(tu_nodes) == 3
|
||||
|
||||
assert tu_nodes[0].kind == CursorKind.STRUCT_DECL
|
||||
assert tu_nodes[0].spelling == 's0'
|
||||
assert tu_nodes[0].is_definition() == True
|
||||
assert tu_nodes[0].location.file.name == 't.c'
|
||||
assert tu_nodes[0].location.line == 4
|
||||
assert tu_nodes[0].location.column == 8
|
||||
|
||||
s0_nodes = list(tu_nodes[0].get_children())
|
||||
assert len(s0_nodes) == 2
|
||||
assert s0_nodes[0].kind == CursorKind.FIELD_DECL
|
||||
assert s0_nodes[0].spelling == 'a'
|
||||
assert s0_nodes[1].kind == CursorKind.FIELD_DECL
|
||||
assert s0_nodes[1].spelling == 'b'
|
||||
|
||||
assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
|
||||
assert tu_nodes[1].spelling == 's1'
|
||||
assert tu_nodes[1].is_definition() == False
|
||||
|
||||
assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL
|
||||
assert tu_nodes[2].spelling == 'f0'
|
||||
assert tu_nodes[2].is_definition() == True
|
||||
@@ -1,27 +0,0 @@
|
||||
from clang.cindex import CursorKind
|
||||
|
||||
def test_name():
|
||||
assert CursorKind.UNEXPOSED_DECL.name is 'UNEXPOSED_DECL'
|
||||
|
||||
def test_get_all_kinds():
|
||||
assert CursorKind.UNEXPOSED_DECL in CursorKind.get_all_kinds()
|
||||
assert CursorKind.TRANSLATION_UNIT in CursorKind.get_all_kinds()
|
||||
|
||||
def test_kind_groups():
|
||||
"""Check that every kind classifies to exactly one group."""
|
||||
|
||||
assert CursorKind.UNEXPOSED_DECL.is_declaration()
|
||||
assert CursorKind.TYPE_REF.is_reference()
|
||||
assert CursorKind.DECL_REF_EXPR.is_expression()
|
||||
assert CursorKind.UNEXPOSED_STMT.is_statement()
|
||||
assert CursorKind.INVALID_FILE.is_invalid()
|
||||
|
||||
for k in CursorKind.get_all_kinds():
|
||||
group = [n for n in ('is_declaration', 'is_reference', 'is_expression',
|
||||
'is_statement', 'is_invalid')
|
||||
if getattr(k, n)()]
|
||||
|
||||
if k == CursorKind.TRANSLATION_UNIT:
|
||||
assert len(group) == 0
|
||||
else:
|
||||
assert len(group) == 1
|
||||
@@ -1,48 +0,0 @@
|
||||
from clang.cindex import *
|
||||
|
||||
def tu_from_source(source):
|
||||
index = Index.create()
|
||||
tu = index.parse('INPUT.c', unsaved_files = [('INPUT.c', source)])
|
||||
# FIXME: Remove the need for this.
|
||||
tu.index = index
|
||||
return tu
|
||||
|
||||
# FIXME: We need support for invalid translation units to test better.
|
||||
|
||||
def test_diagnostic_warning():
|
||||
tu = tu_from_source("""int f0() {}\n""")
|
||||
assert len(tu.diagnostics) == 1
|
||||
assert tu.diagnostics[0].severity == Diagnostic.Warning
|
||||
assert tu.diagnostics[0].location.line == 1
|
||||
assert tu.diagnostics[0].location.column == 11
|
||||
assert (tu.diagnostics[0].spelling ==
|
||||
'control reaches end of non-void function')
|
||||
|
||||
def test_diagnostic_note():
|
||||
# FIXME: We aren't getting notes here for some reason.
|
||||
index = Index.create()
|
||||
tu = tu_from_source("""#define A x\nvoid *A = 1;\n""")
|
||||
assert len(tu.diagnostics) == 1
|
||||
assert tu.diagnostics[0].severity == Diagnostic.Warning
|
||||
assert tu.diagnostics[0].location.line == 2
|
||||
assert tu.diagnostics[0].location.column == 7
|
||||
assert 'incompatible' in tu.diagnostics[0].spelling
|
||||
# assert tu.diagnostics[1].severity == Diagnostic.Note
|
||||
# assert tu.diagnostics[1].location.line == 1
|
||||
# assert tu.diagnostics[1].location.column == 11
|
||||
# assert tu.diagnostics[1].spelling == 'instantiated from'
|
||||
|
||||
def test_diagnostic_fixit():
|
||||
index = Index.create()
|
||||
tu = tu_from_source("""struct { int f0; } x = { f0 : 1 };""")
|
||||
assert len(tu.diagnostics) == 1
|
||||
assert tu.diagnostics[0].severity == Diagnostic.Warning
|
||||
assert tu.diagnostics[0].location.line == 1
|
||||
assert tu.diagnostics[0].location.column == 31
|
||||
assert tu.diagnostics[0].spelling.startswith('use of GNU old-style')
|
||||
assert len(tu.diagnostics[0].fixits) == 1
|
||||
assert tu.diagnostics[0].fixits[0].range.start.line == 1
|
||||
assert tu.diagnostics[0].fixits[0].range.start.column == 26
|
||||
assert tu.diagnostics[0].fixits[0].range.end.line == 1
|
||||
assert tu.diagnostics[0].fixits[0].range.end.column == 30
|
||||
assert tu.diagnostics[0].fixits[0].value == '.f0 = '
|
||||
@@ -1,15 +0,0 @@
|
||||
from clang.cindex import *
|
||||
import os
|
||||
|
||||
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
|
||||
|
||||
def test_create():
|
||||
index = Index.create()
|
||||
|
||||
# FIXME: test Index.read
|
||||
|
||||
def test_parse():
|
||||
index = Index.create()
|
||||
assert isinstance(index, Index)
|
||||
tu = index.parse(os.path.join(kInputsDir, 'hello.cpp'))
|
||||
assert isinstance(tu, TranslationUnit)
|
||||
@@ -1,73 +0,0 @@
|
||||
from clang.cindex import *
|
||||
import os
|
||||
|
||||
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
|
||||
|
||||
def test_spelling():
|
||||
path = os.path.join(kInputsDir, 'hello.cpp')
|
||||
index = Index.create()
|
||||
tu = index.parse(path)
|
||||
assert tu.spelling == path
|
||||
|
||||
def test_cursor():
|
||||
path = os.path.join(kInputsDir, 'hello.cpp')
|
||||
index = Index.create()
|
||||
tu = index.parse(path)
|
||||
c = tu.cursor
|
||||
assert isinstance(c, Cursor)
|
||||
assert c.kind is CursorKind.TRANSLATION_UNIT
|
||||
|
||||
def test_parse_arguments():
|
||||
path = os.path.join(kInputsDir, 'parse_arguments.c')
|
||||
index = Index.create()
|
||||
tu = index.parse(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi'])
|
||||
spellings = [c.spelling for c in tu.cursor.get_children()]
|
||||
assert spellings[-2] == 'hello'
|
||||
assert spellings[-1] == 'hi'
|
||||
|
||||
def test_unsaved_files():
|
||||
index = Index.create()
|
||||
# FIXME: Why can't we just use "fake.h" here (instead of /tmp/fake.h)?
|
||||
tu = index.parse('fake.c', unsaved_files = [
|
||||
('fake.c', """
|
||||
#include "/tmp/fake.h"
|
||||
int x;
|
||||
int SOME_DEFINE;
|
||||
"""),
|
||||
('/tmp/fake.h', """
|
||||
#define SOME_DEFINE y
|
||||
""")
|
||||
])
|
||||
spellings = [c.spelling for c in tu.cursor.get_children()]
|
||||
assert spellings[-2] == 'x'
|
||||
assert spellings[-1] == 'y'
|
||||
|
||||
def test_unsaved_files_2():
|
||||
import StringIO
|
||||
index = Index.create()
|
||||
tu = index.parse('fake.c', unsaved_files = [
|
||||
('fake.c', StringIO.StringIO('int x;'))])
|
||||
spellings = [c.spelling for c in tu.cursor.get_children()]
|
||||
assert spellings[-1] == 'x'
|
||||
|
||||
|
||||
def test_includes():
|
||||
def eq(expected, actual):
|
||||
if not actual.is_input_file:
|
||||
return expected[0] == actual.source.name and \
|
||||
expected[1] == actual.include.name
|
||||
else:
|
||||
return expected[1] == actual.include.name
|
||||
|
||||
src = os.path.join(kInputsDir, 'include.cpp')
|
||||
h1 = os.path.join(kInputsDir, "header1.h")
|
||||
h2 = os.path.join(kInputsDir, "header2.h")
|
||||
h3 = os.path.join(kInputsDir, "header3.h")
|
||||
inc = [(None, src), (src, h1), (h1, h3), (src, h2), (h2, h3)]
|
||||
|
||||
index = Index.create()
|
||||
tu = index.parse(src)
|
||||
for i in zip(inc, tu.get_includes()):
|
||||
assert eq(i[0], i[1])
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,258 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Static Analyzer Design Document: Memory Regions</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Static Analyzer Design Document: Memory Regions</h1>
|
||||
|
||||
<h3>Authors</h3>
|
||||
|
||||
<p>Ted Kremenek, <tt>kremenek at apple</tt><br>
|
||||
Zhongxing Xu, <tt>xuzhongzhing at gmail</tt></p>
|
||||
|
||||
<h2 id="intro">Introduction</h2>
|
||||
|
||||
<p>The path-sensitive analysis engine in libAnalysis employs an extensible API
|
||||
for abstractly modeling the memory of an analyzed program. This API employs the
|
||||
concept of "memory regions" to abstractly model chunks of program memory such as
|
||||
program variables and dynamically allocated memory such as those returned from
|
||||
'malloc' and 'alloca'. Regions are hierarchical, with subregions modeling
|
||||
subtyping relationships, field and array offsets into larger chunks of memory,
|
||||
and so on.</p>
|
||||
|
||||
<p>The region API consists of two components:</p>
|
||||
|
||||
<ul> <li>A taxonomy and representation of regions themselves within the analyzer
|
||||
engine. The primary definitions and interfaces are described in <tt><a
|
||||
href="http://clang.llvm.org/doxygen/MemRegion_8h-source.html">MemRegion.h</a></tt>.
|
||||
At the root of the region hierarchy is the class <tt>MemRegion</tt> with
|
||||
specific subclasses refining the region concept for variables, heap allocated
|
||||
memory, and so forth.</li> <li>The modeling of binding of values to regions. For
|
||||
example, modeling the value stored to a local variable <tt>x</tt> consists of
|
||||
recording the binding between the region for <tt>x</tt> (which represents the
|
||||
raw memory associated with <tt>x</tt>) and the value stored to <tt>x</tt>. This
|
||||
binding relationship is captured with the notion of "symbolic
|
||||
stores."</li> </ul>
|
||||
|
||||
<p>Symbolic stores, which can be thought of as representing the relation
|
||||
<tt>regions -> values</tt>, are implemented by subclasses of the
|
||||
<tt>StoreManager</tt> class (<tt><a
|
||||
href="http://clang.llvm.org/doxygen/Store_8h-source.html">Store.h</a></tt>). A
|
||||
particular StoreManager implementation has complete flexibility concerning the
|
||||
following:
|
||||
|
||||
<ul>
|
||||
<li><em>How</em> to model the binding between regions and values</li>
|
||||
<li><em>What</em> bindings are recorded
|
||||
</ul>
|
||||
|
||||
<p>Together, both points allow different StoreManagers to tradeoff between
|
||||
different levels of analysis precision and scalability concerning the reasoning
|
||||
of program memory. Meanwhile, the core path-sensitive engine makes no
|
||||
assumptions about either points, and queries a StoreManager about the bindings
|
||||
to a memory region through a generic interface that all StoreManagers share. If
|
||||
a particular StoreManager cannot reason about the potential bindings of a given
|
||||
memory region (e.g., '<tt>BasicStoreManager</tt>' does not reason about fields
|
||||
of structures) then the StoreManager can simply return 'unknown' (represented by
|
||||
'<tt>UnknownVal</tt>') for a particular region-binding. This separation of
|
||||
concerns not only isolates the core analysis engine from the details of
|
||||
reasoning about program memory but also facilities the option of a client of the
|
||||
path-sensitive engine to easily swap in different StoreManager implementations
|
||||
that internally reason about program memory in very different ways.</pp>
|
||||
|
||||
<p>The rest of this document is divided into two parts. We first discuss region
|
||||
taxonomy and the semantics of regions. We then discuss the StoreManager
|
||||
interface, and details of how the currently available StoreManager classes
|
||||
implement region bindings.</p>
|
||||
|
||||
<h2 id="regions">Memory Regions and Region Taxonomy</h2>
|
||||
|
||||
<h3>Pointers</h3>
|
||||
|
||||
<p>Before talking about the memory regions, we would talk about the pointers
|
||||
since memory regions are essentially used to represent pointer values.</p>
|
||||
|
||||
<p>The pointer is a type of values. Pointer values have two semantic aspects.
|
||||
One is its physical value, which is an address or location. The other is the
|
||||
type of the memory object residing in the address.</p>
|
||||
|
||||
<p>Memory regions are designed to abstract these two properties of the pointer.
|
||||
The physical value of a pointer is represented by MemRegion pointers. The rvalue
|
||||
type of the region corresponds to the type of the pointee object.</p>
|
||||
|
||||
<p>One complication is that we could have different view regions on the same
|
||||
memory chunk. They represent the same memory location, but have different
|
||||
abstract location, i.e., MemRegion pointers. Thus we need to canonicalize the
|
||||
abstract locations to get a unique abstract location for one physical
|
||||
location.</p>
|
||||
|
||||
<p>Furthermore, these different view regions may or may not represent memory
|
||||
objects of different types. Some different types are semantically the same,
|
||||
for example, 'struct s' and 'my_type' are the same type.</p>
|
||||
|
||||
<pre>
|
||||
struct s;
|
||||
typedef struct s my_type;
|
||||
</pre>
|
||||
|
||||
<p>But <tt>char</tt> and <tt>int</tt> are not the same type in the code below:</p>
|
||||
|
||||
<pre>
|
||||
void *p;
|
||||
int *q = (int*) p;
|
||||
char *r = (char*) p;
|
||||
</pre
|
||||
|
||||
<p>Thus we need to canonicalize the MemRegion which is used in binding and
|
||||
retrieving.</p>
|
||||
|
||||
<h3>Regions</h3>
|
||||
<p>Region is the entity used to model pointer values. A Region has the following
|
||||
properties:</p>
|
||||
|
||||
<ul>
|
||||
<li>Kind</li>
|
||||
|
||||
<li>ObjectType: the type of the object residing on the region.</li>
|
||||
|
||||
<li>LocationType: the type of the pointer value that the region corresponds to.
|
||||
Usually this is the pointer to the ObjectType. But sometimes we want to cache
|
||||
this type explicitly, for example, for a CodeTextRegion.</li>
|
||||
|
||||
<li>StartLocation</li>
|
||||
|
||||
<li>EndLocation</li>
|
||||
</ul>
|
||||
|
||||
<h3>Symbolic Regions</h3>
|
||||
|
||||
<p>A symbolic region is a map of the concept of symbolic values into the domain
|
||||
of regions. It is the way that we represent symbolic pointers. Whenever a
|
||||
symbolic pointer value is needed, a symbolic region is created to represent
|
||||
it.</p>
|
||||
|
||||
<p>A symbolic region has no type. It wraps a SymbolData. But sometimes we have
|
||||
type information associated with a symbolic region. For this case, a
|
||||
TypedViewRegion is created to layer the type information on top of the symbolic
|
||||
region. The reason we do not carry type information with the symbolic region is
|
||||
that the symbolic regions can have no type. To be consistent, we don't let them
|
||||
to carry type information.</p>
|
||||
|
||||
<p>Like a symbolic pointer, a symbolic region may be NULL, has unknown extent,
|
||||
and represents a generic chunk of memory.</p>
|
||||
|
||||
<p><em><b>NOTE</b>: We plan not to use loc::SymbolVal in RegionStore and remove it
|
||||
gradually.</em></p>
|
||||
|
||||
<p>Symbolic regions get their rvalue types through the following ways:</p>
|
||||
|
||||
<ul>
|
||||
<li>Through the parameter or global variable that points to it, e.g.:
|
||||
<pre>
|
||||
void f(struct s* p) {
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The symbolic region pointed to by <tt>p</tt> has type <tt>struct
|
||||
s</tt>.</p></li>
|
||||
|
||||
<li>Through explicit or implicit casts, e.g.:
|
||||
<pre>
|
||||
void f(void* p) {
|
||||
struct s* q = (struct s*) p;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>We attach the type information to the symbolic region lazily. For the first
|
||||
case above, we create the <tt>TypedViewRegion</tt> only when the pointer is
|
||||
actually used to access the pointee memory object, that is when the element or
|
||||
field region is created. For the cast case, the <tt>TypedViewRegion</tt> is
|
||||
created when visiting the <tt>CastExpr</tt>.</p>
|
||||
|
||||
<p>The reason for doing lazy typing is that symbolic regions are sometimes only
|
||||
used to do location comparison.</p>
|
||||
|
||||
<h3>Pointer Casts</h3>
|
||||
|
||||
<p>Pointer casts allow people to impose different 'views' onto a chunk of
|
||||
memory.</p>
|
||||
|
||||
<p>Usually we have two kinds of casts. One kind of casts cast down with in the
|
||||
type hierarchy. It imposes more specific views onto more generic memory regions.
|
||||
The other kind of casts cast up with in the type hierarchy. It strips away more
|
||||
specific views on top of the more generic memory regions.</p>
|
||||
|
||||
<p>We simulate the down casts by layering another <tt>TypedViewRegion</tt> on
|
||||
top of the original region. We simulate the up casts by striping away the top
|
||||
<tt>TypedViewRegion</tt>. Down casts is usually simple. For up casts, if the
|
||||
there is no <tt>TypedViewRegion</tt> to be stripped, we return the original
|
||||
region. If the underlying region is of the different type than the cast-to type,
|
||||
we flag an error state.</p>
|
||||
|
||||
<p>For toll-free bridging casts, we return the original region.</p>
|
||||
|
||||
<p>We can set up a partial order for pointer types, with the most general type
|
||||
<tt>void*</tt> at the top. The partial order forms a tree with <tt>void*</tt> as
|
||||
its root node.</p>
|
||||
|
||||
<p>Every <tt>MemRegion</tt> has a root position in the type tree. For example,
|
||||
the pointee region of <tt>void *p</tt> has its root position at the root node of
|
||||
the tree. <tt>VarRegion</tt> of <tt>int x</tt> has its root position at the 'int
|
||||
type' node.</p>
|
||||
|
||||
<p><tt>TypedViewRegion</tt> is used to move the region down or up in the tree.
|
||||
Moving down in the tree adds a <tt>TypedViewRegion</tt>. Moving up in the tree
|
||||
removes a <Tt>TypedViewRegion</tt>.</p>
|
||||
|
||||
<p>Do we want to allow moving up beyond the root position? This happens
|
||||
when:</p> <pre> int x; void *p = &x; </pre>
|
||||
|
||||
<p>The region of <tt>x</tt> has its root position at 'int*' node. the cast to
|
||||
void* moves that region up to the 'void*' node. I propose to not allow such
|
||||
casts, and assign the region of <tt>x</tt> for <tt>p</tt>.</p>
|
||||
|
||||
<p>Another non-ideal case is that people might cast to a non-generic pointer
|
||||
from another non-generic pointer instead of first casting it back to the generic
|
||||
pointer. Direct handling of this case would result in multiple layers of
|
||||
TypedViewRegions. This enforces an incorrect semantic view to the region,
|
||||
because we can only have one typed view on a region at a time. To avoid this
|
||||
inconsistency, before casting the region, we strip the TypedViewRegion, then do
|
||||
the cast. In summary, we only allow one layer of TypedViewRegion.</p>
|
||||
|
||||
<h3>Region Bindings</h3>
|
||||
|
||||
<p>The following region kinds are boundable: VarRegion, CompoundLiteralRegion,
|
||||
StringRegion, ElementRegion, FieldRegion, and ObjCIvarRegion.</p>
|
||||
|
||||
<p>When binding regions, we perform canonicalization on element regions and field
|
||||
regions. This is because we can have different views on the same region, some
|
||||
of which are essentially the same view with different sugar type names.</p>
|
||||
|
||||
<p>To canonicalize a region, we get the canonical types for all TypedViewRegions
|
||||
along the way up to the root region, and make new TypedViewRegions with those
|
||||
canonical types.</p>
|
||||
|
||||
<p>For Objective-C and C++, perhaps another canonicalization rule should be
|
||||
added: for FieldRegion, the least derived class that has the field is used as
|
||||
the type of the super region of the FieldRegion.</p>
|
||||
|
||||
<p>All bindings and retrievings are done on the canonicalized regions.</p>
|
||||
|
||||
<p>Canonicalization is transparent outside the region store manager, and more
|
||||
specifically, unaware outside the Bind() and Retrieve() method. We don't need to
|
||||
consider region canonicalization when doing pointer cast.</p>
|
||||
|
||||
<h3>Constraint Manager</h3>
|
||||
|
||||
<p>The constraint manager reasons about the abstract location of memory objects.
|
||||
We can have different views on a region, but none of these views changes the
|
||||
location of that object. Thus we should get the same abstract location for those
|
||||
regions.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,670 +0,0 @@
|
||||
Block Implementation Specification
|
||||
|
||||
Copyright 2008-2010 Apple, Inc.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
0. History
|
||||
|
||||
2008/7/14 - created
|
||||
2008/8/21 - revised, C++
|
||||
2008/9/24 - add NULL isa field to __block storage
|
||||
2008/10/1 - revise block layout to use a static descriptor structure
|
||||
2008/10/6 - revise block layout to use an unsigned long int flags
|
||||
2008/10/28 - specify use of _Block_object_assign/dispose for all "Object" types in helper functions
|
||||
2008/10/30 - revise new layout to have invoke function in same place
|
||||
2008/10/30 - add __weak support
|
||||
|
||||
2010/3/16 - rev for stret return, signature field
|
||||
2010/4/6 - improved wording
|
||||
|
||||
This document describes the Apple ABI implementation specification of Blocks.
|
||||
|
||||
The first shipping version of this ABI is found in Mac OS X 10.6, and shall be referred to as 10.6.ABI. As of 2010/3/16, the following describes the ABI contract with the runtime and the compiler, and, as necessary, will be referred to as ABI.2010.3.16.
|
||||
|
||||
Since the Apple ABI references symbols from other elements of the system, any attempt to use this ABI on systems prior to SnowLeopard is undefined.
|
||||
|
||||
1. High Level
|
||||
|
||||
The ABI of blocks consist of their layout and the runtime functions required by the compiler.
|
||||
A Block consists of a structure of the following form:
|
||||
|
||||
struct Block_literal_1 {
|
||||
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(void *, ...);
|
||||
struct Block_descriptor_1 {
|
||||
unsigned long int reserved; // NULL
|
||||
unsigned long int size; // sizeof(struct Block_literal_1)
|
||||
// optional helper functions
|
||||
void (*copy_helper)(void *dst, void *src); // IFF (1<<25)
|
||||
void (*dispose_helper)(void *src); // IFF (1<<25)
|
||||
// required ABI.2010.3.16
|
||||
const char *signature; // IFF (1<<30)
|
||||
} *descriptor;
|
||||
// imported variables
|
||||
};
|
||||
|
||||
The following flags bits are in use thusly for a possible ABI.2010.3.16:
|
||||
|
||||
enum {
|
||||
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
|
||||
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
|
||||
BLOCK_IS_GLOBAL = (1 << 28),
|
||||
BLOCK_HAS_STRET = (1 << 29),
|
||||
BLOCK_HAS_SIGNATURE = (1 << 30),
|
||||
};
|
||||
|
||||
In 10.6.ABI the (1<<29) was unconditionally set and ignored by the runtime - it was a transitional marker that did not get deleted after the transition. This bit is now paired with (1<<30), and represented as the pair (3<<30), for the following combinations of valid bit settings, and their meanings.
|
||||
|
||||
switch (flags & (3<<29)) {
|
||||
case (0<<29): <unused> , error
|
||||
case (1<<29): 10.6.ABI, no signature field available
|
||||
case (2<<29): ABI.2010.3.16, regular calling convention, presence of signature field
|
||||
case (3<<29): ABI.2010.3.16, stret calling convention, presence of signature field,
|
||||
}
|
||||
|
||||
The following discussions are presented as 10.6.ABI otherwise.
|
||||
|
||||
Block literals may occur within functions where the structure is created in stack local memory. They may also appear as initialization expressions for Block variables of global or static local variables.
|
||||
|
||||
When a Block literal expression is evaluated the stack based structure is initialized as follows:
|
||||
|
||||
1) static descriptor structure is declared and initialized as follows:
|
||||
1a) the invoke function pointer is set to a function that takes the Block structure as its first argument and the rest of the arguments (if any) to the Block and executes the Block compound statement.
|
||||
1b) the size field is set to the size of the following Block literal structure.
|
||||
1c) the copy_helper and dispose_helper function pointers are set to respective helper functions if they are required by the Block literal
|
||||
2) a stack (or global) Block literal data structure is created and initialized as follows:
|
||||
2a) the isa field is set to the address of the external _NSConcreteStackBlock, which is a block of uninitialized memory supplied in libSystem, or _NSConcreteGlobalBlock if this is a static or file level block literal.
|
||||
2) The flags field is set to zero unless there are variables imported into the block that need helper functions for program level Block_copy() and Block_release() operations, in which case the (1<<25) flags bit is set.
|
||||
|
||||
|
||||
As an example, the Block literal expression
|
||||
^ { printf("hello world\n"); }
|
||||
would cause to be created on a 32-bit system:
|
||||
|
||||
struct __block_literal_1 {
|
||||
void *isa;
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(struct __block_literal_1 *);
|
||||
struct __block_descriptor_1 *descriptor;
|
||||
};
|
||||
|
||||
void __block_invoke_1(struct __block_literal_1 *_block) {
|
||||
printf("hello world\n");
|
||||
}
|
||||
|
||||
static struct __block_descriptor_1 {
|
||||
unsigned long int reserved;
|
||||
unsigned long int Block_size;
|
||||
} __block_descriptor_1 = { 0, sizeof(struct __block_literal_1), __block_invoke_1 };
|
||||
|
||||
and where the block literal appeared
|
||||
|
||||
struct __block_literal_1 _block_literal = {
|
||||
&_NSConcreteStackBlock,
|
||||
(1<<29), <uninitialized>,
|
||||
__block_invoke_1,
|
||||
&__block_descriptor_1
|
||||
};
|
||||
|
||||
Blocks import other Block references, const copies of other variables, and variables marked __block. In Objective-C variables may additionally be objects.
|
||||
|
||||
When a Block literal expression used as the initial value of a global or static local variable it is initialized as follows:
|
||||
struct __block_literal_1 __block_literal_1 = {
|
||||
&_NSConcreteGlobalBlock,
|
||||
(1<<28)|(1<<29), <uninitialized>,
|
||||
__block_invoke_1,
|
||||
&__block_descriptor_1
|
||||
};
|
||||
that is, a different address is provided as the first value and a particular (1<<28) bit is set in the flags field, and otherwise it is the same as for stack based Block literals. This is an optimization that can be used for any Block literal that imports no const or __block storage variables.
|
||||
|
||||
|
||||
2. Imported Variables
|
||||
|
||||
Variables of "auto" storage class are imported as const copies. Variables of "__block" storage class are imported as a pointer to an enclosing data structure. Global variables are simply referenced and not considered as imported.
|
||||
|
||||
2.1 Imported const copy variables
|
||||
|
||||
Automatic storage variables not marked with __block are imported as const copies.
|
||||
|
||||
The simplest example is that of importing a variable of type int.
|
||||
|
||||
int x = 10;
|
||||
void (^vv)(void) = ^{ printf("x is %d\n", x); }
|
||||
x = 11;
|
||||
vv();
|
||||
|
||||
would be compiled
|
||||
|
||||
struct __block_literal_2 {
|
||||
void *isa;
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(struct __block_literal_2 *);
|
||||
struct __block_descriptor_2 *descriptor;
|
||||
const int x;
|
||||
};
|
||||
|
||||
void __block_invoke_2(struct __block_literal_2 *_block) {
|
||||
printf("x is %d\n", _block->x);
|
||||
}
|
||||
|
||||
static struct __block_descriptor_2 {
|
||||
unsigned long int reserved;
|
||||
unsigned long int Block_size;
|
||||
} __block_descriptor_2 = { 0, sizeof(struct __block_literal_2) };
|
||||
|
||||
and
|
||||
|
||||
struct __block_literal_2 __block_literal_2 = {
|
||||
&_NSConcreteStackBlock,
|
||||
(1<<29), <uninitialized>,
|
||||
__block_invoke_2,
|
||||
&__block_descriptor_2,
|
||||
x
|
||||
};
|
||||
|
||||
In summary, scalars, structures, unions, and function pointers are generally imported as const copies with no need for helper functions.
|
||||
|
||||
2.2 Imported const copy of Block reference
|
||||
|
||||
The first case where copy and dispose helper functions are required is for the case of when a block itself is imported. In this case both a copy_helper function and a dispose_helper function are needed. The copy_helper function is passed both the existing stack based pointer and the pointer to the new heap version and should call back into the runtime to actually do the copy operation on the imported fields within the block. The runtime functions are all described in Section 5.0 Runtime Helper Functions.
|
||||
|
||||
An example:
|
||||
|
||||
void (^existingBlock)(void) = ...;
|
||||
void (^vv)(void) = ^{ existingBlock(); }
|
||||
vv();
|
||||
|
||||
struct __block_literal_3 {
|
||||
...; // existing block
|
||||
};
|
||||
|
||||
struct __block_literal_4 {
|
||||
void *isa;
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(struct __block_literal_4 *);
|
||||
struct __block_literal_3 *const existingBlock;
|
||||
};
|
||||
|
||||
void __block_invoke_4(struct __block_literal_2 *_block) {
|
||||
__block->existingBlock->invoke(__block->existingBlock);
|
||||
}
|
||||
|
||||
void __block_copy_4(struct __block_literal_4 *dst, struct __block_literal_4 *src) {
|
||||
//_Block_copy_assign(&dst->existingBlock, src->existingBlock, 0);
|
||||
_Block_object_assign(&dst->existingBlock, src->existingBlock, BLOCK_FIELD_IS_BLOCK);
|
||||
}
|
||||
|
||||
void __block_dispose_4(struct __block_literal_4 *src) {
|
||||
// was _Block_destroy
|
||||
_Block_object_dispose(src->existingBlock, BLOCK_FIELD_IS_BLOCK);
|
||||
}
|
||||
|
||||
static struct __block_descriptor_4 {
|
||||
unsigned long int reserved;
|
||||
unsigned long int Block_size;
|
||||
void (*copy_helper)(struct __block_literal_4 *dst, struct __block_literal_4 *src);
|
||||
void (*dispose_helper)(struct __block_literal_4 *);
|
||||
} __block_descriptor_4 = {
|
||||
0,
|
||||
sizeof(struct __block_literal_4),
|
||||
__block_copy_4,
|
||||
__block_dispose_4,
|
||||
};
|
||||
|
||||
and where it is used
|
||||
|
||||
struct __block_literal_4 _block_literal = {
|
||||
&_NSConcreteStackBlock,
|
||||
(1<<25)|(1<<29), <uninitialized>
|
||||
__block_invoke_4,
|
||||
& __block_descriptor_4
|
||||
existingBlock,
|
||||
};
|
||||
|
||||
2.2.1 Importing __attribute__((NSObject)) variables.
|
||||
|
||||
GCC introduces __attribute__((NSObject)) on structure pointers to mean "this is an object". This is useful because many low level data structures are declared as opaque structure pointers, e.g. CFStringRef, CFArrayRef, etc. When used from C, however, these are still really objects and are the second case where that requires copy and dispose helper functions to be generated. The copy helper functions generated by the compiler should use the _Block_object_assign runtime helper function and in the dispose helper the _Block_object_dispose runtime helper function should be called.
|
||||
|
||||
For example, block xyzzy in the following
|
||||
|
||||
struct Opaque *__attribute__((NSObject)) objectPointer = ...;
|
||||
...
|
||||
void (^xyzzy)(void) = ^{ CFPrint(objectPointer); };
|
||||
|
||||
would have helper functions
|
||||
|
||||
void __block_copy_xyzzy(struct __block_literal_5 *dst, struct __block_literal_5 *src) {
|
||||
_Block_object_assign(&dst->objectPointer, src-> objectPointer, BLOCK_FIELD_IS_OBJECT);
|
||||
}
|
||||
|
||||
void __block_dispose_xyzzy(struct __block_literal_5 *src) {
|
||||
_Block_object_dispose(src->objectPointer, BLOCK_FIELD_IS_OBJECT);
|
||||
}
|
||||
|
||||
generated.
|
||||
|
||||
|
||||
2.3 Imported __block marked variables.
|
||||
|
||||
2.3.1 Layout of __block marked variables
|
||||
|
||||
The compiler must embed variables that are marked __block in a specialized structure of the form:
|
||||
|
||||
struct _block_byref_xxxx {
|
||||
void *isa;
|
||||
struct Block_byref *forwarding;
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
typeof(marked_variable) marked_variable;
|
||||
};
|
||||
|
||||
Variables of certain types require helper functions for when Block_copy() and Block_release() are performed upon a referencing Block. At the "C" level only variables that are of type Block or ones that have __attribute__((NSObject)) marked require helper functions. In Objective-C objects require helper functions and in C++ stack based objects require helper functions. Variables that require helper functions use the form:
|
||||
|
||||
struct _block_byref_xxxx {
|
||||
void *isa;
|
||||
struct _block_byref_xxxx *forwarding;
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
// helper functions called via Block_copy() and Block_release()
|
||||
void (*byref_keep)(void *dst, void *src);
|
||||
void (*byref_dispose)(void *);
|
||||
typeof(marked_variable) marked_variable;
|
||||
};
|
||||
|
||||
The structure is initialized such that
|
||||
a) the forwarding pointer is set to the beginning of its enclosing structure,
|
||||
b) the size field is initialized to the total size of the enclosing structure,
|
||||
c) the flags field is set to either 0 if no helper functions are needed or (1<<25) if they are,
|
||||
d) the helper functions are initialized (if present)
|
||||
e) the variable itself is set to its initial value.
|
||||
f) the isa field is set to NULL
|
||||
|
||||
2.3.2 Access to __block variables from within its lexical scope.
|
||||
|
||||
In order to "move" the variable to the heap upon a copy_helper operation the compiler must rewrite access to such a variable to be indirect through the structures forwarding pointer. For example:
|
||||
|
||||
int __block i = 10;
|
||||
i = 11;
|
||||
|
||||
would be rewritten to be:
|
||||
|
||||
struct _block_byref_i {
|
||||
void *isa;
|
||||
struct _block_byref_i *forwarding;
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
int captured_i;
|
||||
} i = { NULL, &i, 0, sizeof(struct _block_byref_i), 11 };
|
||||
|
||||
i.forwarding->captured_i = 11;
|
||||
|
||||
In the case of a Block reference variable being marked __block the helper code generated must use the _Block_object_assign and _Block_object_dispose routines supplied by the runtime to make the copies. For example:
|
||||
|
||||
__block void (voidBlock)(void) = blockA;
|
||||
voidBlock = blockB;
|
||||
|
||||
would translate into
|
||||
|
||||
struct _block_byref_voidBlock {
|
||||
void *isa;
|
||||
struct _block_byref_voidBlock *forwarding;
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
void (*byref_keep)(struct _block_byref_voidBlock *dst, struct _block_byref_voidBlock *src);
|
||||
void (*byref_dispose)(struct _block_byref_voidBlock *);
|
||||
void (^captured_voidBlock)(void);
|
||||
};
|
||||
|
||||
void _block_byref_keep_helper(struct _block_byref_voidBlock *dst, struct _block_byref_voidBlock *src) {
|
||||
//_Block_copy_assign(&dst->captured_voidBlock, src->captured_voidBlock, 0);
|
||||
_Block_object_assign(&dst->captured_voidBlock, src->captured_voidBlock, BLOCK_FIELD_IS_BLOCK | BLOCK_BYREF_CALLER);
|
||||
}
|
||||
|
||||
void _block_byref_dispose_helper(struct _block_byref_voidBlock *param) {
|
||||
//_Block_destroy(param->captured_voidBlock, 0);
|
||||
_Block_object_dispose(param->captured_voidBlock, BLOCK_FIELD_IS_BLOCK | BLOCK_BYREF_CALLER)}
|
||||
|
||||
and
|
||||
struct _block_byref_voidBlock voidBlock = {( .forwarding=&voidBlock, .flags=(1<<25), .size=sizeof(struct _block_byref_voidBlock *),
|
||||
.byref_keep=_block_byref_keep_helper, .byref_dispose=_block_byref_dispose_helper,
|
||||
.captured_voidBlock=blockA };
|
||||
|
||||
voidBlock.forwarding->captured_voidBlock = blockB;
|
||||
|
||||
|
||||
2.3.3 Importing __block variables into Blocks
|
||||
|
||||
A Block that uses a __block variable in its compound statement body must import the variable and emit copy_helper and dispose_helper helper functions that, in turn, call back into the runtime to actually copy or release the byref data block using the functions _Block_object_assign and _Block_object_dispose.
|
||||
|
||||
For example:
|
||||
|
||||
int __block i = 2;
|
||||
functioncall(^{ i = 10; });
|
||||
|
||||
would translate to
|
||||
|
||||
struct _block_byref_i {
|
||||
void *isa; // set to NULL
|
||||
struct _block_byref_voidBlock *forwarding;
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
void (*byref_keep)(struct _block_byref_i *dst, struct _block_byref_i *src);
|
||||
void (*byref_dispose)(struct _block_byref_i *);
|
||||
int captured_i;
|
||||
};
|
||||
|
||||
|
||||
struct __block_literal_5 {
|
||||
void *isa;
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(struct __block_literal_5 *);
|
||||
struct __block_descriptor_5 *descriptor;
|
||||
struct _block_byref_i *i_holder;
|
||||
};
|
||||
|
||||
void __block_invoke_5(struct __block_literal_5 *_block) {
|
||||
_block->forwarding->captured_i = 10;
|
||||
}
|
||||
|
||||
void __block_copy_5(struct __block_literal_5 *dst, struct __block_literal_5 *src) {
|
||||
//_Block_byref_assign_copy(&dst->captured_i, src->captured_i);
|
||||
_Block_object_assign(&dst->captured_i, src->captured_i, BLOCK_FIELD_IS_BYREF | BLOCK_BYREF_CALLER);
|
||||
}
|
||||
|
||||
void __block_dispose_5(struct __block_literal_5 *src) {
|
||||
//_Block_byref_release(src->captured_i);
|
||||
_Block_object_dispose(src->captured_i, BLOCK_FIELD_IS_BYREF | BLOCK_BYREF_CALLER);
|
||||
}
|
||||
|
||||
static struct __block_descriptor_5 {
|
||||
unsigned long int reserved;
|
||||
unsigned long int Block_size;
|
||||
void (*copy_helper)(struct __block_literal_5 *dst, struct __block_literal_5 *src);
|
||||
void (*dispose_helper)(struct __block_literal_5 *);
|
||||
} __block_descriptor_5 = { 0, sizeof(struct __block_literal_5) __block_copy_5, __block_dispose_5 };
|
||||
|
||||
and
|
||||
|
||||
struct _block_byref_i i = {( .forwarding=&i, .flags=0, .size=sizeof(struct _block_byref_i) )};
|
||||
struct __block_literal_5 _block_literal = {
|
||||
&_NSConcreteStackBlock,
|
||||
(1<<25)|(1<<29), <uninitialized>,
|
||||
__block_invoke_5,
|
||||
&__block_descriptor_5,
|
||||
2,
|
||||
};
|
||||
|
||||
2.3.4 Importing __attribute__((NSObject)) __block variables
|
||||
|
||||
A __block variable that is also marked __attribute__((NSObject)) should have byref_keep and byref_dispose helper functions that use _Block_object_assign and _Block_object_dispose.
|
||||
|
||||
2.3.5 __block escapes
|
||||
|
||||
Because Blocks referencing __block variables may have Block_copy() performed upon them the underlying storage for the variables may move to the heap. In Objective-C Garbage Collection Only compilation environments the heap used is the garbage collected one and no further action is required. Otherwise the compiler must issue a call to potentially release any heap storage for __block variables at all escapes or terminations of their scope.
|
||||
|
||||
|
||||
2.3.6 Nesting
|
||||
|
||||
Blocks may contain Block literal expressions. Any variables used within inner blocks are imported into all enclosing Block scopes even if the variables are not used. This includes const imports as well as __block variables.
|
||||
|
||||
3. Objective C Extensions to Blocks
|
||||
|
||||
3.1 Importing Objects
|
||||
|
||||
Objects should be treated as __attribute__((NSObject)) variables; all copy_helper, dispose_helper, byref_keep, and byref_dispose helper functions should use _Block_object_assign and _Block_object_dispose. There should be no code generated that uses -retain or -release methods.
|
||||
|
||||
|
||||
3.2 Blocks as Objects
|
||||
|
||||
The compiler will treat Blocks as objects when synthesizing property setters and getters, will characterize them as objects when generating garbage collection strong and weak layout information in the same manner as objects, and will issue strong and weak write-barrier assignments in the same manner as objects.
|
||||
|
||||
3.3 __weak __block Support
|
||||
|
||||
Objective-C (and Objective-C++) support the __weak attribute on __block variables. Under normal circumstances the compiler uses the Objective-C runtime helper support functions objc_assign_weak and objc_read_weak. Both should continue to be used for all reads and writes of __weak __block variables:
|
||||
objc_read_weak(&block->byref_i->forwarding->i)
|
||||
|
||||
The __weak variable is stored in a _block_byref_xxxx structure and the Block has copy and dispose helpers for this structure that call:
|
||||
_Block_object_assign(&dest->_block_byref_i, src-> _block_byref_i, BLOCK_FIELD_IS_WEAK | BLOCK_FIELD_IS_BYREF);
|
||||
and
|
||||
_Block_object_dispose(src->_block_byref_i, BLOCK_FIELD_IS_WEAK | BLOCK_FIELD_IS_BYREF);
|
||||
|
||||
|
||||
In turn, the block_byref copy support helpers distinguish between whether the __block variable is a Block or not and should either call:
|
||||
_Block_object_assign(&dest->_block_byref_i, src->_block_byref_i, BLOCK_FIELD_IS_WEAK | BLOCK_FIELD_IS_OBJECT | BLOCK_BYREF_CALLER);
|
||||
for something declared as an object or
|
||||
_Block_object_assign(&dest->_block_byref_i, src->_block_byref_i, BLOCK_FIELD_IS_WEAK | BLOCK_FIELD_IS_BLOCK | BLOCK_BYREF_CALLER);
|
||||
for something declared as a Block.
|
||||
|
||||
A full example follows:
|
||||
|
||||
|
||||
__block __weak id obj = <initialization expression>;
|
||||
functioncall(^{ [obj somemessage]; });
|
||||
|
||||
would translate to
|
||||
|
||||
struct _block_byref_obj {
|
||||
void *isa; // uninitialized
|
||||
struct _block_byref_obj *forwarding;
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
void (*byref_keep)(struct _block_byref_i *dst, struct _block_byref_i *src);
|
||||
void (*byref_dispose)(struct _block_byref_i *);
|
||||
int captured_obj;
|
||||
};
|
||||
|
||||
void _block_byref_obj_keep(struct _block_byref_voidBlock *dst, struct _block_byref_voidBlock *src) {
|
||||
//_Block_copy_assign(&dst->captured_obj, src->captured_obj, 0);
|
||||
_Block_object_assign(&dst->captured_obj, src->captured_obj, BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK | BLOCK_BYREF_CALLER);
|
||||
}
|
||||
|
||||
void _block_byref_obj_dispose(struct _block_byref_voidBlock *param) {
|
||||
//_Block_destroy(param->captured_obj, 0);
|
||||
_Block_object_dispose(param->captured_obj, BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK | BLOCK_BYREF_CALLER);
|
||||
};
|
||||
|
||||
for the block byref part and
|
||||
|
||||
struct __block_literal_5 {
|
||||
void *isa;
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(struct __block_literal_5 *);
|
||||
struct __block_descriptor_5 *descriptor;
|
||||
struct _block_byref_obj *byref_obj;
|
||||
};
|
||||
|
||||
void __block_invoke_5(struct __block_literal_5 *_block) {
|
||||
[objc_read_weak(&_block->byref_obj->forwarding->captured_obj) somemessage];
|
||||
}
|
||||
|
||||
void __block_copy_5(struct __block_literal_5 *dst, struct __block_literal_5 *src) {
|
||||
//_Block_byref_assign_copy(&dst->byref_obj, src->byref_obj);
|
||||
_Block_object_assign(&dst->byref_obj, src->byref_obj, BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK);
|
||||
}
|
||||
|
||||
void __block_dispose_5(struct __block_literal_5 *src) {
|
||||
//_Block_byref_release(src->byref_obj);
|
||||
_Block_object_dispose(src->byref_obj, BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK);
|
||||
}
|
||||
|
||||
static struct __block_descriptor_5 {
|
||||
unsigned long int reserved;
|
||||
unsigned long int Block_size;
|
||||
void (*copy_helper)(struct __block_literal_5 *dst, struct __block_literal_5 *src);
|
||||
void (*dispose_helper)(struct __block_literal_5 *);
|
||||
} __block_descriptor_5 = { 0, sizeof(struct __block_literal_5), __block_copy_5, __block_dispose_5 };
|
||||
|
||||
and within the compound statement:
|
||||
|
||||
struct _block_byref_obj obj = {( .forwarding=&obj, .flags=(1<<25), .size=sizeof(struct _block_byref_obj),
|
||||
.byref_keep=_block_byref_obj_keep, .byref_dispose=_block_byref_obj_dispose,
|
||||
.captured_obj = <initialization expression> )};
|
||||
|
||||
struct __block_literal_5 _block_literal = {
|
||||
&_NSConcreteStackBlock,
|
||||
(1<<25)|(1<<29), <uninitialized>,
|
||||
__block_invoke_5,
|
||||
&__block_descriptor_5,
|
||||
&obj, // a reference to the on-stack structure containing "captured_obj"
|
||||
};
|
||||
|
||||
|
||||
functioncall(_block_literal->invoke(&_block_literal));
|
||||
|
||||
|
||||
4.0 C++ Support
|
||||
|
||||
Within a block stack based C++ objects are copied as const copies using the const copy constructor. It is an error if a stack based C++ object is used within a block if it does not have a const copy constructor. In addition both copy and destroy helper routines must be synthesized for the block to support the Block_copy() operation, and the flags work marked with the (1<<26) bit in addition to the (1<<25) bit. The copy helper should call the constructor using appropriate offsets of the variable within the supplied stack based block source and heap based destination for all const constructed copies, and similarly should call the destructor in the destroy routine.
|
||||
|
||||
As an example, suppose a C++ class FOO existed with a const copy constructor. Within a code block a stack version of a FOO object is declared and used within a Block literal expression:
|
||||
|
||||
{
|
||||
FOO foo;
|
||||
void (^block)(void) = ^{ printf("%d\n", foo.value()); };
|
||||
}
|
||||
|
||||
The compiler would synthesize
|
||||
|
||||
struct __block_literal_10 {
|
||||
void *isa;
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(struct __block_literal_10 *);
|
||||
struct __block_descriptor_10 *descriptor;
|
||||
const FOO foo;
|
||||
};
|
||||
|
||||
void __block_invoke_10(struct __block_literal_10 *_block) {
|
||||
printf("%d\n", _block->foo.value());
|
||||
}
|
||||
|
||||
void __block_literal_10(struct __block_literal_10 *dst, struct __block_literal_10 *src) {
|
||||
comp_ctor(&dst->foo, &src->foo);
|
||||
}
|
||||
|
||||
void __block_dispose_10(struct __block_literal_10 *src) {
|
||||
comp_dtor(&src->foo);
|
||||
}
|
||||
|
||||
static struct __block_descriptor_10 {
|
||||
unsigned long int reserved;
|
||||
unsigned long int Block_size;
|
||||
void (*copy_helper)(struct __block_literal_10 *dst, struct __block_literal_10 *src);
|
||||
void (*dispose_helper)(struct __block_literal_10 *);
|
||||
} __block_descriptor_10 = { 0, sizeof(struct __block_literal_10), __block_copy_10, __block_dispose_10 };
|
||||
|
||||
and the code would be:
|
||||
{
|
||||
FOO foo;
|
||||
comp_ctor(&foo); // default constructor
|
||||
struct __block_literal_10 _block_literal = {
|
||||
&_NSConcreteStackBlock,
|
||||
(1<<25)|(1<<26)|(1<<29), <uninitialized>,
|
||||
__block_invoke_10,
|
||||
&__block_descriptor_10,
|
||||
};
|
||||
comp_ctor(&_block_literal->foo, &foo); // const copy into stack version
|
||||
struct __block_literal_10 &block = &_block_literal; // assign literal to block variable
|
||||
block->invoke(block); // invoke block
|
||||
comp_dtor(&_block_literal->foo); // destroy stack version of const block copy
|
||||
comp_dtor(&foo); // destroy original version
|
||||
}
|
||||
|
||||
|
||||
C++ objects stored in __block storage start out on the stack in a block_byref data structure as do other variables. Such objects (if not const objects) must support a regular copy constructor. The block_byref data structure will have copy and destroy helper routines synthesized by the compiler. The copy helper will have code created to perform the copy constructor based on the initial stack block_byref data structure, and will also set the (1<<26) bit in addition to the (1<<25) bit. The destroy helper will have code to do the destructor on the object stored within the supplied block_byref heap data structure.
|
||||
|
||||
To support member variable and function access the compiler will synthesize a const pointer to a block version of the this pointer.
|
||||
|
||||
5.0 Runtime Helper Functions
|
||||
|
||||
The runtime helper functions are described in /usr/local/include/Block_private.h. To summarize their use, a block requires copy/dispose helpers if it imports any block variables, __block storage variables, __attribute__((NSObject)) variables, or C++ const copied objects with constructor/destructors. The (1<<26) bit is set and functions are generated.
|
||||
|
||||
The block copy helper function should, for each of the variables of the type mentioned above, call
|
||||
_Block_object_assign(&dst->target, src->target, BLOCK_FIELD_<appropo>);
|
||||
in the copy helper and
|
||||
_Block_object_dispose(->target, BLOCK_FIELD_<appropo>);
|
||||
in the dispose helper where
|
||||
<appropo> is
|
||||
|
||||
enum {
|
||||
BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ...
|
||||
BLOCK_FIELD_IS_BLOCK = 7, // a block variable
|
||||
BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable
|
||||
|
||||
BLOCK_FIELD_IS_WEAK = 16, // declared __weak
|
||||
|
||||
BLOCK_BYREF_CALLER = 128, // called from byref copy/dispose helpers
|
||||
};
|
||||
|
||||
and of course the CTORs/DTORs for const copied C++ objects.
|
||||
|
||||
The block_byref data structure similarly requires copy/dispose helpers for block variables, __attribute__((NSObject)) variables, or C++ const copied objects with constructor/destructors, and again the (1<<26) bit is set and functions are generated in the same manner.
|
||||
|
||||
Under ObjC we allow __weak as an attribute on __block variables, and this causes the addition of BLOCK_FIELD_IS_WEAK orred onto the BLOCK_FIELD_IS_BYREF flag when copying the block_byref structure in the block copy helper, and onto the BLOCK_FIELD_<appropo> field within the block_byref copy/dispose helper calls.
|
||||
|
||||
The prototypes, and summary, of the helper functions are
|
||||
|
||||
/* Certain field types require runtime assistance when being copied to the heap. The following function is used
|
||||
to copy fields of types: blocks, pointers to byref structures, and objects (including __attribute__((NSObject)) pointers.
|
||||
BLOCK_FIELD_IS_WEAK is orthogonal to the other choices which are mutually exclusive.
|
||||
Only in a Block copy helper will one see BLOCK_FIELD_IS_BYREF.
|
||||
*/
|
||||
void _Block_object_assign(void *destAddr, const void *object, const int flags);
|
||||
|
||||
/* Similarly a compiler generated dispose helper needs to call back for each field of the byref data structure.
|
||||
(Currently the implementation only packs one field into the byref structure but in principle there could be more).
|
||||
The same flags used in the copy helper should be used for each call generated to this function:
|
||||
*/
|
||||
void _Block_object_dispose(const void *object, const int flags);
|
||||
|
||||
The following functions have been used and will continue to be supported until new compiler support is complete.
|
||||
|
||||
// Obsolete functions.
|
||||
// Copy helper callback for copying a block imported into a Block
|
||||
// Called by copy_helper helper functions synthesized by the compiler.
|
||||
// The address in the destination block of an imported Block is provided as the first argument
|
||||
// and the value of the existing imported Block is the second.
|
||||
// Use: _Block_object_assign(dest, src, BLOCK_FIELD_IS_BLOCK {| BLOCK_FIELD_IS_WEAK});
|
||||
void _Block_copy_assign(struct Block_basic **dest, const struct Block_basic *src, const int flags);
|
||||
|
||||
// Destroy helper callback for releasing Blocks imported into a Block
|
||||
// Called by dispose_helper helper functions synthesized by the compiler.
|
||||
// The value of the imported Block variable is passed back.
|
||||
// Use: _Block_object_dispose(src, BLOCK_FIELD_IS_BLOCK {| BLOCK_FIELD_IS_WEAK});
|
||||
void _Block_destroy(const struct Block_basic *src, const int flags);
|
||||
|
||||
// Byref data block copy helper callback
|
||||
// Called by block copy helpers when copying __block structures
|
||||
// Use: _Block_object_assign(dest, src, BLOCK_FIELD_IS_BYREF {| BLOCK_FIELD_IS_WEAK});
|
||||
void _Block_byref_assign_copy(struct Block_byref **destp, struct Block_byref *src);
|
||||
|
||||
// Byref data block release helper callback
|
||||
// Called by block release helpers when releasing a Block
|
||||
// Called at escape points in scope where __block variables live (under non-GC-only conditions)
|
||||
// Use: _Block_object_dispose(src, BLOCK_FIELD_IS_BYREF {| BLOCK_FIELD_IS_WEAK});
|
||||
void <20>(struct Block_byref *shared_struct);
|
||||
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
Language Specification for Blocks
|
||||
|
||||
2008/2/25 — created
|
||||
2008/7/28 — revised, __block syntax
|
||||
2008/8/13 — revised, Block globals
|
||||
2008/8/21 — revised, C++ elaboration
|
||||
2008/11/1 — revised, __weak support
|
||||
2009/1/12 — revised, explicit return types
|
||||
2009/2/10 — revised, __block objects need retain
|
||||
|
||||
Copyright 2008-2009 Apple, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
The Block Type
|
||||
|
||||
A new derived type is introduced to C and, by extension, Objective-C, C++, and Objective-C++. Like function types, the Block type is a pair consisting of a result value type and a list of parameter types very similar to a function type. Blocks are intended to be used much like functions with the key distinction being that in addition to executable code they also contain various variable bindings to automatic (stack) or managed (heap) memory.
|
||||
|
||||
The abstract declarator int (^)(char, float) describes a reference to a Block that, when invoked, takes two parameters, the first of type char and the second of type float, and returns a value of type int. The Block referenced is of opaque data that may reside in automatic (stack) memory, global memory, or heap memory.
|
||||
|
||||
|
||||
Block Variable Declarations
|
||||
|
||||
A variable with Block type is declared using function pointer style notation substituting ^ for *. The following are valid Block variable declarations:
|
||||
void (^blockReturningVoidWithVoidArgument)(void);
|
||||
int (^blockReturningIntWithIntAndCharArguments)(int, char);
|
||||
void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(int);
|
||||
|
||||
Variadic ... arguments are supported. [variadic.c] A Block that takes no arguments must specify void in the argument list [voidarg.c]. An empty parameter list does not represent, as K&R provide, an unspecified argument list. Note: both gcc and clang support K&R style as a convenience.
|
||||
|
||||
A Block reference may be cast to a pointer of arbitrary type and vice versa. [cast.c] A Block reference may not be dereferenced via the pointer dereference operator *, and thus a Block's size may not be computed at compile time. [sizeof.c]
|
||||
|
||||
|
||||
Block Literal Expressions
|
||||
|
||||
A Block literal expression produces a reference to a Block. It is introduced by the use of the ^ token as a unary operator.
|
||||
Block_literal_expression ::= ^ block_decl compound_statement_body
|
||||
block_decl ::=
|
||||
block_decl ::= parameter_list
|
||||
block_decl ::= type_expression
|
||||
|
||||
...where type expression is extended to allow ^ as a Block reference (pointer) where * is allowed as a function reference (pointer).
|
||||
|
||||
The following Block literal:
|
||||
^ void (void) { printf("hello world\n"); }
|
||||
|
||||
...produces a reference to a Block with no arguments with no return value.
|
||||
|
||||
The return type is optional and is inferred from the return statements. If the return statements return a value, they all must return a value of the same type. If there is no value returned the inferred type of the Block is void; otherwise it is the type of the return statement value.
|
||||
|
||||
If the return type is omitted and the argument list is ( void ), the ( void ) argument list may also be omitted.
|
||||
|
||||
So:
|
||||
^ ( void ) { printf("hello world\n"); }
|
||||
|
||||
...and:
|
||||
^ { printf("hello world\n"); }
|
||||
|
||||
...are exactly equivalent constructs for the same expression.
|
||||
|
||||
The type_expression extends C expression parsing to accommodate Block reference declarations as it accommodates function pointer declarations.
|
||||
|
||||
Given:
|
||||
typedef int (*pointerToFunctionThatReturnsIntWithCharArg)(char);
|
||||
pointerToFunctionThatReturnsIntWithCharArg functionPointer;
|
||||
|
||||
^ pointerToFunctionThatReturnsIntWithCharArg (float x) { return functionPointer; }
|
||||
|
||||
...and:
|
||||
^ int ((*)(float x))(char) { return functionPointer; }
|
||||
|
||||
...are equivalent expressions, as is:
|
||||
|
||||
^(float x) { return functionPointer; }
|
||||
|
||||
[returnfunctionptr.c]
|
||||
|
||||
The compound statement body establishes a new lexical scope within that of its parent. Variables used within the scope of the compound statement are bound to the Block in the normal manner with the exception of those in automatic (stack) storage. Thus one may access functions and global variables as one would expect, as well as static local variables. [testme]
|
||||
|
||||
Local automatic (stack) variables referenced within the compound statement of a Block are imported and captured by the Block as const copies. The capture (binding) is performed at the time of the Block literal expression evaluation.
|
||||
|
||||
The lifetime of variables declared in a Block is that of a function; each activation frame contains a new copy of variables declared within the local scope of the Block. Such variable declarations should be allowed anywhere [testme] rather than only when C99 parsing is requested, including for statements. [testme]
|
||||
|
||||
Block literal expressions may occur within Block literal expressions (nest) and all variables captured by any nested blocks are implicitly also captured in the scopes of their enclosing Blocks.
|
||||
|
||||
A Block literal expression may be used as the initialization value for Block variables at global or local static scope.
|
||||
|
||||
|
||||
The Invoke Operator
|
||||
|
||||
Blocks are invoked using function call syntax with a list of expression parameters of types corresponding to the declaration and returning a result type also according to the declaration. Given:
|
||||
int (^x)(char);
|
||||
void (^z)(void);
|
||||
int (^(*y))(char) = &x;
|
||||
|
||||
...the following are all legal Block invocations:
|
||||
x('a');
|
||||
(*y)('a');
|
||||
(true ? x : *y)('a')
|
||||
|
||||
|
||||
The Copy and Release Operations
|
||||
|
||||
The compiler and runtime provide copy and release operations for Block references that create and, in matched use, release allocated storage for referenced Blocks.
|
||||
|
||||
The copy operation Block_copy() is styled as a function that takes an arbitrary Block reference and returns a Block reference of the same type. The release operation, Block_release(), is styled as a function that takes an arbitrary Block reference and, if dynamically matched to a Block copy operation, allows recovery of the referenced allocated memory.
|
||||
|
||||
|
||||
The __block Storage Qualifier
|
||||
|
||||
In addition to the new Block type we also introduce a new storage qualifier, __block, for local variables. [testme: a __block declaration within a block literal] The __block storage qualifier is mutually exclusive to the existing local storage qualifiers auto, register, and static.[testme] Variables qualified by __block act as if they were in allocated storage and this storage is automatically recovered after last use of said variable. An implementation may choose an optimization where the storage is initially automatic and only "moved" to allocated (heap) storage upon a Block_copy of a referencing Block. Such variables may be mutated as normal variables are.
|
||||
|
||||
In the case where a __block variable is a Block one must assume that the __block variable resides in allocated storage and as such is assumed to reference a Block that is also in allocated storage (that it is the result of a Block_copy operation). Despite this there is no provision to do a Block_copy or a Block_release if an implementation provides initial automatic storage for Blocks. This is due to the inherent race condition of potentially several threads trying to update the shared variable and the need for synchronization around disposing of older values and copying new ones. Such synchronization is beyond the scope of this language specification.
|
||||
|
||||
|
||||
Control Flow
|
||||
|
||||
The compound statement of a Block is treated much like a function body with respect to control flow in that goto, break, and continue do not escape the Block. Exceptions are treated "normally" in that when thrown they pop stack frames until a catch clause is found.
|
||||
|
||||
|
||||
Objective-C Extensions
|
||||
|
||||
Objective-C extends the definition of a Block reference type to be that also of id. A variable or expression of Block type may be messaged or used as a parameter wherever an id may be. The converse is also true. Block references may thus appear as properties and are subject to the assign, retain, and copy attribute logic that is reserved for objects.
|
||||
|
||||
All Blocks are constructed to be Objective-C objects regardless of whether the Objective-C runtime is operational in the program or not. Blocks using automatic (stack) memory are objects and may be messaged, although they may not be assigned into __weak locations if garbage collection is enabled.
|
||||
|
||||
Within a Block literal expression within a method definition references to instance variables are also imported into the lexical scope of the compound statement. These variables are implicitly qualified as references from self, and so self is imported as a const copy. The net effect is that instance variables can be mutated.
|
||||
|
||||
The Block_copy operator retains all objects held in variables of automatic storage referenced within the Block expression (or form strong references if running under garbage collection). Object variables of __block storage type are assumed to hold normal pointers with no provision for retain and release messages.
|
||||
|
||||
Foundation defines (and supplies) -copy and -release methods for Blocks.
|
||||
|
||||
In the Objective-C and Objective-C++ languages, we allow the __weak specifier for __block variables of object type. If garbage collection is not enabled, this qualifier causes these variables to be kept without retain messages being sent. This knowingly leads to dangling pointers if the Block (or a copy) outlives the lifetime of this object.
|
||||
|
||||
In garbage collected environments, the __weak variable is set to nil when the object it references is collected, as long as the __block variable resides in the heap (either by default or via Block_copy()). The initial Apple implementation does in fact start __block variables on the stack and migrate them to the heap only as a result of a Block_copy() operation.
|
||||
|
||||
It is a runtime error to attempt to assign a reference to a stack-based Block into any storage marked __weak, including __weak __block variables.
|
||||
|
||||
|
||||
C++ Extensions
|
||||
|
||||
Block literal expressions within functions are extended to allow const use of C++ objects, pointers, or references held in automatic storage.
|
||||
|
||||
For example, given class Foo with member function fighter(void):
|
||||
Foo foo;
|
||||
Foo &fooRef = foo;
|
||||
Foo *fooPtr = &foo;
|
||||
|
||||
...a Block that used foo would import the variables as const variations:
|
||||
const Foo block_foo = foo; // const copy constructor
|
||||
const Foo &block_fooRef = fooRef;
|
||||
const Foo *block_fooPtr = fooPtr;
|
||||
|
||||
Stack-local objects are copied into a Block via a copy const constructor. If no such constructor exists, it is considered an error to reference such objects from within the Block compound statements. A destructor is run as control leaves the compound statement that contains the Block literal expression.
|
||||
|
||||
If a Block originates on the stack, a const copy constructor of the stack-based Block const copy is performed when a Block_copy operation is called; when the last Block_release (or subsequently GC) occurs, a destructor is run on the heap copy.
|
||||
|
||||
Variables declared as residing in __block storage may be initially allocated in the heap or may first appear on the stack and be copied to the heap as a result of a Block_copy() operation. When copied from the stack, a normal copy constructor is used to initialize the heap-based version from the original stack version. The destructor for a const copied object is run at the normal end of scope. The destructor for any initial stack based version is also called at normal end of scope.
|
||||
|
||||
Within a member function, access to member functions and variables is done via an implicit const copy of a this pointer.
|
||||
|
||||
Member variables that are Blocks may not be overloaded by the types of their arguments.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB |
@@ -1,517 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Clang Driver Manual</title>
|
||||
<link type="text/css" rel="stylesheet" href="../menu.css" />
|
||||
<link type="text/css" rel="stylesheet" href="../content.css" />
|
||||
<style type="text/css">
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--#include virtual="../menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Driver Design & Internals</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="#intro">Introduction</a></li>
|
||||
<li><a href="#features">Features and Goals</a></li>
|
||||
<ul>
|
||||
<li><a href="#gcccompat">GCC Compatibility</a></li>
|
||||
<li><a href="#components">Flexible</a></li>
|
||||
<li><a href="#performance">Low Overhead</a></li>
|
||||
<li><a href="#simple">Simple</a></li>
|
||||
</ul>
|
||||
<li><a href="#design">Design</a></li>
|
||||
<ul>
|
||||
<li><a href="#int_intro">Internals Introduction</a></li>
|
||||
<li><a href="#int_overview">Design Overview</a></li>
|
||||
<li><a href="#int_notes">Additional Notes</a></li>
|
||||
<ul>
|
||||
<li><a href="#int_compilation">The Compilation Object</a></li>
|
||||
<li><a href="#int_unified_parsing">Unified Parsing & Pipelining</a></li>
|
||||
<li><a href="#int_toolchain_translation">ToolChain Argument Translation</a></li>
|
||||
<li><a href="#int_unused_warnings">Unused Argument Warnings</a></li>
|
||||
</ul>
|
||||
<li><a href="#int_gcc_concepts">Relation to GCC Driver Concepts</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="intro">Introduction</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This document describes the Clang driver. The purpose of this
|
||||
document is to describe both the motivation and design goals
|
||||
for the driver, as well as details of the internal
|
||||
implementation.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="features">Features and Goals</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The Clang driver is intended to be a production quality
|
||||
compiler driver providing access to the Clang compiler and
|
||||
tools, with a command line interface which is compatible with
|
||||
the gcc driver.</p>
|
||||
|
||||
<p>Although the driver is part of and driven by the Clang
|
||||
project, it is logically a separate tool which shares many of
|
||||
the same goals as Clang:</p>
|
||||
|
||||
<p><b>Features</b>:</p>
|
||||
<ul>
|
||||
<li><a href="#gcccompat">GCC Compatibility</a></li>
|
||||
<li><a href="#components">Flexible</a></li>
|
||||
<li><a href="#performance">Low Overhead</a></li>
|
||||
<li><a href="#simple">Simple</a></li>
|
||||
</ul>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3 id="gcccompat">GCC Compatibility</h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<p>The number one goal of the driver is to ease the adoption of
|
||||
Clang by allowing users to drop Clang into a build system
|
||||
which was designed to call GCC. Although this makes the driver
|
||||
much more complicated than might otherwise be necessary, we
|
||||
decided that being very compatible with the gcc command line
|
||||
interface was worth it in order to allow users to quickly test
|
||||
clang on their projects.</p>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3 id="components">Flexible</h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<p>The driver was designed to be flexible and easily accomodate
|
||||
new uses as we grow the clang and LLVM infrastructure. As one
|
||||
example, the driver can easily support the introduction of
|
||||
tools which have an integrated assembler; something we hope to
|
||||
add to LLVM in the future.</p>
|
||||
|
||||
<p>Similarly, most of the driver functionality is kept in a
|
||||
library which can be used to build other tools which want to
|
||||
implement or accept a gcc like interface. </p>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3 id="performance">Low Overhead</h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<p>The driver should have as little overhead as possible. In
|
||||
practice, we found that the gcc driver by itself incurred a
|
||||
small but meaningful overhead when compiling many small
|
||||
files. The driver doesn't do much work compared to a
|
||||
compilation, but we have tried to keep it as efficient as
|
||||
possible by following a few simple principles:</p>
|
||||
<ul>
|
||||
<li>Avoid memory allocation and string copying when
|
||||
possible.</li>
|
||||
|
||||
<li>Don't parse arguments more than once.</li>
|
||||
|
||||
<li>Provide a few simple interfaces for efficiently searching
|
||||
arguments.</li>
|
||||
</ul>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3 id="simple">Simple</h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<p>Finally, the driver was designed to be "as simple as
|
||||
possible", given the other goals. Notably, trying to be
|
||||
completely compatible with the gcc driver adds a significant
|
||||
amount of complexity. However, the design of the driver
|
||||
attempts to mitigate this complexity by dividing the process
|
||||
into a number of independent stages instead of a single
|
||||
monolithic task.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="design">Internal Design and Implementation</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<ul>
|
||||
<li><a href="#int_intro">Internals Introduction</a></li>
|
||||
<li><a href="#int_overview">Design Overview</a></li>
|
||||
<li><a href="#int_notes">Additional Notes</a></li>
|
||||
<li><a href="#int_gcc_concepts">Relation to GCC Driver Concepts</a></li>
|
||||
</ul>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3><a name="int_intro">Internals Introduction</a></h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<p>In order to satisfy the stated goals, the driver was designed
|
||||
to completely subsume the functionality of the gcc executable;
|
||||
that is, the driver should not need to delegate to gcc to
|
||||
perform subtasks. On Darwin, this implies that the Clang
|
||||
driver also subsumes the gcc driver-driver, which is used to
|
||||
implement support for building universal images (binaries and
|
||||
object files). This also implies that the driver should be
|
||||
able to call the language specific compilers (e.g. cc1)
|
||||
directly, which means that it must have enough information to
|
||||
forward command line arguments to child processes
|
||||
correctly.</p>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3><a name="int_overview">Design Overview</a></h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<p>The diagram below shows the significant components of the
|
||||
driver architecture and how they relate to one another. The
|
||||
orange components represent concrete data structures built by
|
||||
the driver, the green components indicate conceptually
|
||||
distinct stages which manipulate these data structures, and
|
||||
the blue components are important helper classes. </p>
|
||||
|
||||
<center>
|
||||
<a href="DriverArchitecture.png" alt="Driver Architecture Diagram">
|
||||
<img width=400 src="DriverArchitecture.png">
|
||||
</a>
|
||||
</center>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3><a name="int_stages">Driver Stages</a></h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<p>The driver functionality is conceptually divided into five stages:</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<b>Parse: Option Parsing</b>
|
||||
|
||||
<p>The command line argument strings are decomposed into
|
||||
arguments (<tt>Arg</tt> instances). The driver expects to
|
||||
understand all available options, although there is some
|
||||
facility for just passing certain classes of options
|
||||
through (like <tt>-Wl,</tt>).</p>
|
||||
|
||||
<p>Each argument corresponds to exactly one
|
||||
abstract <tt>Option</tt> definition, which describes how
|
||||
the option is parsed along with some additional
|
||||
metadata. The Arg instances themselves are lightweight and
|
||||
merely contain enough information for clients to determine
|
||||
which option they correspond to and their values (if they
|
||||
have additional parameters).</p>
|
||||
|
||||
<p>For example, a command line like "-Ifoo -I foo" would
|
||||
parse to two Arg instances (a JoinedArg and a SeparateArg
|
||||
instance), but each would refer to the same Option.</p>
|
||||
|
||||
<p>Options are lazily created in order to avoid populating
|
||||
all Option classes when the driver is loaded. Most of the
|
||||
driver code only needs to deal with options by their
|
||||
unique ID (e.g., <tt>options::OPT_I</tt>),</p>
|
||||
|
||||
<p>Arg instances themselves do not generally store the
|
||||
values of parameters. In many cases, this would
|
||||
simply result in creating unnecessary string
|
||||
copies. Instead, Arg instances are always embedded inside
|
||||
an ArgList structure, which contains the original vector
|
||||
of argument strings. Each Arg itself only needs to contain
|
||||
an index into this vector instead of storing its values
|
||||
directly.</p>
|
||||
|
||||
<p>The clang driver can dump the results of this
|
||||
stage using the <tt>-ccc-print-options</tt> flag (which
|
||||
must preceed any actual command line arguments). For
|
||||
example:</p>
|
||||
<pre>
|
||||
$ <b>clang -ccc-print-options -Xarch_i386 -fomit-frame-pointer -Wa,-fast -Ifoo -I foo t.c</b>
|
||||
Option 0 - Name: "-Xarch_", Values: {"i386", "-fomit-frame-pointer"}
|
||||
Option 1 - Name: "-Wa,", Values: {"-fast"}
|
||||
Option 2 - Name: "-I", Values: {"foo"}
|
||||
Option 3 - Name: "-I", Values: {"foo"}
|
||||
Option 4 - Name: "<input>", Values: {"t.c"}
|
||||
</pre>
|
||||
|
||||
<p>After this stage is complete the command line should be
|
||||
broken down into well defined option objects with their
|
||||
appropriate parameters. Subsequent stages should rarely,
|
||||
if ever, need to do any string processing.</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Pipeline: Compilation Job Construction</b>
|
||||
|
||||
<p>Once the arguments are parsed, the tree of subprocess
|
||||
jobs needed for the desired compilation sequence are
|
||||
constructed. This involves determining the input files and
|
||||
their types, what work is to be done on them (preprocess,
|
||||
compile, assemble, link, etc.), and constructing a list of
|
||||
Action instances for each task. The result is a list of
|
||||
one or more top-level actions, each of which generally
|
||||
corresponds to a single output (for example, an object or
|
||||
linked executable).</p>
|
||||
|
||||
<p>The majority of Actions correspond to actual tasks,
|
||||
however there are two special Actions. The first is
|
||||
InputAction, which simply serves to adapt an input
|
||||
argument for use as an input to other Actions. The second
|
||||
is BindArchAction, which conceptually alters the
|
||||
architecture to be used for all of its input Actions.</p>
|
||||
|
||||
<p>The clang driver can dump the results of this
|
||||
stage using the <tt>-ccc-print-phases</tt> flag. For
|
||||
example:</p>
|
||||
<pre>
|
||||
$ <b>clang -ccc-print-phases -x c t.c -x assembler t.s</b>
|
||||
0: input, "t.c", c
|
||||
1: preprocessor, {0}, cpp-output
|
||||
2: compiler, {1}, assembler
|
||||
3: assembler, {2}, object
|
||||
4: input, "t.s", assembler
|
||||
5: assembler, {4}, object
|
||||
6: linker, {3, 5}, image
|
||||
</pre>
|
||||
<p>Here the driver is constructing seven distinct actions,
|
||||
four to compile the "t.c" input into an object file, two to
|
||||
assemble the "t.s" input, and one to link them together.</p>
|
||||
|
||||
<p>A rather different compilation pipeline is shown here; in
|
||||
this example there are two top level actions to compile
|
||||
the input files into two separate object files, where each
|
||||
object file is built using <tt>lipo</tt> to merge results
|
||||
built for two separate architectures.</p>
|
||||
<pre>
|
||||
$ <b>clang -ccc-print-phases -c -arch i386 -arch x86_64 t0.c t1.c</b>
|
||||
0: input, "t0.c", c
|
||||
1: preprocessor, {0}, cpp-output
|
||||
2: compiler, {1}, assembler
|
||||
3: assembler, {2}, object
|
||||
4: bind-arch, "i386", {3}, object
|
||||
5: bind-arch, "x86_64", {3}, object
|
||||
6: lipo, {4, 5}, object
|
||||
7: input, "t1.c", c
|
||||
8: preprocessor, {7}, cpp-output
|
||||
9: compiler, {8}, assembler
|
||||
10: assembler, {9}, object
|
||||
11: bind-arch, "i386", {10}, object
|
||||
12: bind-arch, "x86_64", {10}, object
|
||||
13: lipo, {11, 12}, object
|
||||
</pre>
|
||||
|
||||
<p>After this stage is complete the compilation process is
|
||||
divided into a simple set of actions which need to be
|
||||
performed to produce intermediate or final outputs (in
|
||||
some cases, like <tt>-fsyntax-only</tt>, there is no
|
||||
"real" final output). Phases are well known compilation
|
||||
steps, such as "preprocess", "compile", "assemble",
|
||||
"link", etc.</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Bind: Tool & Filename Selection</b>
|
||||
|
||||
<p>This stage (in conjunction with the Translate stage)
|
||||
turns the tree of Actions into a list of actual subprocess
|
||||
to run. Conceptually, the driver performs a top down
|
||||
matching to assign Action(s) to Tools. The ToolChain is
|
||||
responsible for selecting the tool to perform a particular
|
||||
action; once selected the driver interacts with the tool
|
||||
to see if it can match additional actions (for example, by
|
||||
having an integrated preprocessor).
|
||||
|
||||
<p>Once Tools have been selected for all actions, the driver
|
||||
determines how the tools should be connected (for example,
|
||||
using an inprocess module, pipes, temporary files, or user
|
||||
provided filenames). If an output file is required, the
|
||||
driver also computes the appropriate file name (the suffix
|
||||
and file location depend on the input types and options
|
||||
such as <tt>-save-temps</tt>).
|
||||
|
||||
<p>The driver interacts with a ToolChain to perform the Tool
|
||||
bindings. Each ToolChain contains information about all
|
||||
the tools needed for compilation for a particular
|
||||
architecture, platform, and operating system. A single
|
||||
driver invocation may query multiple ToolChains during one
|
||||
compilation in order to interact with tools for separate
|
||||
architectures.</p>
|
||||
|
||||
<p>The results of this stage are not computed directly, but
|
||||
the driver can print the results via
|
||||
the <tt>-ccc-print-bindings</tt> option. For example:</p>
|
||||
<pre>
|
||||
$ <b>clang -ccc-print-bindings -arch i386 -arch ppc t0.c</b>
|
||||
# "i386-apple-darwin9" - "clang", inputs: ["t0.c"], output: "/tmp/cc-Sn4RKF.s"
|
||||
# "i386-apple-darwin9" - "darwin::Assemble", inputs: ["/tmp/cc-Sn4RKF.s"], output: "/tmp/cc-gvSnbS.o"
|
||||
# "i386-apple-darwin9" - "darwin::Link", inputs: ["/tmp/cc-gvSnbS.o"], output: "/tmp/cc-jgHQxi.out"
|
||||
# "ppc-apple-darwin9" - "gcc::Compile", inputs: ["t0.c"], output: "/tmp/cc-Q0bTox.s"
|
||||
# "ppc-apple-darwin9" - "gcc::Assemble", inputs: ["/tmp/cc-Q0bTox.s"], output: "/tmp/cc-WCdicw.o"
|
||||
# "ppc-apple-darwin9" - "gcc::Link", inputs: ["/tmp/cc-WCdicw.o"], output: "/tmp/cc-HHBEBh.out"
|
||||
# "i386-apple-darwin9" - "darwin::Lipo", inputs: ["/tmp/cc-jgHQxi.out", "/tmp/cc-HHBEBh.out"], output: "a.out"
|
||||
</pre>
|
||||
|
||||
<p>This shows the tool chain, tool, inputs and outputs which
|
||||
have been bound for this compilation sequence. Here clang
|
||||
is being used to compile t0.c on the i386 architecture and
|
||||
darwin specific versions of the tools are being used to
|
||||
assemble and link the result, but generic gcc versions of
|
||||
the tools are being used on PowerPC.</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Translate: Tool Specific Argument Translation</b>
|
||||
|
||||
<p>Once a Tool has been selected to perform a particular
|
||||
Action, the Tool must construct concrete Jobs which will be
|
||||
executed during compilation. The main work is in translating
|
||||
from the gcc style command line options to whatever options
|
||||
the subprocess expects.</p>
|
||||
|
||||
<p>Some tools, such as the assembler, only interact with a
|
||||
handful of arguments and just determine the path of the
|
||||
executable to call and pass on their input and output
|
||||
arguments. Others, like the compiler or the linker, may
|
||||
translate a large number of arguments in addition.</p>
|
||||
|
||||
<p>The ArgList class provides a number of simple helper
|
||||
methods to assist with translating arguments; for example,
|
||||
to pass on only the last of arguments corresponding to some
|
||||
option, or all arguments for an option.</p>
|
||||
|
||||
<p>The result of this stage is a list of Jobs (executable
|
||||
paths and argument strings) to execute.</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Execute</b>
|
||||
<p>Finally, the compilation pipeline is executed. This is
|
||||
mostly straightforward, although there is some interaction
|
||||
with options
|
||||
like <tt>-pipe</tt>, <tt>-pass-exit-codes</tt>
|
||||
and <tt>-time</tt>.</p>
|
||||
</li>
|
||||
|
||||
</ol>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3><a name="int_notes">Additional Notes</a></h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<h4 id="int_compilation">The Compilation Object</h4>
|
||||
|
||||
<p>The driver constructs a Compilation object for each set of
|
||||
command line arguments. The Driver itself is intended to be
|
||||
invariant during construction of a Compilation; an IDE should be
|
||||
able to construct a single long lived driver instance to use
|
||||
for an entire build, for example.</p>
|
||||
|
||||
<p>The Compilation object holds information that is particular
|
||||
to each compilation sequence. For example, the list of used
|
||||
temporary files (which must be removed once compilation is
|
||||
finished) and result files (which should be removed if
|
||||
compilation files).</p>
|
||||
|
||||
<h4 id="int_unified_parsing">Unified Parsing & Pipelining</h4>
|
||||
|
||||
<p>Parsing and pipelining both occur without reference to a
|
||||
Compilation instance. This is by design; the driver expects that
|
||||
both of these phases are platform neutral, with a few very well
|
||||
defined exceptions such as whether the platform uses a driver
|
||||
driver.</p>
|
||||
|
||||
<h4 id="int_toolchain_translation">ToolChain Argument Translation</h4>
|
||||
|
||||
<p>In order to match gcc very closely, the clang driver
|
||||
currently allows tool chains to perform their own translation of
|
||||
the argument list (into a new ArgList data structure). Although
|
||||
this allows the clang driver to match gcc easily, it also makes
|
||||
the driver operation much harder to understand (since the Tools
|
||||
stop seeing some arguments the user provided, and see new ones
|
||||
instead).</p>
|
||||
|
||||
<p>For example, on Darwin <tt>-gfull</tt> gets translated into two
|
||||
separate arguments, <tt>-g</tt>
|
||||
and <tt>-fno-eliminate-unused-debug-symbols</tt>. Trying to write Tool
|
||||
logic to do something with <tt>-gfull</tt> will not work, because Tool
|
||||
argument translation is done after the arguments have been
|
||||
translated.</p>
|
||||
|
||||
<p>A long term goal is to remove this tool chain specific
|
||||
translation, and instead force each tool to change its own logic
|
||||
to do the right thing on the untranslated original arguments.</p>
|
||||
|
||||
<h4 id="int_unused_warnings">Unused Argument Warnings</h4>
|
||||
<p>The driver operates by parsing all arguments but giving Tools
|
||||
the opportunity to choose which arguments to pass on. One
|
||||
downside of this infrastructure is that if the user misspells
|
||||
some option, or is confused about which options to use, some
|
||||
command line arguments the user really cared about may go
|
||||
unused. This problem is particularly important when using
|
||||
clang as a compiler, since the clang compiler does not support
|
||||
anywhere near all the options that gcc does, and we want to make
|
||||
sure users know which ones are being used.</p>
|
||||
|
||||
<p>To support this, the driver maintains a bit associated with
|
||||
each argument of whether it has been used (at all) during the
|
||||
compilation. This bit usually doesn't need to be set by hand,
|
||||
as the key ArgList accessors will set it automatically.</p>
|
||||
|
||||
<p>When a compilation is successful (there are no errors), the
|
||||
driver checks the bit and emits an "unused argument" warning for
|
||||
any arguments which were never accessed. This is conservative
|
||||
(the argument may not have been used to do what the user wanted)
|
||||
but still catches the most obvious cases.</p>
|
||||
|
||||
<!--=======================================================================-->
|
||||
<h3><a name="int_gcc_concepts">Relation to GCC Driver Concepts</a></h3>
|
||||
<!--=======================================================================-->
|
||||
|
||||
<p>For those familiar with the gcc driver, this section provides
|
||||
a brief overview of how things from the gcc driver map to the
|
||||
clang driver.</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>Driver Driver</b>
|
||||
<p>The driver driver is fully integrated into the clang
|
||||
driver. The driver simply constructs additional Actions to
|
||||
bind the architecture during the <i>Pipeline</i>
|
||||
phase. The tool chain specific argument translation is
|
||||
responsible for handling <tt>-Xarch_</tt>.</p>
|
||||
|
||||
<p>The one caveat is that this approach
|
||||
requires <tt>-Xarch_</tt> not be used to alter the
|
||||
compilation itself (for example, one cannot
|
||||
provide <tt>-S</tt> as an <tt>-Xarch_</tt> argument). The
|
||||
driver attempts to reject such invocations, and overall
|
||||
there isn't a good reason to abuse <tt>-Xarch_</tt> to
|
||||
that end in practice.</p>
|
||||
|
||||
<p>The upside is that the clang driver is more efficient and
|
||||
does little extra work to support universal builds. It also
|
||||
provides better error reporting and UI consistency.</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Specs</b>
|
||||
<p>The clang driver has no direct correspondant for
|
||||
"specs". The majority of the functionality that is
|
||||
embedded in specs is in the Tool specific argument
|
||||
translation routines. The parts of specs which control the
|
||||
compilation pipeline are generally part of
|
||||
the <ii>Pipeline</ii> stage.</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Toolchains</b>
|
||||
<p>The gcc driver has no direct understanding of tool
|
||||
chains. Each gcc binary roughly corresponds to the
|
||||
information which is embedded inside a single
|
||||
ToolChain.</p>
|
||||
|
||||
<p>The clang driver is intended to be portable and support
|
||||
complex compilation environments. All platform and tool
|
||||
chain specific code should be protected behind either
|
||||
abstract or well defined interfaces (such as whether the
|
||||
platform supports use as a driver driver).</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,666 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Clang Language Extensions</title>
|
||||
<link type="text/css" rel="stylesheet" href="../menu.css" />
|
||||
<link type="text/css" rel="stylesheet" href="../content.css" />
|
||||
<style type="text/css">
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--#include virtual="../menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Clang Language Extensions</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="#intro">Introduction</a></li>
|
||||
<li><a href="#feature_check">Feature Checking Macros</a></li>
|
||||
<li><a href="#has_include">Include File Checking Macros</a></li>
|
||||
<li><a href="#builtinmacros">Builtin Macros</a></li>
|
||||
<li><a href="#vectors">Vectors and Extended Vectors</a></li>
|
||||
<li><a href="#checking_language_features">Checks for Standard Language Features</a></li>
|
||||
<ul>
|
||||
<li><a href="#cxx_exceptions">C++ exceptions</a></li>
|
||||
<li><a href="#cxx_rtti">C++ RTTI</a></li>
|
||||
</ul>
|
||||
<li><a href="#checking_upcoming_features">Checks for Upcoming Standard Language Features</a></li>
|
||||
<ul>
|
||||
<li><a href="#cxx_attributes">C++0x attributes</a></li>
|
||||
<li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li>
|
||||
<li><a href="#cxx_deleted_functions">C++0x deleted functions</a></li>
|
||||
<li><a href="#cxx_concepts">C++ TR concepts</a></li>
|
||||
<li><a href="#cxx_lambdas">C++0x lambdas</a></li>
|
||||
<li><a href="#cxx_nullptr">C++0x nullptr</a></li>
|
||||
<li><a href="#cxx_rvalue_references">C++0x rvalue references</a></li>
|
||||
<li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li>
|
||||
<li><a href="#cxx_auto_type">C++0x type inference</a></li>
|
||||
<li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
|
||||
<li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
|
||||
</ul>
|
||||
<li><a href="#blocks">Blocks</a></li>
|
||||
<li><a href="#overloading-in-c">Function Overloading in C</a></li>
|
||||
<li><a href="#builtins">Builtin Functions</a>
|
||||
<ul>
|
||||
<li><a href="#__builtin_shufflevector">__builtin_shufflevector</a></li>
|
||||
<li><a href="#__builtin_unreachable">__builtin_unreachable</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#targetspecific">Target-Specific Extensions</a>
|
||||
<ul>
|
||||
<li><a href="#x86-specific">X86/X86-64 Language Extensions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#analyzerspecific">Static Analysis-Specific Extensions</a>
|
||||
<ul>
|
||||
<li><a href="#analyzerattributes">Analyzer Attributes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="intro">Introduction</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This document describes the language extensions provided by Clang. In
|
||||
addition to the language extensions listed here, Clang aims to support a broad
|
||||
range of GCC extensions. Please see the <a
|
||||
href="http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html">GCC manual</a> for
|
||||
more information on these extensions.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="feature_check">Feature Checking Macros</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Language extensions can be very useful, but only if you know you can depend
|
||||
on them. In order to allow fine-grain features checks, we support two builtin
|
||||
function-like macros. This allows you to directly test for a feature in your
|
||||
code without having to resort to something like autoconf or fragile "compiler
|
||||
version checks".</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__has_builtin">__has_builtin</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This function-like macro takes a single identifier argument that is the name
|
||||
of a builtin function. It evaluates to 1 if the builtin is supported or 0 if
|
||||
not. It can be used like this:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#ifndef __has_builtin // Optional of course.
|
||||
#define __has_builtin(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
...
|
||||
#if __has_builtin(__builtin_trap)
|
||||
__builtin_trap();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__has_feature">__has_feature</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This function-like macro takes a single identifier argument that is the name
|
||||
of a feature. It evaluates to 1 if the feature is supported or 0 if not. It
|
||||
can be used like this:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#ifndef __has_feature // Optional of course.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
...
|
||||
#if __has_feature(attribute_overloadable) || \
|
||||
__has_feature(blocks)
|
||||
...
|
||||
#endif
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>The feature tag is described along with the language feature below.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="has_include">Include File Checking Macros</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Not all developments systems have the same include files.
|
||||
The <a href="#__has_include">__has_include</a> and
|
||||
<a href="#__has_include_next">__has_include_next</a> macros allow you to
|
||||
check for the existence of an include file before doing
|
||||
a possibly failing #include directive.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__has_include">__has_include</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This function-like macro takes a single file name string argument that
|
||||
is the name of an include file. It evaluates to 1 if the file can
|
||||
be found using the include paths, or 0 otherwise:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// Note the two possible file name string formats.
|
||||
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
|
||||
# include "myinclude.h"
|
||||
#endif
|
||||
|
||||
// To avoid problem with non-clang compilers not having this macro.
|
||||
#if defined(__has_include) && __has_include("myinclude.h")
|
||||
# include "myinclude.h"
|
||||
#endif
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>To test for this feature, use #if defined(__has_include).</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__has_include_next">__has_include_next</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This function-like macro takes a single file name string argument that
|
||||
is the name of an include file. It is like __has_include except that it
|
||||
looks for the second instance of the given file found in the include
|
||||
paths. It evaluates to 1 if the second instance of the file can
|
||||
be found using the include paths, or 0 otherwise:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// Note the two possible file name string formats.
|
||||
#if __has_include_next("myinclude.h") && __has_include_next(<stdint.h>)
|
||||
# include_next "myinclude.h"
|
||||
#endif
|
||||
|
||||
// To avoid problem with non-clang compilers not having this macro.
|
||||
#if defined(__has_include_next) && __has_include_next("myinclude.h")
|
||||
# include_next "myinclude.h"
|
||||
#endif
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Note that __has_include_next, like the GNU extension
|
||||
#include_next directive, is intended for use in headers only,
|
||||
and will issue a warning if used in the top-level compilation
|
||||
file. A warning will also be issued if an absolute path
|
||||
is used in the file argument.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="builtinmacros">Builtin Macros</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<dl>
|
||||
<dt><code>__BASE_FILE__</code></dt>
|
||||
<dd>Defined to a string that contains the name of the main input
|
||||
file passed to Clang.</dd>
|
||||
|
||||
<dt><code>__COUNTER__</code></dt>
|
||||
<dd>Defined to an integer value that starts at zero and is
|
||||
incremented each time the <code>__COUNTER__</code> macro is
|
||||
expanded.</dd>
|
||||
|
||||
<dt><code>__INCLUDE_LEVEL__</code></dt>
|
||||
<dd>Defined to an integral value that is the include depth of the
|
||||
file currently being translated. For the main file, this value is
|
||||
zero.</dd>
|
||||
|
||||
<dt><code>__TIMESTAMP__</code></dt>
|
||||
<dd>Defined to the date and time of the last modification of the
|
||||
current source file.</dd>
|
||||
|
||||
<dt><code>__clang__</code></dt>
|
||||
<dd>Defined when compiling with Clang</dd>
|
||||
|
||||
<dt><code>__clang_major__</code></dt>
|
||||
<dd>Defined to the major version number of Clang (e.g., the 2 in
|
||||
2.0.1).</dd>
|
||||
|
||||
<dt><code>__clang_minor__</code></dt>
|
||||
<dd>Defined to the minor version number of Clang (e.g., the 0 in
|
||||
2.0.1).</dd>
|
||||
|
||||
<dt><code>__clang_patchlevel__</code></dt>
|
||||
<dd>Defined to the patch level of Clang (e.g., the 1 in 2.0.1).</dd>
|
||||
|
||||
<dt><code>__clang_version__</code></dt>
|
||||
<dd>Defined to a string that captures the Clang version, including
|
||||
the Subversion tag or revision number, e.g., "1.5 (trunk
|
||||
102332)".</dd>
|
||||
</dl>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="vectors">Vectors and Extended Vectors</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Supports the GCC vector extensions, plus some stuff like V[1].</p>
|
||||
|
||||
<p>Also supports <tt>ext_vector</tt>, which additionally support for V.xyzw
|
||||
syntax and other tidbits as seen in OpenCL. An example is:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
typedef float float4 <b>__attribute__((ext_vector_type(4)))</b>;
|
||||
typedef float float2 <b>__attribute__((ext_vector_type(2)))</b>;
|
||||
|
||||
float4 foo(float2 a, float2 b) {
|
||||
float4 c;
|
||||
c.xz = a;
|
||||
c.yw = b;
|
||||
return c;
|
||||
}
|
||||
</blockquote>
|
||||
|
||||
<p>Query for this feature with __has_feature(attribute_ext_vector_type).</p>
|
||||
|
||||
<p>See also <a href="#__builtin_shufflevector">__builtin_shufflevector</a>.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="checking_language_features">Checks for Standard Language Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The <tt>__has_feature</tt> macro can be used to query if certain standard language features are
|
||||
enabled. Those features are listed here.</p>
|
||||
|
||||
<h3 id="cxx_exceptions">C++ exceptions</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_exceptions)</tt> to determine if C++ exceptions have been enabled. For
|
||||
example, compiling code with <tt>-fexceptions</tt> enables C++ exceptions.</p>
|
||||
|
||||
<h3 id="cxx_rtti">C++ RTTI</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_rtti)</tt> to determine if C++ RTTI has been enabled. For example,
|
||||
compiling code with <tt>-fno-rtti</tt> disables the use of RTTI.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="checking_upcoming_features">Checks for Upcoming Standard Language Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The <tt>__has_feature</tt> macro can be used to query if certain upcoming
|
||||
standard language features are enabled. Those features are listed here.</p>
|
||||
|
||||
<p>Currently, all features listed here are slated for inclusion in the upcoming
|
||||
C++0x standard. As a result, all the features that clang supports are enabled
|
||||
with the <tt>-std=c++0x</tt> option when compiling C++ code. Features that are
|
||||
not yet implemented will be noted.</p>
|
||||
|
||||
<h3 id="cxx_decltype">C++0x <tt>decltype()</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_decltype)</tt> to determine if support for the
|
||||
<tt>decltype()</tt> specifier is enabled.</p>
|
||||
|
||||
<h3 id="cxx_attributes">C++0x attributes</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_attributes)</tt> to determine if support for
|
||||
attribute parsing with C++0x's square bracket notation is enabled.</p>
|
||||
|
||||
<h3 id="cxx_deleted_functions">C++0x deleted functions</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_deleted_functions)</tt> to determine if support for
|
||||
deleted function definitions (with <tt>= delete</tt>) is enabled.</p>
|
||||
|
||||
<h3 id="cxx_concepts">C++ TR concepts</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_concepts)</tt> to determine if support for
|
||||
concepts is enabled. clang does not currently implement this feature.</p>
|
||||
|
||||
<h3 id="cxx_lambdas">C++0x lambdas</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_lambdas)</tt> to determine if support for
|
||||
lambdas is enabled. clang does not currently implement this feature.</p>
|
||||
|
||||
<h3 id="cxx_nullptr">C++0x <tt>nullptr</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_nullptr)</tt> to determine if support for
|
||||
<tt>nullptr</tt> is enabled. clang does not yet fully implement this
|
||||
feature.</p>
|
||||
|
||||
<h3 id="cxx_rvalue_references">C++0x rvalue references</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_rvalue_references)</tt> to determine if support for
|
||||
rvalue references is enabled. clang does not yet fully implement this
|
||||
feature.</p>
|
||||
|
||||
<h3 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_static_assert)</tt> to determine if support for
|
||||
compile-time assertions using <tt>static_assert</tt> is enabled.</p>
|
||||
|
||||
<h3 id="cxx_auto_type">C++0x type inference</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_auto_type)</tt> to determine C++0x type inference
|
||||
is supported using the <tt>auto</tt> specifier. If this is disabled,
|
||||
<tt>auto</tt> will instead be a storage class specifier, as in C or C++98.</p>
|
||||
|
||||
<h3 id="cxx_variadic_templates">C++0x variadic templates</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> to determine if support
|
||||
for templates taking any number of arguments with the ellipsis notation is
|
||||
enabled. clang does not yet fully implement this feature.</p>
|
||||
|
||||
<h3 id="cxx_inline_namespaces">C++0x inline namespaces</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> to determine if support for
|
||||
inline namespaces is enabled.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="blocks">Blocks</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The syntax and high level language feature description is in <a
|
||||
href="BlockLanguageSpec.txt">BlockLanguageSpec.txt</a>. Implementation and ABI
|
||||
details for the clang implementation are in <a
|
||||
href="Block-ABI-Apple.txt">Block-ABI-Apple.txt</a>.</p>
|
||||
|
||||
|
||||
<p>Query for this feature with __has_feature(blocks).</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="overloading-in-c">Function Overloading in C</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Clang provides support for C++ function overloading in C. Function
|
||||
overloading in C is introduced using the <tt>overloadable</tt> attribute. For
|
||||
example, one might provide several overloaded versions of a <tt>tgsin</tt>
|
||||
function that invokes the appropriate standard function computing the sine of a
|
||||
value with <tt>float</tt>, <tt>double</tt>, or <tt>long double</tt>
|
||||
precision:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <math.h>
|
||||
float <b>__attribute__((overloadable))</b> tgsin(float x) { return sinf(x); }
|
||||
double <b>__attribute__((overloadable))</b> tgsin(double x) { return sin(x); }
|
||||
long double <b>__attribute__((overloadable))</b> tgsin(long double x) { return sinl(x); }
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Given these declarations, one can call <tt>tgsin</tt> with a
|
||||
<tt>float</tt> value to receive a <tt>float</tt> result, with a
|
||||
<tt>double</tt> to receive a <tt>double</tt> result, etc. Function
|
||||
overloading in C follows the rules of C++ function overloading to pick
|
||||
the best overload given the call arguments, with a few C-specific
|
||||
semantics:</p>
|
||||
<ul>
|
||||
<li>Conversion from <tt>float</tt> or <tt>double</tt> to <tt>long
|
||||
double</tt> is ranked as a floating-point promotion (per C99) rather
|
||||
than as a floating-point conversion (as in C++).</li>
|
||||
|
||||
<li>A conversion from a pointer of type <tt>T*</tt> to a pointer of type
|
||||
<tt>U*</tt> is considered a pointer conversion (with conversion
|
||||
rank) if <tt>T</tt> and <tt>U</tt> are compatible types.</li>
|
||||
|
||||
<li>A conversion from type <tt>T</tt> to a value of type <tt>U</tt>
|
||||
is permitted if <tt>T</tt> and <tt>U</tt> are compatible types. This
|
||||
conversion is given "conversion" rank.</li>
|
||||
</ul>
|
||||
|
||||
<p>The declaration of <tt>overloadable</tt> functions is restricted to
|
||||
function declarations and definitions. Most importantly, if any
|
||||
function with a given name is given the <tt>overloadable</tt>
|
||||
attribute, then all function declarations and definitions with that
|
||||
name (and in that scope) must have the <tt>overloadable</tt>
|
||||
attribute. This rule even applies to redeclarations of functions whose original
|
||||
declaration had the <tt>overloadable</tt> attribute, e.g.,</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
int f(int) __attribute__((overloadable));
|
||||
float f(float); <i>// error: declaration of "f" must have the "overloadable" attribute</i>
|
||||
|
||||
int g(int) __attribute__((overloadable));
|
||||
int g(int) { } <i>// error: redeclaration of "g" must also have the "overloadable" attribute</i>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Functions marked <tt>overloadable</tt> must have
|
||||
prototypes. Therefore, the following code is ill-formed:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
int h() __attribute__((overloadable)); <i>// error: h does not have a prototype</i>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>However, <tt>overloadable</tt> functions are allowed to use a
|
||||
ellipsis even if there are no named parameters (as is permitted in C++). This feature is particularly useful when combined with the <tt>unavailable</tt> attribute:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
void honeypot(...) __attribute__((overloadable, unavailable)); <i>// calling me is an error</i>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Functions declared with the <tt>overloadable</tt> attribute have
|
||||
their names mangled according to the same rules as C++ function
|
||||
names. For example, the three <tt>tgsin</tt> functions in our
|
||||
motivating example get the mangled names <tt>_Z5tgsinf</tt>,
|
||||
<tt>_Z5tgsind</tt>, and <tt>Z5tgsine</tt>, respectively. There are two
|
||||
caveats to this use of name mangling:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Future versions of Clang may change the name mangling of
|
||||
functions overloaded in C, so you should not depend on an specific
|
||||
mangling. To be completely safe, we strongly urge the use of
|
||||
<tt>static inline</tt> with <tt>overloadable</tt> functions.</li>
|
||||
|
||||
<li>The <tt>overloadable</tt> attribute has almost no meaning when
|
||||
used in C++, because names will already be mangled and functions are
|
||||
already overloadable. However, when an <tt>overloadable</tt>
|
||||
function occurs within an <tt>extern "C"</tt> linkage specification,
|
||||
it's name <i>will</i> be mangled in the same way as it would in
|
||||
C.</li>
|
||||
</ul>
|
||||
|
||||
<p>Query for this feature with __has_feature(attribute_overloadable).</p>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="builtins">Builtin Functions</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Clang supports a number of builtin library functions with the same syntax as
|
||||
GCC, including things like <tt>__builtin_nan</tt>,
|
||||
<tt>__builtin_constant_p</tt>, <tt>__builtin_choose_expr</tt>,
|
||||
<tt>__builtin_types_compatible_p</tt>, <tt>__sync_fetch_and_add</tt>, etc. In
|
||||
addition to the GCC builtins, Clang supports a number of builtins that GCC does
|
||||
not, which are listed here.</p>
|
||||
|
||||
<p>Please note that Clang does not and will not support all of the GCC builtins
|
||||
for vector operations. Instead of using builtins, you should use the functions
|
||||
defined in target-specific header files like <tt><xmmintrin.h></tt>, which
|
||||
define portable wrappers for these. Many of the Clang versions of these
|
||||
functions are implemented directly in terms of <a href="#vectors">extended
|
||||
vector support</a> instead of builtins, in order to reduce the number of
|
||||
builtins that we need to implement.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__builtin_shufflevector">__builtin_shufflevector</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p><tt>__builtin_shufflevector</tt> is used to express generic vector
|
||||
permutation/shuffle/swizzle operations. This builtin is also very important for
|
||||
the implementation of various target-specific header files like
|
||||
<tt><xmmintrin.h></tt>.
|
||||
</p>
|
||||
|
||||
<p><b>Syntax:</b></p>
|
||||
|
||||
<pre>
|
||||
__builtin_shufflevector(vec1, vec2, index1, index2, ...)
|
||||
</pre>
|
||||
|
||||
<p><b>Examples:</b></p>
|
||||
|
||||
<pre>
|
||||
// Identity operation - return 4-element vector V1.
|
||||
__builtin_shufflevector(V1, V1, 0, 1, 2, 3)
|
||||
|
||||
// "Splat" element 0 of V1 into a 4-element result.
|
||||
__builtin_shufflevector(V1, V1, 0, 0, 0, 0)
|
||||
|
||||
// Reverse 4-element vector V1.
|
||||
__builtin_shufflevector(V1, V1, 3, 2, 1, 0)
|
||||
|
||||
// Concatenate every other element of 4-element vectors V1 and V2.
|
||||
__builtin_shufflevector(V1, V2, 0, 2, 4, 6)
|
||||
|
||||
// Concatenate every other element of 8-element vectors V1 and V2.
|
||||
__builtin_shufflevector(V1, V2, 0, 2, 4, 6, 8, 10, 12, 14)
|
||||
</pre>
|
||||
|
||||
<p><b>Description:</b></p>
|
||||
|
||||
<p>The first two arguments to __builtin_shufflevector are vectors that have the
|
||||
same element type. The remaining arguments are a list of integers that specify
|
||||
the elements indices of the first two vectors that should be extracted and
|
||||
returned in a new vector. These element indices are numbered sequentially
|
||||
starting with the first vector, continuing into the second vector. Thus, if
|
||||
vec1 is a 4-element vector, index 5 would refer to the second element of vec2.
|
||||
</p>
|
||||
|
||||
<p>The result of __builtin_shufflevector is a vector
|
||||
with the same element type as vec1/vec2 but that has an element count equal to
|
||||
the number of indices specified.
|
||||
</p>
|
||||
|
||||
<p>Query for this feature with __has_builtin(__builtin_shufflevector).</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__builtin_unreachable">__builtin_unreachable</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p><tt>__builtin_unreachable</tt> is used to indicate that a specific point in
|
||||
the program cannot be reached, even if the compiler might otherwise think it
|
||||
can. This is useful to improve optimization and eliminates certain warnings.
|
||||
For example, without the <tt>__builtin_unreachable</tt> in the example below,
|
||||
the compiler assumes that the inline asm can fall through and prints a "function
|
||||
declared 'noreturn' should not return" warning.
|
||||
</p>
|
||||
|
||||
<p><b>Syntax:</b></p>
|
||||
|
||||
<pre>
|
||||
__builtin_unreachable()
|
||||
</pre>
|
||||
|
||||
<p><b>Example of Use:</b></p>
|
||||
|
||||
<pre>
|
||||
void myabort(void) __attribute__((noreturn));
|
||||
void myabort(void) {
|
||||
asm("int3");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p><b>Description:</b></p>
|
||||
|
||||
<p>The __builtin_unreachable() builtin has completely undefined behavior. Since
|
||||
it has undefined behavior, it is a statement that it is never reached and the
|
||||
optimizer can take advantage of this to produce better code. This builtin takes
|
||||
no arguments and produces a void result.
|
||||
</p>
|
||||
|
||||
<p>Query for this feature with __has_builtin(__builtin_unreachable).</p>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="targetspecific">Target-Specific Extensions</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Clang supports some language features conditionally on some targets.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="x86-specific">X86/X86-64 Language Extensions</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The X86 backend has these language extensions:</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h4 id="x86-gs-segment">Memory references off the GS segment</h4>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Annotating a pointer with address space #256 causes it to be code generated
|
||||
relative to the X86 GS segment register, and address space #257 causes it to be
|
||||
relative to the X86 FS segment. Note that this is a very very low-level
|
||||
feature that should only be used if you know what you're doing (for example in
|
||||
an OS kernel).</p>
|
||||
|
||||
<p>Here is an example:</p>
|
||||
|
||||
<pre>
|
||||
#define GS_RELATIVE __attribute__((address_space(256)))
|
||||
int foo(int GS_RELATIVE *P) {
|
||||
return *P;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Which compiles to (on X86-32):</p>
|
||||
|
||||
<pre>
|
||||
_foo:
|
||||
movl 4(%esp), %eax
|
||||
movl %gs:(%eax), %eax
|
||||
ret
|
||||
</pre>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="analyzerspecific">Static Analysis-Specific Extensions</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Clang supports additional attributes that are useful for documenting program
|
||||
invariants and rules for static analysis tools. The extensions documented here
|
||||
are used by the <a
|
||||
href="http://clang.llvm.org/StaticAnalysis.html">path-sensitive static analyzer
|
||||
engine</a> that is part of Clang's Analysis library.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="analyzerattributes">Analyzer Attributes</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<h4 id="attr_analyzer_noreturn"><tt>analyzer_noreturn</tt></h4>
|
||||
|
||||
<p>Clang's static analysis engine understands the standard <tt>noreturn</tt>
|
||||
attribute. This attribute, which is typically affixed to a function prototype,
|
||||
indicates that a call to a given function never returns. Function prototypes for
|
||||
common functions like <tt>exit</tt> are typically annotated with this attribute,
|
||||
as well as a variety of common assertion handlers. Users can educate the static
|
||||
analyzer about their own custom assertion handles (thus cutting down on false
|
||||
positives due to false paths) by marking their own "panic" functions
|
||||
with this attribute.</p>
|
||||
|
||||
<p>While useful, <tt>noreturn</tt> is not applicable in all cases. Sometimes
|
||||
there are special functions that for all intents and purposes should be
|
||||
considered panic functions (i.e., they are only called when an internal program
|
||||
error occurs) but may actually return so that the program can fail gracefully.
|
||||
The <tt>analyzer_noreturn</tt> attribute allows one to annotate such functions
|
||||
as being interpreted as "no return" functions by the analyzer (thus
|
||||
pruning bogus paths) but will not affect compilation (as in the case of
|
||||
<tt>noreturn</tt>).</p>
|
||||
|
||||
<p><b>Usage</b>: The <tt>analyzer_noreturn</tt> attribute can be placed in the
|
||||
same places where the <tt>noreturn</tt> attribute can be placed. It is commonly
|
||||
placed at the end of function prototypes:</p>
|
||||
|
||||
<pre>
|
||||
void foo() <b>__attribute__((analyzer_noreturn))</b>;
|
||||
</pre>
|
||||
|
||||
<p>Query for this feature with __has_feature(attribute_analyzer_noreturn).</p>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,97 +0,0 @@
|
||||
##===- docs/Makefile ---------------------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
CLANG_LEVEL := ..
|
||||
DIRS := tools
|
||||
|
||||
ifdef BUILD_FOR_WEBSITE
|
||||
PROJ_OBJ_DIR = .
|
||||
DOXYGEN = doxygen
|
||||
|
||||
$(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in
|
||||
cat $< | sed \
|
||||
-e 's/@abs_top_srcdir@/../g' \
|
||||
-e 's/@DOT@/dot/g' \
|
||||
-e 's/@PACKAGE_VERSION@/mainline/' \
|
||||
-e 's/@abs_top_builddir@/../g' > $@
|
||||
endif
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
||||
HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) \
|
||||
$(wildcard $(PROJ_SRC_DIR)/*.css)
|
||||
#IMAGES := $(wildcard $(PROJ_SRC_DIR)/img/*.*)
|
||||
DOXYFILES := doxygen.cfg.in doxygen.css doxygen.footer doxygen.header \
|
||||
doxygen.intro
|
||||
EXTRA_DIST := $(HTML) $(DOXYFILES) llvm.css CommandGuide img
|
||||
|
||||
.PHONY: install-html install-doxygen doxygen generated
|
||||
|
||||
install_targets :=
|
||||
ifndef ONLY_MAN_DOCS
|
||||
install_targets += install-html
|
||||
endif
|
||||
ifeq ($(ENABLE_DOXYGEN),1)
|
||||
install_targets += install-doxygen
|
||||
endif
|
||||
install-local:: $(install_targets)
|
||||
|
||||
# Live documentation is generated for the web site using this target:
|
||||
# 'make generated BUILD_FOR_WEBSITE=1'
|
||||
generated:: doxygen
|
||||
|
||||
install-html: $(PROJ_OBJ_DIR)/html.tar.gz
|
||||
$(Echo) Installing HTML documentation
|
||||
$(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html
|
||||
$(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/img
|
||||
$(Verb) $(DataInstall) $(HTML) $(DESTDIR)$(PROJ_docsdir)/html
|
||||
# $(Verb) $(DataInstall) $(IMAGES) $(DESTDIR)$(PROJ_docsdir)/html/img
|
||||
$(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(DESTDIR)$(PROJ_docsdir)
|
||||
|
||||
$(PROJ_OBJ_DIR)/html.tar.gz: $(HTML)
|
||||
$(Echo) Packaging HTML documentation
|
||||
$(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/html.tar
|
||||
$(Verb) cd $(PROJ_SRC_DIR) && \
|
||||
$(TAR) cf $(PROJ_OBJ_DIR)/html.tar *.html
|
||||
$(Verb) $(GZIP) $(PROJ_OBJ_DIR)/html.tar
|
||||
|
||||
install-doxygen: doxygen
|
||||
$(Echo) Installing doxygen documentation
|
||||
$(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/doxygen
|
||||
$(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(DESTDIR)$(PROJ_docsdir)
|
||||
$(Verb) cd $(PROJ_OBJ_DIR)/doxygen && \
|
||||
$(FIND) . -type f -exec \
|
||||
$(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/html/doxygen \;
|
||||
|
||||
doxygen: regendoc $(PROJ_OBJ_DIR)/doxygen.tar.gz
|
||||
|
||||
regendoc:
|
||||
$(Echo) Building doxygen documentation
|
||||
$(Verb) if test -e $(PROJ_OBJ_DIR)/doxygen ; then \
|
||||
$(RM) -rf $(PROJ_OBJ_DIR)/doxygen ; \
|
||||
fi
|
||||
$(Verb) $(DOXYGEN) $(PROJ_OBJ_DIR)/doxygen.cfg
|
||||
|
||||
$(PROJ_OBJ_DIR)/doxygen.tar.gz: $(DOXYFILES) $(PROJ_OBJ_DIR)/doxygen.cfg
|
||||
$(Echo) Packaging doxygen documentation
|
||||
$(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/doxygen.tar
|
||||
$(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/doxygen.tar doxygen
|
||||
$(Verb) $(GZIP) $(PROJ_OBJ_DIR)/doxygen.tar
|
||||
$(Verb) $(CP) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_OBJ_DIR)/doxygen/html/
|
||||
|
||||
userloc: $(LLVM_SRC_ROOT)/docs/userloc.html
|
||||
|
||||
$(LLVM_SRC_ROOT)/docs/userloc.html:
|
||||
$(Echo) Making User LOC Table
|
||||
$(Verb) cd $(LLVM_SRC_ROOT) ; ./utils/userloc.pl -details -recurse \
|
||||
-html lib include tools runtime utils examples autoconf test > docs/userloc.html
|
||||
|
||||
uninstall-local::
|
||||
$(Echo) Uninstalling Documentation
|
||||
$(Verb) $(RM) -rf $(DESTDIR)$(PROJ_docsdir)
|
||||
@@ -1,530 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Precompiled Headers (PCH)</title>
|
||||
<link type="text/css" rel="stylesheet" href="../menu.css" />
|
||||
<link type="text/css" rel="stylesheet" href="../content.css" />
|
||||
<style type="text/css">
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!--#include virtual="../menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Precompiled Headers</h1>
|
||||
|
||||
<p>This document describes the design and implementation of Clang's
|
||||
precompiled headers (PCH). If you are interested in the end-user
|
||||
view, please see the <a
|
||||
href="UsersManual.html#precompiledheaders">User's Manual</a>.</p>
|
||||
|
||||
<p><b>Table of Contents</b></p>
|
||||
<ul>
|
||||
<li><a href="#usage">Using Precompiled Headers with
|
||||
<tt>clang</tt></a></li>
|
||||
<li><a href="#philosophy">Design Philosophy</a></li>
|
||||
<li><a href="#contents">Precompiled Header Contents</a>
|
||||
<ul>
|
||||
<li><a href="#metadata">Metadata Block</a></li>
|
||||
<li><a href="#sourcemgr">Source Manager Block</a></li>
|
||||
<li><a href="#preprocessor">Preprocessor Block</a></li>
|
||||
<li><a href="#types">Types Block</a></li>
|
||||
<li><a href="#decls">Declarations Block</a></li>
|
||||
<li><a href="#stmt">Statements and Expressions</a></li>
|
||||
<li><a href="#idtable">Identifier Table Block</a></li>
|
||||
<li><a href="#method-pool">Method Pool Block</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#tendrils">Precompiled Header Integration
|
||||
Points</a></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="usage">Using Precompiled Headers with <tt>clang</tt></h2>
|
||||
|
||||
<p>The Clang compiler frontend, <tt>clang -cc1</tt>, supports two command line
|
||||
options for generating and using PCH files.<p>
|
||||
|
||||
<p>To generate PCH files using <tt>clang -cc1</tt>, use the option
|
||||
<b><tt>-emit-pch</tt></b>:
|
||||
|
||||
<pre> $ clang -cc1 test.h -emit-pch -o test.h.pch </pre>
|
||||
|
||||
<p>This option is transparently used by <tt>clang</tt> when generating
|
||||
PCH files. The resulting PCH file contains the serialized form of the
|
||||
compiler's internal representation after it has completed parsing and
|
||||
semantic analysis. The PCH file can then be used as a prefix header
|
||||
with the <b><tt>-include-pch</tt></b> option:</p>
|
||||
|
||||
<pre>
|
||||
$ clang -cc1 -include-pch test.h.pch test.c -o test.s
|
||||
</pre>
|
||||
|
||||
<h2 id="philosophy">Design Philosophy</h2>
|
||||
|
||||
<p>Precompiled headers are meant to improve overall compile times for
|
||||
projects, so the design of precompiled headers is entirely driven by
|
||||
performance concerns. The use case for precompiled headers is
|
||||
relatively simple: when there is a common set of headers that is
|
||||
included in nearly every source file in the project, we
|
||||
<i>precompile</i> that bundle of headers into a single precompiled
|
||||
header (PCH file). Then, when compiling the source files in the
|
||||
project, we load the PCH file first (as a prefix header), which acts
|
||||
as a stand-in for that bundle of headers.</p>
|
||||
|
||||
<p>A precompiled header implementation improves performance when:</p>
|
||||
<ul>
|
||||
<li>Loading the PCH file is significantly faster than re-parsing the
|
||||
bundle of headers stored within the PCH file. Thus, a precompiled
|
||||
header design attempts to minimize the cost of reading the PCH
|
||||
file. Ideally, this cost should not vary with the size of the
|
||||
precompiled header file.</li>
|
||||
|
||||
<li>The cost of generating the PCH file initially is not so large
|
||||
that it counters the per-source-file performance improvement due to
|
||||
eliminating the need to parse the bundled headers in the first
|
||||
place. This is particularly important on multi-core systems, because
|
||||
PCH file generation serializes the build when all compilations
|
||||
require the PCH file to be up-to-date.</li>
|
||||
</ul>
|
||||
|
||||
<p>Clang's precompiled headers are designed with a compact on-disk
|
||||
representation, which minimizes both PCH creation time and the time
|
||||
required to initially load the PCH file. The PCH file itself contains
|
||||
a serialized representation of Clang's abstract syntax trees and
|
||||
supporting data structures, stored using the same compressed bitstream
|
||||
as <a href="http://llvm.org/docs/BitCodeFormat.html">LLVM's bitcode
|
||||
file format</a>.</p>
|
||||
|
||||
<p>Clang's precompiled headers are loaded "lazily" from disk. When a
|
||||
PCH file is initially loaded, Clang reads only a small amount of data
|
||||
from the PCH file to establish where certain important data structures
|
||||
are stored. The amount of data read in this initial load is
|
||||
independent of the size of the PCH file, such that a larger PCH file
|
||||
does not lead to longer PCH load times. The actual header data in the
|
||||
PCH file--macros, functions, variables, types, etc.--is loaded only
|
||||
when it is referenced from the user's code, at which point only that
|
||||
entity (and those entities it depends on) are deserialized from the
|
||||
PCH file. With this approach, the cost of using a precompiled header
|
||||
for a translation unit is proportional to the amount of code actually
|
||||
used from the header, rather than being proportional to the size of
|
||||
the header itself.</p>
|
||||
|
||||
<p>When given the <code>-print-stats</code> option, Clang produces
|
||||
statistics describing how much of the precompiled header was actually
|
||||
loaded from disk. For a simple "Hello, World!" program that includes
|
||||
the Apple <code>Cocoa.h</code> header (which is built as a precompiled
|
||||
header), this option illustrates how little of the actual precompiled
|
||||
header is required:</p>
|
||||
|
||||
<pre>
|
||||
*** PCH Statistics:
|
||||
933 stat cache hits
|
||||
4 stat cache misses
|
||||
895/39981 source location entries read (2.238563%)
|
||||
19/15315 types read (0.124061%)
|
||||
20/82685 declarations read (0.024188%)
|
||||
154/58070 identifiers read (0.265197%)
|
||||
0/7260 selectors read (0.000000%)
|
||||
0/30842 statements read (0.000000%)
|
||||
4/8400 macros read (0.047619%)
|
||||
1/4995 lexical declcontexts read (0.020020%)
|
||||
0/4413 visible declcontexts read (0.000000%)
|
||||
0/7230 method pool entries read (0.000000%)
|
||||
0 method pool misses
|
||||
</pre>
|
||||
|
||||
<p>For this small program, only a tiny fraction of the source
|
||||
locations, types, declarations, identifiers, and macros were actually
|
||||
deserialized from the precompiled header. These statistics can be
|
||||
useful to determine whether the precompiled header implementation can
|
||||
be improved by making more of the implementation lazy.</p>
|
||||
|
||||
<p>Precompiled headers can be chained. When you create a PCH while
|
||||
including an existing PCH, Clang can create the new PCH by referencing
|
||||
the original file and only writing the new data to the new file. For
|
||||
example, you could create a PCH out of all the headers that are very
|
||||
commonly used throughout your project, and then create a PCH for every
|
||||
single source file in the project that includes the code that is
|
||||
specific to that file, so that recompiling the file itself is very fast,
|
||||
without duplicating the data from the common headers for every file.</p>
|
||||
|
||||
<h2 id="contents">Precompiled Header Contents</h2>
|
||||
|
||||
<img src="PCHLayout.png" align="right" alt="Precompiled header layout">
|
||||
|
||||
<p>Clang's precompiled headers are organized into several different
|
||||
blocks, each of which contains the serialized representation of a part
|
||||
of Clang's internal representation. Each of the blocks corresponds to
|
||||
either a block or a record within <a
|
||||
href="http://llvm.org/docs/BitCodeFormat.html">LLVM's bitstream
|
||||
format</a>. The contents of each of these logical blocks are described
|
||||
below.</p>
|
||||
|
||||
<p>For a given precompiled header, the <a
|
||||
href="http://llvm.org/cmds/llvm-bcanalyzer.html"><code>llvm-bcanalyzer</code></a>
|
||||
utility can be used to examine the actual structure of the bitstream
|
||||
for the precompiled header. This information can be used both to help
|
||||
understand the structure of the precompiled header and to isolate
|
||||
areas where precompiled headers can still be optimized, e.g., through
|
||||
the introduction of abbreviations.</p>
|
||||
|
||||
<h3 id="metadata">Metadata Block</h3>
|
||||
|
||||
<p>The metadata block contains several records that provide
|
||||
information about how the precompiled header was built. This metadata
|
||||
is primarily used to validate the use of a precompiled header. For
|
||||
example, a precompiled header built for a 32-bit x86 target cannot be used
|
||||
when compiling for a 64-bit x86 target. The metadata block contains
|
||||
information about:</p>
|
||||
|
||||
<dl>
|
||||
<dt>Language options</dt>
|
||||
<dd>Describes the particular language dialect used to compile the
|
||||
PCH file, including major options (e.g., Objective-C support) and more
|
||||
minor options (e.g., support for "//" comments). The contents of this
|
||||
record correspond to the <code>LangOptions</code> class.</dd>
|
||||
|
||||
<dt>Target architecture</dt>
|
||||
<dd>The target triple that describes the architecture, platform, and
|
||||
ABI for which the PCH file was generated, e.g.,
|
||||
<code>i386-apple-darwin9</code>.</dd>
|
||||
|
||||
<dt>PCH version</dt>
|
||||
<dd>The major and minor version numbers of the precompiled header
|
||||
format. Changes in the minor version number should not affect backward
|
||||
compatibility, while changes in the major version number imply that a
|
||||
newer compiler cannot read an older precompiled header (and
|
||||
vice-versa).</dd>
|
||||
|
||||
<dt>Original file name</dt>
|
||||
<dd>The full path of the header that was used to generate the
|
||||
precompiled header.</dd>
|
||||
|
||||
<dt>Predefines buffer</dt>
|
||||
<dd>Although not explicitly stored as part of the metadata, the
|
||||
predefines buffer is used in the validation of the precompiled header.
|
||||
The predefines buffer itself contains code generated by the compiler
|
||||
to initialize the preprocessor state according to the current target,
|
||||
platform, and command-line options. For example, the predefines buffer
|
||||
will contain "<code>#define __STDC__ 1</code>" when we are compiling C
|
||||
without Microsoft extensions. The predefines buffer itself is stored
|
||||
within the <a href="#sourcemgr">source manager block</a>, but its
|
||||
contents are verified along with the rest of the metadata.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<p>A chained PCH file (that is, one that references another PCH) has
|
||||
a slightly different metadata block, which contains the following
|
||||
information:</p>
|
||||
|
||||
<dl>
|
||||
<dt>Referenced file</dt>
|
||||
<dd>The name of the referenced PCH file. It is looked up like a file
|
||||
specified using -include-pch.</dd>
|
||||
|
||||
<dt>PCH version</dt>
|
||||
<dd>This is the same as in normal PCH files.</dd>
|
||||
|
||||
<dt>Original file name</dt>
|
||||
<dd>The full path of the header that was used to generate this
|
||||
precompiled header.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<p>The language options, target architecture and predefines buffer data
|
||||
is taken from the end of the chain, since they have to match anyway.</p>
|
||||
|
||||
<h3 id="sourcemgr">Source Manager Block</h3>
|
||||
|
||||
<p>The source manager block contains the serialized representation of
|
||||
Clang's <a
|
||||
href="InternalsManual.html#SourceLocation">SourceManager</a> class,
|
||||
which handles the mapping from source locations (as represented in
|
||||
Clang's abstract syntax tree) into actual column/line positions within
|
||||
a source file or macro instantiation. The precompiled header's
|
||||
representation of the source manager also includes information about
|
||||
all of the headers that were (transitively) included when building the
|
||||
precompiled header.</p>
|
||||
|
||||
<p>The bulk of the source manager block is dedicated to information
|
||||
about the various files, buffers, and macro instantiations into which
|
||||
a source location can refer. Each of these is referenced by a numeric
|
||||
"file ID", which is a unique number (allocated starting at 1) stored
|
||||
in the source location. Clang serializes the information for each kind
|
||||
of file ID, along with an index that maps file IDs to the position
|
||||
within the PCH file where the information about that file ID is
|
||||
stored. The data associated with a file ID is loaded only when
|
||||
required by the front end, e.g., to emit a diagnostic that includes a
|
||||
macro instantiation history inside the header itself.</p>
|
||||
|
||||
<p>The source manager block also contains information about all of the
|
||||
headers that were included when building the precompiled header. This
|
||||
includes information about the controlling macro for the header (e.g.,
|
||||
when the preprocessor identified that the contents of the header
|
||||
dependent on a macro like <code>LLVM_CLANG_SOURCEMANAGER_H</code>)
|
||||
along with a cached version of the results of the <code>stat()</code>
|
||||
system calls performed when building the precompiled header. The
|
||||
latter is particularly useful in reducing system time when searching
|
||||
for include files.</p>
|
||||
|
||||
<h3 id="preprocessor">Preprocessor Block</h3>
|
||||
|
||||
<p>The preprocessor block contains the serialized representation of
|
||||
the preprocessor. Specifically, it contains all of the macros that
|
||||
have been defined by the end of the header used to build the
|
||||
precompiled header, along with the token sequences that comprise each
|
||||
macro. The macro definitions are only read from the PCH file when the
|
||||
name of the macro first occurs in the program. This lazy loading of
|
||||
macro definitions is triggered by lookups into the <a
|
||||
href="#idtable">identifier table</a>.</p>
|
||||
|
||||
<h3 id="types">Types Block</h3>
|
||||
|
||||
<p>The types block contains the serialized representation of all of
|
||||
the types referenced in the translation unit. Each Clang type node
|
||||
(<code>PointerType</code>, <code>FunctionProtoType</code>, etc.) has a
|
||||
corresponding record type in the PCH file. When types are deserialized
|
||||
from the precompiled header, the data within the record is used to
|
||||
reconstruct the appropriate type node using the AST context.</p>
|
||||
|
||||
<p>Each type has a unique type ID, which is an integer that uniquely
|
||||
identifies that type. Type ID 0 represents the NULL type, type IDs
|
||||
less than <code>NUM_PREDEF_TYPE_IDS</code> represent predefined types
|
||||
(<code>void</code>, <code>float</code>, etc.), while other
|
||||
"user-defined" type IDs are assigned consecutively from
|
||||
<code>NUM_PREDEF_TYPE_IDS</code> upward as the types are encountered.
|
||||
The PCH file has an associated mapping from the user-defined types
|
||||
block to the location within the types block where the serialized
|
||||
representation of that type resides, enabling lazy deserialization of
|
||||
types. When a type is referenced from within the PCH file, that
|
||||
reference is encoded using the type ID shifted left by 3 bits. The
|
||||
lower three bits are used to represent the <code>const</code>,
|
||||
<code>volatile</code>, and <code>restrict</code> qualifiers, as in
|
||||
Clang's <a
|
||||
href="http://clang.llvm.org/docs/InternalsManual.html#Type">QualType</a>
|
||||
class.</p>
|
||||
|
||||
<h3 id="decls">Declarations Block</h3>
|
||||
|
||||
<p>The declarations block contains the serialized representation of
|
||||
all of the declarations referenced in the translation unit. Each Clang
|
||||
declaration node (<code>VarDecl</code>, <code>FunctionDecl</code>,
|
||||
etc.) has a corresponding record type in the PCH file. When
|
||||
declarations are deserialized from the precompiled header, the data
|
||||
within the record is used to build and populate a new instance of the
|
||||
corresponding <code>Decl</code> node. As with types, each declaration
|
||||
node has a numeric ID that is used to refer to that declaration within
|
||||
the PCH file. In addition, a lookup table provides a mapping from that
|
||||
numeric ID to the offset within the precompiled header where that
|
||||
declaration is described.</p>
|
||||
|
||||
<p>Declarations in Clang's abstract syntax trees are stored
|
||||
hierarchically. At the top of the hierarchy is the translation unit
|
||||
(<code>TranslationUnitDecl</code>), which contains all of the
|
||||
declarations in the translation unit. These declarations (such as
|
||||
functions or struct types) may also contain other declarations inside
|
||||
them, and so on. Within Clang, each declaration is stored within a <a
|
||||
href="http://clang.llvm.org/docs/InternalsManual.html#DeclContext">declaration
|
||||
context</a>, as represented by the <code>DeclContext</code> class.
|
||||
Declaration contexts provide the mechanism to perform name lookup
|
||||
within a given declaration (e.g., find the member named <code>x</code>
|
||||
in a structure) and iterate over the declarations stored within a
|
||||
context (e.g., iterate over all of the fields of a structure for
|
||||
structure layout).</p>
|
||||
|
||||
<p>In Clang's precompiled header format, deserializing a declaration
|
||||
that is a <code>DeclContext</code> is a separate operation from
|
||||
deserializing all of the declarations stored within that declaration
|
||||
context. Therefore, Clang will deserialize the translation unit
|
||||
declaration without deserializing the declarations within that
|
||||
translation unit. When required, the declarations stored within a
|
||||
declaration context will be deserialized. There are two representations
|
||||
of the declarations within a declaration context, which correspond to
|
||||
the name-lookup and iteration behavior described above:</p>
|
||||
|
||||
<ul>
|
||||
<li>When the front end performs name lookup to find a name
|
||||
<code>x</code> within a given declaration context (for example,
|
||||
during semantic analysis of the expression <code>p->x</code>,
|
||||
where <code>p</code>'s type is defined in the precompiled header),
|
||||
Clang deserializes a hash table mapping from the names within that
|
||||
declaration context to the declaration IDs that represent each
|
||||
visible declaration with that name. The entire hash table is
|
||||
deserialized at this point (into the <code>llvm::DenseMap</code>
|
||||
stored within each <code>DeclContext</code> object), but the actual
|
||||
declarations are not yet deserialized. In a second step, those
|
||||
declarations with the name <code>x</code> will be deserialized and
|
||||
will be used as the result of name lookup.</li>
|
||||
|
||||
<li>When the front end performs iteration over all of the
|
||||
declarations within a declaration context, all of those declarations
|
||||
are immediately de-serialized. For large declaration contexts (e.g.,
|
||||
the translation unit), this operation is expensive; however, large
|
||||
declaration contexts are not traversed in normal compilation, since
|
||||
such a traversal is unnecessary. However, it is common for the code
|
||||
generator and semantic analysis to traverse declaration contexts for
|
||||
structs, classes, unions, and enumerations, although those contexts
|
||||
contain relatively few declarations in the common case.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="stmt">Statements and Expressions</h3>
|
||||
|
||||
<p>Statements and expressions are stored in the precompiled header in
|
||||
both the <a href="#types">types</a> and the <a
|
||||
href="#decls">declarations</a> blocks, because every statement or
|
||||
expression will be associated with either a type or declaration. The
|
||||
actual statement and expression records are stored immediately
|
||||
following the declaration or type that owns the statement or
|
||||
expression. For example, the statement representing the body of a
|
||||
function will be stored directly following the declaration of the
|
||||
function.</p>
|
||||
|
||||
<p>As with types and declarations, each statement and expression kind
|
||||
in Clang's abstract syntax tree (<code>ForStmt</code>,
|
||||
<code>CallExpr</code>, etc.) has a corresponding record type in the
|
||||
precompiled header, which contains the serialized representation of
|
||||
that statement or expression. Each substatement or subexpression
|
||||
within an expression is stored as a separate record (which keeps most
|
||||
records to a fixed size). Within the precompiled header, the
|
||||
subexpressions of an expression are stored prior to the expression
|
||||
that owns those expression, using a form of <a
|
||||
href="http://en.wikipedia.org/wiki/Reverse_Polish_notation">Reverse
|
||||
Polish Notation</a>. For example, an expression <code>3 - 4 + 5</code>
|
||||
would be represented as follows:</p>
|
||||
|
||||
<table border="1">
|
||||
<tr><td><code>IntegerLiteral(3)</code></td></tr>
|
||||
<tr><td><code>IntegerLiteral(4)</code></td></tr>
|
||||
<tr><td><code>BinaryOperator(-)</code></td></tr>
|
||||
<tr><td><code>IntegerLiteral(5)</code></td></tr>
|
||||
<tr><td><code>BinaryOperator(+)</code></td></tr>
|
||||
<tr><td>STOP</td></tr>
|
||||
</table>
|
||||
|
||||
<p>When reading this representation, Clang evaluates each expression
|
||||
record it encounters, builds the appropriate abstract synax tree node,
|
||||
and then pushes that expression on to a stack. When a record contains <i>N</i>
|
||||
subexpressions--<code>BinaryOperator</code> has two of them--those
|
||||
expressions are popped from the top of the stack. The special STOP
|
||||
code indicates that we have reached the end of a serialized expression
|
||||
or statement; other expression or statement records may follow, but
|
||||
they are part of a different expression.</p>
|
||||
|
||||
<h3 id="idtable">Identifier Table Block</h3>
|
||||
|
||||
<p>The identifier table block contains an on-disk hash table that maps
|
||||
each identifier mentioned within the precompiled header to the
|
||||
serialized representation of the identifier's information (e.g, the
|
||||
<code>IdentifierInfo</code> structure). The serialized representation
|
||||
contains:</p>
|
||||
|
||||
<ul>
|
||||
<li>The actual identifier string.</li>
|
||||
<li>Flags that describe whether this identifier is the name of a
|
||||
built-in, a poisoned identifier, an extension token, or a
|
||||
macro.</li>
|
||||
<li>If the identifier names a macro, the offset of the macro
|
||||
definition within the <a href="#preprocessor">preprocessor
|
||||
block</a>.</li>
|
||||
<li>If the identifier names one or more declarations visible from
|
||||
translation unit scope, the <a href="#decls">declaration IDs</a> of these
|
||||
declarations.</li>
|
||||
</ul>
|
||||
|
||||
<p>When a precompiled header is loaded, the precompiled header
|
||||
mechanism introduces itself into the identifier table as an external
|
||||
lookup source. Thus, when the user program refers to an identifier
|
||||
that has not yet been seen, Clang will perform a lookup into the
|
||||
identifier table. If an identifier is found, its contents (macro
|
||||
definitions, flags, top-level declarations, etc.) will be deserialized, at which point the corresponding <code>IdentifierInfo</code> structure will have the same contents it would have after parsing the headers in the precompiled header.</p>
|
||||
|
||||
<p>Within the PCH file, the identifiers used to name declarations are represented with an integral value. A separate table provides a mapping from this integral value (the identifier ID) to the location within the on-disk
|
||||
hash table where that identifier is stored. This mapping is used when
|
||||
deserializing the name of a declaration, the identifier of a token, or
|
||||
any other construct in the PCH file that refers to a name.</p>
|
||||
|
||||
<h3 id="method-pool">Method Pool Block</h3>
|
||||
|
||||
<p>The method pool block is represented as an on-disk hash table that
|
||||
serves two purposes: it provides a mapping from the names of
|
||||
Objective-C selectors to the set of Objective-C instance and class
|
||||
methods that have that particular selector (which is required for
|
||||
semantic analysis in Objective-C) and also stores all of the selectors
|
||||
used by entities within the precompiled header. The design of the
|
||||
method pool is similar to that of the <a href="#idtable">identifier
|
||||
table</a>: the first time a particular selector is formed during the
|
||||
compilation of the program, Clang will search in the on-disk hash
|
||||
table of selectors; if found, Clang will read the Objective-C methods
|
||||
associated with that selector into the appropriate front-end data
|
||||
structure (<code>Sema::InstanceMethodPool</code> and
|
||||
<code>Sema::FactoryMethodPool</code> for instance and class methods,
|
||||
respectively).</p>
|
||||
|
||||
<p>As with identifiers, selectors are represented by numeric values
|
||||
within the PCH file. A separate index maps these numeric selector
|
||||
values to the offset of the selector within the on-disk hash table,
|
||||
and will be used when de-serializing an Objective-C method declaration
|
||||
(or other Objective-C construct) that refers to the selector.</p>
|
||||
|
||||
<h2 id="tendrils">Precompiled Header Integration Points</h2>
|
||||
|
||||
<p>The "lazy" deserialization behavior of precompiled headers requires
|
||||
their integration into several completely different submodules of
|
||||
Clang. For example, lazily deserializing the declarations during name
|
||||
lookup requires that the name-lookup routines be able to query the
|
||||
precompiled header to find entities within the PCH file.</p>
|
||||
|
||||
<p>For each Clang data structure that requires direct interaction with
|
||||
the precompiled header logic, there is an abstract class that provides
|
||||
the interface between the two modules. The <code>PCHReader</code>
|
||||
class, which handles the loading of a precompiled header, inherits
|
||||
from all of these abstract classes to provide lazy deserialization of
|
||||
Clang's data structures. <code>PCHReader</code> implements the
|
||||
following abstract classes:</p>
|
||||
|
||||
<dl>
|
||||
<dt><code>StatSysCallCache</code></dt>
|
||||
<dd>This abstract interface is associated with the
|
||||
<code>FileManager</code> class, and is used whenever the file
|
||||
manager is going to perform a <code>stat()</code> system call.</dd>
|
||||
|
||||
<dt><code>ExternalSLocEntrySource</code></dt>
|
||||
<dd>This abstract interface is associated with the
|
||||
<code>SourceManager</code> class, and is used whenever the
|
||||
<a href="#sourcemgr">source manager</a> needs to load the details
|
||||
of a file, buffer, or macro instantiation.</dd>
|
||||
|
||||
<dt><code>IdentifierInfoLookup</code></dt>
|
||||
<dd>This abstract interface is associated with the
|
||||
<code>IdentifierTable</code> class, and is used whenever the
|
||||
program source refers to an identifier that has not yet been seen.
|
||||
In this case, the precompiled header implementation searches for
|
||||
this identifier within its <a href="#idtable">identifier table</a>
|
||||
to load any top-level declarations or macros associated with that
|
||||
identifier.</dd>
|
||||
|
||||
<dt><code>ExternalASTSource</code></dt>
|
||||
<dd>This abstract interface is associated with the
|
||||
<code>ASTContext</code> class, and is used whenever the abstract
|
||||
syntax tree nodes need to loaded from the precompiled header. It
|
||||
provides the ability to de-serialize declarations and types
|
||||
identified by their numeric values, read the bodies of functions
|
||||
when required, and read the declarations stored within a
|
||||
declaration context (either for iteration or for name lookup).</dd>
|
||||
|
||||
<dt><code>ExternalSemaSource</code></dt>
|
||||
<dd>This abstract interface is associated with the <code>Sema</code>
|
||||
class, and is used whenever semantic analysis needs to read
|
||||
information from the <a href="#methodpool">global method
|
||||
pool</a>.</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
@@ -1,177 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Pretokenized Headers (PTH)</title>
|
||||
<link type="text/css" rel="stylesheet" href="../menu.css" />
|
||||
<link type="text/css" rel="stylesheet" href="../content.css" />
|
||||
<style type="text/css">
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--#include virtual="../menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Pretokenized Headers (PTH)</h1>
|
||||
|
||||
<p>This document first describes the low-level
|
||||
interface for using PTH and then briefly elaborates on its design and
|
||||
implementation. If you are interested in the end-user view, please see the
|
||||
<a href="UsersManual.html#precompiledheaders">User's Manual</a>.</p>
|
||||
|
||||
|
||||
<h2>Using Pretokenized Headers with <tt>clang</tt> (Low-level Interface)</h2>
|
||||
|
||||
<p>The Clang compiler frontend, <tt>clang -cc1</tt>, supports three command line
|
||||
options for generating and using PTH files.<p>
|
||||
|
||||
<p>To generate PTH files using <tt>clang -cc1</tt>, use the option
|
||||
<b><tt>-emit-pth</tt></b>:
|
||||
|
||||
<pre> $ clang -cc1 test.h -emit-pth -o test.h.pth </pre>
|
||||
|
||||
<p>This option is transparently used by <tt>clang</tt> when generating PTH
|
||||
files. Similarly, PTH files can be used as prefix headers using the
|
||||
<b><tt>-include-pth</tt></b> option:</p>
|
||||
|
||||
<pre>
|
||||
$ clang -cc1 -include-pth test.h.pth test.c -o test.s
|
||||
</pre>
|
||||
|
||||
<p>Alternatively, Clang's PTH files can be used as a raw "token-cache"
|
||||
(or "content" cache) of the source included by the original header
|
||||
file. This means that the contents of the PTH file are searched as substitutes
|
||||
for <em>any</em> source files that are used by <tt>clang -cc1</tt> to process a
|
||||
source file. This is done by specifying the <b><tt>-token-cache</tt></b>
|
||||
option:</p>
|
||||
|
||||
<pre>
|
||||
$ cat test.h
|
||||
#include <stdio.h>
|
||||
$ clang -cc1 -emit-pth test.h -o test.h.pth
|
||||
$ cat test.c
|
||||
#include "test.h"
|
||||
$ clang -cc1 test.c -o test -token-cache test.h.pth
|
||||
</pre>
|
||||
|
||||
<p>In this example the contents of <tt>stdio.h</tt> (and the files it includes)
|
||||
will be retrieved from <tt>test.h.pth</tt>, as the PTH file is being used in
|
||||
this case as a raw cache of the contents of <tt>test.h</tt>. This is a low-level
|
||||
interface used to both implement the high-level PTH interface as well as to
|
||||
provide alternative means to use PTH-style caching.</p>
|
||||
|
||||
<h2>PTH Design and Implementation</h2>
|
||||
|
||||
<p>Unlike GCC's precompiled headers, which cache the full ASTs and preprocessor
|
||||
state of a header file, Clang's pretokenized header files mainly cache the raw
|
||||
lexer <em>tokens</em> that are needed to segment the stream of characters in a
|
||||
source file into keywords, identifiers, and operators. Consequently, PTH serves
|
||||
to mainly directly speed up the lexing and preprocessing of a source file, while
|
||||
parsing and type-checking must be completely redone every time a PTH file is
|
||||
used.</p>
|
||||
|
||||
<h3>Basic Design Tradeoffs</h3>
|
||||
|
||||
<p>In the long term there are plans to provide an alternate PCH implementation
|
||||
for Clang that also caches the work for parsing and type checking the contents
|
||||
of header files. The current implementation of PCH in Clang as pretokenized
|
||||
header files was motivated by the following factors:<p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><p><b>Language independence</b>: PTH files work with any language that
|
||||
Clang's lexer can handle, including C, Objective-C, and (in the early stages)
|
||||
C++. This means development on language features at the parsing level or above
|
||||
(which is basically almost all interesting pieces) does not require PTH to be
|
||||
modified.</p></li>
|
||||
|
||||
<li><b>Simple design</b>: Relatively speaking, PTH has a simple design and
|
||||
implementation, making it easy to test. Further, because the machinery for PTH
|
||||
resides at the lower-levels of the Clang library stack it is fairly
|
||||
straightforward to profile and optimize.</li>
|
||||
</ul>
|
||||
|
||||
<p>Further, compared to GCC's PCH implementation (which is the dominate
|
||||
precompiled header file implementation that Clang can be directly compared
|
||||
against) the PTH design in Clang yields several attractive features:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><p><b>Architecture independence</b>: In contrast to GCC's PCH files (and
|
||||
those of several other compilers), Clang's PTH files are architecture
|
||||
independent, requiring only a single PTH file when building an program for
|
||||
multiple architectures.</p>
|
||||
|
||||
<p>For example, on Mac OS X one may wish to
|
||||
compile a "universal binary" that runs on PowerPC, 32-bit Intel
|
||||
(i386), and 64-bit Intel architectures. In contrast, GCC requires a PCH file for
|
||||
each architecture, as the definitions of types in the AST are
|
||||
architecture-specific. Since a Clang PTH file essentially represents a lexical
|
||||
cache of header files, a single PTH file can be safely used when compiling for
|
||||
multiple architectures. This can also reduce compile times because only a single
|
||||
PTH file needs to be generated during a build instead of several.</p></li>
|
||||
|
||||
<li><p><b>Reduced memory pressure</b>: Similar to GCC,
|
||||
Clang reads PTH files via the use of memory mapping (i.e., <tt>mmap</tt>).
|
||||
Clang, however, memory maps PTH files as read-only, meaning that multiple
|
||||
invocations of <tt>clang -cc1</tt> can share the same pages in memory from a
|
||||
memory-mapped PTH file. In comparison, GCC also memory maps its PCH files but
|
||||
also modifies those pages in memory, incurring the copy-on-write costs. The
|
||||
read-only nature of PTH can greatly reduce memory pressure for builds involving
|
||||
multiple cores, thus improving overall scalability.</p></li>
|
||||
|
||||
<li><p><b>Fast generation</b>: PTH files can be generated in a small fraction
|
||||
of the time needed to generate GCC's PCH files. Since PTH/PCH generation is a
|
||||
serial operation that typically blocks progress during a build, faster
|
||||
generation time leads to improved processor utilization with parallel builds on
|
||||
multicore machines.</p></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>Despite these strengths, PTH's simple design suffers some algorithmic
|
||||
handicaps compared to other PCH strategies such as those used by GCC. While PTH
|
||||
can greatly speed up the processing time of a header file, the amount of work
|
||||
required to process a header file is still roughly linear in the size of the
|
||||
header file. In contrast, the amount of work done by GCC to process a
|
||||
precompiled header is (theoretically) constant (the ASTs for the header are
|
||||
literally memory mapped into the compiler). This means that only the pieces of
|
||||
the header file that are referenced by the source file including the header are
|
||||
the only ones the compiler needs to process during actual compilation. While
|
||||
GCC's particular implementation of PCH mitigates some of these algorithmic
|
||||
strengths via the use of copy-on-write pages, the approach itself can
|
||||
fundamentally dominate at an algorithmic level, especially when one considers
|
||||
header files of arbitrary size.</p>
|
||||
|
||||
<p>There are plans to potentially implement an complementary PCH implementation
|
||||
for Clang based on the lazy deserialization of ASTs. This approach would
|
||||
theoretically have the same constant-time algorithmic advantages just mentioned
|
||||
but would also retain some of the strengths of PTH such as reduced memory
|
||||
pressure (ideal for multi-core builds).</p>
|
||||
|
||||
<h3>Internal PTH Optimizations</h3>
|
||||
|
||||
<p>While the main optimization employed by PTH is to reduce lexing time of
|
||||
header files by caching pre-lexed tokens, PTH also employs several other
|
||||
optimizations to speed up the processing of header files:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><p><em><tt>stat</tt> caching</em>: PTH files cache information obtained via
|
||||
calls to <tt>stat</tt> that <tt>clang -cc1</tt> uses to resolve which files are
|
||||
included by <tt>#include</tt> directives. This greatly reduces the overhead
|
||||
involved in context-switching to the kernel to resolve included files.</p></li>
|
||||
|
||||
<li><p><em>Fasting skipping of <tt>#ifdef</tt>...<tt>#endif</tt> chains</em>:
|
||||
PTH files record the basic structure of nested preprocessor blocks. When the
|
||||
condition of the preprocessor block is false, all of its tokens are immediately
|
||||
skipped instead of requiring them to be handled by Clang's
|
||||
preprocessor.</p></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,989 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Clang Compiler User's Manual</title>
|
||||
<link type="text/css" rel="stylesheet" href="../menu.css" />
|
||||
<link type="text/css" rel="stylesheet" href="../content.css" />
|
||||
<style type="text/css">
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--#include virtual="../menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Clang Compiler User's Manual</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="#intro">Introduction</a>
|
||||
<ul>
|
||||
<li><a href="#terminology">Terminology</a></li>
|
||||
<li><a href="#basicusage">Basic Usage</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#commandline">Command Line Options</a>
|
||||
<ul>
|
||||
<li><a href="#cl_diagnostics">Options to Control Error and Warning
|
||||
Messages</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#general_features">Language and Target-Independent Features</a>
|
||||
<ul>
|
||||
<li><a href="#diagnostics">Controlling Errors and Warnings</a></li>
|
||||
<ul>
|
||||
<li><a href="#diagnostics_display">Controlling How Clang Displays Diagnostics</a></li>
|
||||
<li><a href="#diagnostics_mappings">Diagnostic Mappings</a></li>
|
||||
<li><a href="#diagnostics_categories">Diagnostic Categories</a></li>
|
||||
<li><a href="#diagnostics_commandline">Controlling Diagnostics via Command Line Flags</a></li>
|
||||
<li><a href="#diagnostics_pragmas">Controlling Diagnostics via Pragmas</a></li>
|
||||
<li><a href="#analyzer_diagnositics">Controlling Static Analyzer Diagnostics</a></li>
|
||||
</ul>
|
||||
<li><a href="#precompiledheaders">Precompiled Headers</a></li>
|
||||
<li><a href="#codegen">Controlling Code Generation</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#c">C Language Features</a>
|
||||
<ul>
|
||||
<li><a href="#c_ext">Extensions supported by clang</a></li>
|
||||
<li><a href="#c_modes">Differences between various standard modes</a></li>
|
||||
<li><a href="#c_unimpl_gcc">GCC extensions not implemented yet</a></li>
|
||||
<li><a href="#c_unsupp_gcc">Intentionally unsupported GCC extensions</a></li>
|
||||
<li><a href="#c_ms">Microsoft extensions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#target_features">Target-Specific Features and Limitations</a>
|
||||
<ul>
|
||||
<li><a href="#target_arch">CPU Architectures Features and Limitations</a>
|
||||
<ul>
|
||||
<li><a href="#target_arch_x86">X86</a></li>
|
||||
<li><a href="#target_arch_arm">ARM</a></li>
|
||||
<li><a href="#target_arch_other">Other platforms</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#target_os">Operating System Features and Limitations</a>
|
||||
<ul>
|
||||
<li><a href="#target_os_darwin">Darwin (Mac OS/X)</a></li>
|
||||
<li>Linux, etc.</li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="intro">Introduction</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The Clang Compiler is an open-source compiler for the C family of programming
|
||||
languages, aiming to be the best in class implementation of these languages.
|
||||
Clang builds on the LLVM optimizer and code generator, allowing it to provide
|
||||
high-quality optimization and code generation support for many targets. For
|
||||
more general information, please see the <a href="http://clang.llvm.org">Clang
|
||||
Web Site</a> or the <a href="http://llvm.org">LLVM Web Site</a>.</p>
|
||||
|
||||
<p>This document describes important notes about using Clang as a compiler for
|
||||
an end-user, documenting the supported features, command line options, etc. If
|
||||
you are interested in using Clang to build a tool that processes code, please
|
||||
see <a href="InternalsManual.html">the Clang Internals Manual</a>. If you are
|
||||
interested in the <a href="http://clang.llvm.org/StaticAnalysis.html">Clang
|
||||
Static Analyzer</a>, please see its web page.</p>
|
||||
|
||||
<p>Clang is designed to support the C family of programming languages, which
|
||||
includes <a href="#c">C</a>, <a href="#objc">Objective-C</a>, <a
|
||||
href="#cxx">C++</a>, and <a href="#objcxx">Objective-C++</a> as well as many
|
||||
dialects of those. For language-specific information, please see the
|
||||
corresponding language specific section:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="#c">C Language</a>: K&R C, ANSI C89, ISO C90, ISO C94
|
||||
(C89+AMD1), ISO C99 (+TC1, TC2, TC3). </li>
|
||||
<li><a href="#objc">Objective-C Language</a>: ObjC 1, ObjC 2, ObjC 2.1, plus
|
||||
variants depending on base language.</li>
|
||||
<li><a href="#cxx">C++ Language Features</a></li>
|
||||
<li><a href="#objcxx">Objective C++ Language</a></li>
|
||||
</ul>
|
||||
|
||||
<p>In addition to these base languages and their dialects, Clang supports a
|
||||
broad variety of language extensions, which are documented in the corresponding
|
||||
language section. These extensions are provided to be compatible with the GCC,
|
||||
Microsoft, and other popular compilers as well as to improve functionality
|
||||
through Clang-specific features. The Clang driver and language features are
|
||||
intentionally designed to be as compatible with the GNU GCC compiler as
|
||||
reasonably possible, easing migration from GCC to Clang. In most cases, code
|
||||
"just works".</p>
|
||||
|
||||
<p>In addition to language specific features, Clang has a variety of features
|
||||
that depend on what CPU architecture or operating system is being compiled for.
|
||||
Please see the <a href="#target_features">Target-Specific Features and
|
||||
Limitations</a> section for more details.</p>
|
||||
|
||||
<p>The rest of the introduction introduces some basic <a
|
||||
href="#terminology">compiler terminology</a> that is used throughout this manual
|
||||
and contains a basic <a href="#basicusage">introduction to using Clang</a>
|
||||
as a command line compiler.</p>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="terminology">Terminology</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>Front end, parser, backend, preprocessor, undefined behavior, diagnostic,
|
||||
optimizer</p>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="basicusage">Basic Usage</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>Intro to how to use a C compiler for newbies.</p>
|
||||
<p>
|
||||
compile + link
|
||||
|
||||
compile then link
|
||||
|
||||
debug info
|
||||
|
||||
enabling optimizations
|
||||
|
||||
picking a language to use, defaults to C99 by default. Autosenses based on
|
||||
extension.
|
||||
|
||||
using a makefile
|
||||
</p>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="commandline">Command Line Options</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>
|
||||
This section is generally an index into other sections. It does not go into
|
||||
depth on the ones that are covered by other sections. However, the first part
|
||||
introduces the language selection and other high level options like -c, -g, etc.
|
||||
</p>
|
||||
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="cl_diagnostics">Options to Control Error and Warning Messages</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p><b>-Werror</b>: Turn warnings into errors.</p>
|
||||
<p><b>-Werror=foo</b>: Turn warning "foo" into an error.</p>
|
||||
<p><b>-Wno-error=foo</b>: Turn warning "foo" into an warning even if -Werror is
|
||||
specified.</p>
|
||||
<p><b>-Wfoo</b>: Enable warning foo</p>
|
||||
<p><b>-Wno-foo</b>: Disable warning foo</p>
|
||||
<p><b>-w</b>: Disable all warnings.</p>
|
||||
<p><b>-pedantic</b>: Warn on language extensions.</p>
|
||||
<p><b>-pedantic-errors</b>: Error on language extensions.</p>
|
||||
<p><b>-Wsystem-headers</b>: Enable warnings from system headers.</p>
|
||||
|
||||
<p><b>-ferror-limit=123</b>: Stop emitting diagnostics after 123 errors have
|
||||
been produced. The default is 20, and the error limit can be disabled with
|
||||
-ferror-limit=0.</p>
|
||||
|
||||
<p><b>-ftemplate-backtrace-limit=123</b>: Only emit up to 123 template instantiation notes within the template instantiation backtrace for a single warning or error. The default is 10, and the limit can be disabled with -ftemplate-backtrace-limit=0.</p>
|
||||
|
||||
<!-- ================================================= -->
|
||||
<h4 id="cl_diag_formatting">Formatting of Diagnostics</h4>
|
||||
<!-- ================================================= -->
|
||||
|
||||
<p>Clang aims to produce beautiful diagnostics by default, particularly for new
|
||||
users that first come to Clang. However, different people have different
|
||||
preferences, and sometimes Clang is driven by another program that wants to
|
||||
parse simple and consistent output, not a person. For these cases, Clang
|
||||
provides a wide range of options to control the exact output format of the
|
||||
diagnostics that it generates.</p>
|
||||
|
||||
<dl>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fshow-column"><b>-f[no-]show-column</b>: Print column number in
|
||||
diagnostic.</dt>
|
||||
<dd>This option, which defaults to on, controls whether or not Clang prints the
|
||||
column number of a diagnostic. For example, when this is enabled, Clang will
|
||||
print something like:</p>
|
||||
|
||||
<pre>
|
||||
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
|
||||
#endif bad
|
||||
^
|
||||
//
|
||||
</pre>
|
||||
|
||||
<p>When this is disabled, Clang will print "test.c:28: warning..." with no
|
||||
column number.</p>
|
||||
</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fshow-source-location"><b>-f[no-]show-source-location</b>: Print
|
||||
source file/line/column information in diagnostic.</dt>
|
||||
<dd>This option, which defaults to on, controls whether or not Clang prints the
|
||||
filename, line number and column number of a diagnostic. For example,
|
||||
when this is enabled, Clang will print something like:</p>
|
||||
|
||||
<pre>
|
||||
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
|
||||
#endif bad
|
||||
^
|
||||
//
|
||||
</pre>
|
||||
|
||||
<p>When this is disabled, Clang will not print the "test.c:28:8: " part.</p>
|
||||
</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fcaret-diagnostics"><b>-f[no-]caret-diagnostics</b>: Print source
|
||||
line and ranges from source code in diagnostic.</dt>
|
||||
<dd>This option, which defaults to on, controls whether or not Clang prints the
|
||||
source line, source ranges, and caret when emitting a diagnostic. For example,
|
||||
when this is enabled, Clang will print something like:</p>
|
||||
|
||||
<pre>
|
||||
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
|
||||
#endif bad
|
||||
^
|
||||
//
|
||||
</pre>
|
||||
|
||||
<p>When this is disabled, Clang will just print:</p>
|
||||
|
||||
<pre>
|
||||
<b><font color="black">test.c:28:8: <font color="magenta">warning</font>: extra tokens at end of #endif directive [-Wextra-tokens]</font></b>
|
||||
#endif bad
|
||||
<font color="green">^</font>
|
||||
<font color="green">//</font>
|
||||
</pre>
|
||||
|
||||
</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fcolor_diagnostics"><b>-f[no-]color-diagnostics</b>: </dt>
|
||||
<dd>This option, which defaults to on when a color-capable terminal is
|
||||
detected, controls whether or not Clang prints diagnostics in color.
|
||||
When this option is enabled, Clang will use colors to highlight
|
||||
specific parts of the diagnostic, e.g.,
|
||||
|
||||
<pre>
|
||||
<test.c:2:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
|
||||
#endif bad
|
||||
^
|
||||
//
|
||||
</pre>
|
||||
</dd>'
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fdiagnostics-show-option"><b>-f[no-]diagnostics-show-option</b>:
|
||||
Enable <tt>[-Woption]</tt> information in diagnostic line.</dt>
|
||||
<dd>This option, which defaults to on,
|
||||
controls whether or not Clang prints the associated <A
|
||||
href="#cl_diag_warning_groups">warning group</a> option name when outputting
|
||||
a warning diagnostic. For example, in this output:</p>
|
||||
|
||||
<pre>
|
||||
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
|
||||
#endif bad
|
||||
^
|
||||
//
|
||||
</pre>
|
||||
|
||||
<p>Passing <b>-fno-diagnostics-show-option</b> will prevent Clang from printing
|
||||
the [<a href="#opt_Wextra-tokens">-Wextra-tokens</a>] information in the
|
||||
diagnostic. This information tells you the flag needed to enable or disable the
|
||||
diagnostic, either from the command line or through <a
|
||||
href="#pragma_GCC_diagnostic">#pragma GCC diagnostic</a>.</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fdiagnostics-show-category"><b>-fdiagnostics-show-category=none/id/name</b>:
|
||||
Enable printing category information in diagnostic line.</dt>
|
||||
<dd>This option, which defaults to "none",
|
||||
controls whether or not Clang prints the category associated with a diagnostic
|
||||
when emitting it. Each diagnostic may or many not have an associated category,
|
||||
if it has one, it is listed in the diagnostic categorization field of the
|
||||
diagnostic line (in the []'s).</p>
|
||||
|
||||
<p>For example, a format string warning will produce these three renditions
|
||||
based on the setting of this option:</p>
|
||||
|
||||
<pre>
|
||||
t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat]
|
||||
t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat<b>,1</b>]
|
||||
t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat<b>,Format String</b>]
|
||||
</pre>
|
||||
|
||||
<p>This category can be used by clients that want to group diagnostics by
|
||||
category, so it should be a high level category. We want dozens of these, not
|
||||
hundreds or thousands of them.</p>
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fdiagnostics-fixit-info"><b>-f[no-]diagnostics-fixit-info</b>:
|
||||
Enable "FixIt" information in the diagnostics output.</dt>
|
||||
<dd>This option, which defaults to on, controls whether or not Clang prints the
|
||||
information on how to fix a specific diagnostic underneath it when it knows.
|
||||
For example, in this output:</p>
|
||||
|
||||
<pre>
|
||||
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
|
||||
#endif bad
|
||||
^
|
||||
//
|
||||
</pre>
|
||||
|
||||
<p>Passing <b>-fno-diagnostics-fixit-info</b> will prevent Clang from printing
|
||||
the "//" line at the end of the message. This information is useful for users
|
||||
who may not understand what is wrong, but can be confusing for machine
|
||||
parsing.</p>
|
||||
</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fdiagnostics-print-source-range-info">
|
||||
<b>-f[no-]diagnostics-print-source-range-info</b>:
|
||||
Print machine parsable information about source ranges.</dt>
|
||||
<dd>This option, which defaults to off, controls whether or not Clang prints
|
||||
information about source ranges in a machine parsable format after the
|
||||
file/line/column number information. The information is a simple sequence of
|
||||
brace enclosed ranges, where each range lists the start and end line/column
|
||||
locations. For example, in this output:</p>
|
||||
|
||||
<pre>
|
||||
exprs.c:47:15:{47:8-47:14}{47:17-47:24}: error: invalid operands to binary expression ('int *' and '_Complex float')
|
||||
P = (P-42) + Gamma*4;
|
||||
~~~~~~ ^ ~~~~~~~
|
||||
</pre>
|
||||
|
||||
<p>The {}'s are generated by -fdiagnostics-print-source-range-info.</p>
|
||||
</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fdiagnostics-parseable-fixits">
|
||||
<b>-fdiagnostics-parseable-fixits</b>:
|
||||
Print Fix-Its in a machine parseable form.</dt>
|
||||
<dd><p>This option makes Clang print available Fix-Its in a machine parseable format at the end of diagnostics. The following example illustrates the format:</p>
|
||||
|
||||
<pre>
|
||||
fix-it:"t.cpp":{7:25-7:29}:"Gamma"
|
||||
</pre>
|
||||
|
||||
<p>The range printed is a half-open range, so in this example the characters at column 25 up to but not including column 29 on line 7 in t.cpp should be replaced with the string "Gamma". Either the range or the replacement string may be empty (representing strict insertions and strict erasures, respectively). Both the file name and the insertion string escape backslash (as "\\"), tabs (as "\t"), newlines (as "\n"), double quotes(as "\"") and non-printable characters (as octal "\xxx").</p>
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<h4 id="cl_diag_warning_groups">Individual Warning Groups</h4>
|
||||
<!-- ===================================================== -->
|
||||
|
||||
<p>TODO: Generate this from tblgen. Define one anchor per warning group.</p>
|
||||
|
||||
|
||||
<dl>
|
||||
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_Wextra-tokens"><b>-Wextra-tokens</b>: Warn about excess tokens at
|
||||
the end of a preprocessor directive.</dt>
|
||||
<dd>This option, which defaults to on, enables warnings about extra tokens at
|
||||
the end of preprocessor directives. For example:</p>
|
||||
|
||||
<pre>
|
||||
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
|
||||
#endif bad
|
||||
^
|
||||
</pre>
|
||||
|
||||
<p>These extra tokens are not strictly conforming, and are usually best handled
|
||||
by commenting them out.</p>
|
||||
|
||||
<p>This option is also enabled by <a href="">-Wfoo</a>, <a href="">-Wbar</a>,
|
||||
and <a href="">-Wbaz</a>.</p>
|
||||
</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_Wambiguous-member-template"><b>-Wambiguous-member-template</b>:
|
||||
Warn about unqualified uses of a member template whose name resolves
|
||||
to another template at the location of the use.</dt>
|
||||
<dd>This option, which defaults to on, enables a warning in the
|
||||
following code:</p>
|
||||
|
||||
<pre>
|
||||
template<typename T> struct set{};
|
||||
template<typename T> struct trait { typedef const T& type; };
|
||||
struct Value {
|
||||
template<typename T> void set(typename trait<T>::type value) {}
|
||||
};
|
||||
void foo() {
|
||||
Value v;
|
||||
v.set<double>(3.2);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>C++ [basic.lookup.classref] requires this to be an error, but,
|
||||
because it's hard to work around, Clang downgrades it to a warning as
|
||||
an extension.</p>
|
||||
</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_Wbind-to-temporary-copy"><b>-Wbind-to-temporary-copy</b>: Warn about
|
||||
an unusable copy constructor when binding a reference to a temporary.</dt>
|
||||
<dd>This option, which defaults to on, enables warnings about binding a
|
||||
reference to a temporary when the temporary doesn't have a usable copy
|
||||
constructor. For example:</p>
|
||||
|
||||
<pre>
|
||||
struct NonCopyable {
|
||||
NonCopyable();
|
||||
private:
|
||||
NonCopyable(const NonCopyable&);
|
||||
};
|
||||
void foo(const NonCopyable&);
|
||||
void bar() {
|
||||
foo(NonCopyable()); // Disallowed in C++98; allowed in C++0x.
|
||||
}
|
||||
</pre>
|
||||
<pre>
|
||||
struct NonCopyable2 {
|
||||
NonCopyable2();
|
||||
NonCopyable2(NonCopyable2&);
|
||||
};
|
||||
void foo(const NonCopyable2&);
|
||||
void bar() {
|
||||
foo(NonCopyable2()); // Disallowed in C++98; allowed in C++0x.
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Note that if <tt>NonCopyable2::NonCopyable2()</tt> has a default
|
||||
argument whose instantiation produces a compile error, that error will
|
||||
still be a hard error in C++98 mode even if this warning is turned
|
||||
off.</p>
|
||||
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="general_features">Language and Target-Independent Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="diagnostics">Controlling Errors and Warnings</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>Clang provides a number of ways to control which code constructs cause it to
|
||||
emit errors and warning messages, and how they are displayed to the console.</p>
|
||||
|
||||
<h4 id="diagnostics_display">Controlling How Clang Displays Diagnostics</h4>
|
||||
|
||||
<p>When Clang emits a diagnostic, it includes rich information in the output,
|
||||
and gives you fine-grain control over which information is printed. Clang has
|
||||
the ability to print this information, and these are the options that control
|
||||
it:</p>
|
||||
|
||||
<p>
|
||||
<ol>
|
||||
<li>A file/line/column indicator that shows exactly where the diagnostic occurs
|
||||
in your code [<a href="#opt_fshow-column">-fshow-column</a>, <a
|
||||
href="#opt_fshow-source-location">-fshow-source-location</a>].</li>
|
||||
<li>A categorization of the diagnostic as a note, warning, error, or fatal
|
||||
error.</li>
|
||||
<li>A text string that describes what the problem is.</li>
|
||||
<li>An option that indicates how to control the diagnostic (for diagnostics that
|
||||
support it) [<a
|
||||
href="#opt_fdiagnostics-show-option">-fdiagnostics-show-option</a>].</li>
|
||||
<li>A <a href="#diagnostics_categories">high-level category</a> for the
|
||||
diagnostic for clients that want to group diagnostics by class (for
|
||||
diagnostics that support it) [<a
|
||||
href="#opt_fdiagnostics-show-category">-fdiagnostics-show-category</a>].</li>
|
||||
<li>The line of source code that the issue occurs on, along with a caret and
|
||||
ranges that indicate the important locations [<a
|
||||
href="opt_fcaret-diagnostics">-fcaret-diagnostics</a>].</li>
|
||||
<li>"FixIt" information, which is a concise explanation of how to fix the
|
||||
problem (when Clang is certain it knows) [<a
|
||||
href="opt_fdiagnostics-fixit-info">-fdiagnostics-fixit-info</a>].</li>
|
||||
<li>A machine-parsable representation of the ranges involved (off by
|
||||
default) [<a
|
||||
href="opt_fdiagnostics-print-source-range-info">-fdiagnostics-print-source-range-info</a>].</li>
|
||||
</ol></p>
|
||||
|
||||
<p>For more information please see <a href="#cl_diag_formatting">Formatting of
|
||||
Diagnostics</a>.</p>
|
||||
|
||||
|
||||
<h4 id="diagnostics_mappings">Diagnostic Mappings</h4>
|
||||
|
||||
<p>All diagnostics are mapped into one of these 5 classes:</p>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Ignored</li>
|
||||
<li>Note</li>
|
||||
<li>Warning</li>
|
||||
<li>Error</li>
|
||||
<li>Fatal</li>
|
||||
</ul></p>
|
||||
|
||||
<h4 id="diagnostics_categories">Diagnostic Categories</h4>
|
||||
|
||||
<p>Though not shown by default, diagnostics may each be associated with a
|
||||
high-level category. This category is intended to make it possible to triage
|
||||
builds that produce a large number of errors or warnings in a grouped way.
|
||||
</p>
|
||||
|
||||
<p>Categories are not shown by default, but they can be turned on with the
|
||||
<a href="#opt_fdiagnostics-show-category">-fdiagnostics-show-category</a> option.
|
||||
When set to "<tt>name</tt>", the category is printed textually in the diagnostic
|
||||
output. When it is set to "<tt>id</tt>", a category number is printed. The
|
||||
mapping of category names to category id's can be obtained by running '<tt>clang
|
||||
--print-diagnostic-categories</tt>'.
|
||||
</p>
|
||||
|
||||
<h4 id="diagnostics_commandline">Controlling Diagnostics via Command Line
|
||||
Flags</h4>
|
||||
|
||||
<p>-W flags, -pedantic, etc</p>
|
||||
|
||||
<h4 id="diagnostics_pragmas">Controlling Diagnostics via Pragmas</h4>
|
||||
|
||||
<p>Clang can also control what diagnostics are enabled through the use of
|
||||
pragmas in the source code. This is useful for turning off specific warnings
|
||||
in a section of source code. Clang supports GCC's pragma for compatibility
|
||||
with existing source code, as well as several extensions. </p>
|
||||
|
||||
<p>The pragma may control any warning that can be used from the command line.
|
||||
Warnings may be set to ignored, warning, error, or fatal. The following
|
||||
example code will tell Clang or GCC to ignore the -Wall warnings:</p>
|
||||
|
||||
<pre>
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
</pre>
|
||||
|
||||
<p>In addition to all of the functionality of provided by GCC's pragma, Clang
|
||||
also allows you to push and pop the current warning state. This is particularly
|
||||
useful when writing a header file that will be compiled by other people, because
|
||||
you don't know what warning flags they build with.</p>
|
||||
|
||||
<p>In the below example
|
||||
-Wmultichar is ignored for only a single line of code, after which the
|
||||
diagnostics return to whatever state had previously existed.</p>
|
||||
|
||||
<pre>
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmultichar"
|
||||
|
||||
char b = 'df'; // no warning.
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
</pre>
|
||||
|
||||
<p>The push and pop pragmas will save and restore the full diagnostic state of
|
||||
the compiler, regardless of how it was set. That means that it is possible to
|
||||
use push and pop around GCC compatible diagnostics and Clang will push and pop
|
||||
them appropriately, while GCC will ignore the pushes and pops as unknown
|
||||
pragmas. It should be noted that while Clang supports the GCC pragma, Clang and
|
||||
GCC do not support the exact same set of warnings, so even when using GCC
|
||||
compatible #pragmas there is no guarantee that they will have identical behaviour
|
||||
on both compilers. </p>
|
||||
|
||||
<h4 id="analyzer_diagnositics">Controlling Static Analyzer Diagnostics</h4>
|
||||
|
||||
<p>While not strictly part of the compiler, the diagnostics from Clang's <a
|
||||
href="http://clang-analyzer.llvm.org">static analyzer</a> can also be influenced
|
||||
by the user via changes to the source code. This can be done in two ways:
|
||||
|
||||
<ul>
|
||||
|
||||
<li id="analyzer_annotations"><b>Annotations</b>: The static analyzer recognizes various GCC-style
|
||||
attributes (e.g., <tt>__attribute__((nonnull)))</tt>) that can either suppress
|
||||
static analyzer warnings or teach the analyzer about code invariants which
|
||||
enable it to find more bugs. While many of these attributes are standard GCC
|
||||
attributes, additional ones have added to Clang to specifically support the
|
||||
static analyzer. Detailed information on these annotations can be found in the
|
||||
<a href="http://clang-analyzer.llvm.org/annotations.html">analyzer's
|
||||
documentation</a>.</li>
|
||||
|
||||
<li><b><tt>__clang_analyzer__</tt></b>: When the static analyzer is using Clang
|
||||
to parse source files, it implicitly defines the preprocessor macro
|
||||
<tt>__clang_analyzer__</tt>. While discouraged, code can use this macro to
|
||||
selectively exclude code the analyzer examines. Here is an example:
|
||||
|
||||
<pre>
|
||||
#ifndef __clang_analyzer__
|
||||
// Code not to be analyzed
|
||||
#endif
|
||||
</pre>
|
||||
|
||||
In general, this usage is discouraged. Instead, we prefer that users file bugs
|
||||
against the analyzer when it flags false positives. There is also active
|
||||
discussion of allowing users in the future to selectively silence specific
|
||||
analyzer warnings (some which can already be done using <a
|
||||
href="analyzer_annotations">annotations</a>).</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="precompiledheaders">Precompiled Headers</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p><a href="http://en.wikipedia.org/wiki/Precompiled_header">Precompiled
|
||||
headers</a> are a general approach employed by many compilers to reduce
|
||||
compilation time. The underlying motivation of the approach is that it is
|
||||
common for the same (and often large) header files to be included by
|
||||
multiple source files. Consequently, compile times can often be greatly improved
|
||||
by caching some of the (redundant) work done by a compiler to process headers.
|
||||
Precompiled header files, which represent one of many ways to implement
|
||||
this optimization, are literally files that represent an on-disk cache that
|
||||
contains the vital information necessary to reduce some of the work
|
||||
needed to process a corresponding header file. While details of precompiled
|
||||
headers vary between compilers, precompiled headers have been shown to be a
|
||||
highly effective at speeding up program compilation on systems with very large
|
||||
system headers (e.g., Mac OS/X).</p>
|
||||
|
||||
<h4>Generating a PCH File</h4>
|
||||
|
||||
<p>To generate a PCH file using Clang, one invokes Clang with
|
||||
the <b><tt>-x <i><language></i>-header</tt></b> option. This mirrors the
|
||||
interface in GCC for generating PCH files:</p>
|
||||
|
||||
<pre>
|
||||
$ gcc -x c-header test.h -o test.h.gch
|
||||
$ clang -x c-header test.h -o test.h.pch
|
||||
</pre>
|
||||
|
||||
<h4>Using a PCH File</h4>
|
||||
|
||||
<p>A PCH file can then be used as a prefix header when a
|
||||
<b><tt>-include</tt></b> option is passed to <tt>clang</tt>:</p>
|
||||
|
||||
<pre>
|
||||
$ clang -include test.h test.c -o test
|
||||
</pre>
|
||||
|
||||
<p>The <tt>clang</tt> driver will first check if a PCH file for <tt>test.h</tt>
|
||||
is available; if so, the contents of <tt>test.h</tt> (and the files it includes)
|
||||
will be processed from the PCH file. Otherwise, Clang falls back to
|
||||
directly processing the content of <tt>test.h</tt>. This mirrors the behavior of
|
||||
GCC.</p>
|
||||
|
||||
<p><b>NOTE:</b> Clang does <em>not</em> automatically use PCH files
|
||||
for headers that are directly included within a source file. For example:</p>
|
||||
|
||||
<pre>
|
||||
$ clang -x c-header test.h -o test.h.pch
|
||||
$ cat test.c
|
||||
#include "test.h"
|
||||
$ clang test.c -o test
|
||||
</pre>
|
||||
|
||||
<p>In this example, <tt>clang</tt> will not automatically use the PCH file for
|
||||
<tt>test.h</tt> since <tt>test.h</tt> was included directly in the source file
|
||||
and not specified on the command line using <tt>-include</tt>.</p>
|
||||
|
||||
<h4>Relocatable PCH Files</h4>
|
||||
<p>It is sometimes necessary to build a precompiled header from headers that
|
||||
are not yet in their final, installed locations. For example, one might build a
|
||||
precompiled header within the build tree that is then meant to be installed
|
||||
alongside the headers. Clang permits the creation of "relocatable" precompiled
|
||||
headers, which are built with a given path (into the build directory) and can
|
||||
later be used from an installed location.</p>
|
||||
|
||||
<p>To build a relocatable precompiled header, place your headers into a
|
||||
subdirectory whose structure mimics the installed location. For example, if you
|
||||
want to build a precompiled header for the header <code>mylib.h</code> that
|
||||
will be installed into <code>/usr/include</code>, create a subdirectory
|
||||
<code>build/usr/include</code> and place the header <code>mylib.h</code> into
|
||||
that subdirectory. If <code>mylib.h</code> depends on other headers, then
|
||||
they can be stored within <code>build/usr/include</code> in a way that mimics
|
||||
the installed location.</p>
|
||||
|
||||
<p>Building a relocatable precompiled header requires two additional arguments.
|
||||
First, pass the <code>--relocatable-pch</code> flag to indicate that the
|
||||
resulting PCH file should be relocatable. Second, pass
|
||||
<code>-isysroot /path/to/build</code>, which makes all includes for your
|
||||
library relative to the build directory. For example:</p>
|
||||
|
||||
<pre>
|
||||
# clang -x c-header --relocatable-pch -isysroot /path/to/build /path/to/build/mylib.h mylib.h.pch
|
||||
</pre>
|
||||
|
||||
<p>When loading the relocatable PCH file, the various headers used in the PCH
|
||||
file are found from the system header root. For example, <code>mylib.h</code>
|
||||
can be found in <code>/usr/include/mylib.h</code>. If the headers are installed
|
||||
in some other system root, the <code>-isysroot</code> option can be used provide
|
||||
a different system root from which the headers will be based. For example,
|
||||
<code>-isysroot /Developer/SDKs/MacOSX10.4u.sdk</code> will look for
|
||||
<code>mylib.h</code> in
|
||||
<code>/Developer/SDKs/MacOSX10.4u.sdk/usr/include/mylib.h</code>.</p>
|
||||
|
||||
<p>Relocatable precompiled headers are intended to be used in a limited number
|
||||
of cases where the compilation environment is tightly controlled and the
|
||||
precompiled header cannot be generated after headers have been installed.
|
||||
Relocatable precompiled headers also have some performance impact, because
|
||||
the difference in location between the header locations at PCH build time vs.
|
||||
at the time of PCH use requires one of the PCH optimizations,
|
||||
<code>stat()</code> caching, to be disabled. However, this change is only
|
||||
likely to affect PCH files that reference a large number of headers.</p>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="codegen">Controlling Code Generation</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>Clang provides a number of ways to control code generation. The options are listed below.</p>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fcatch-undefined-behavior"><b>-fcatch-undefined-behavior</b>: Turn
|
||||
on runtime code generation to check for undefined behavior.</dt>
|
||||
|
||||
<dd>This option, which defaults to off, controls whether or not Clang
|
||||
adds runtime checks for undefined runtime behavior. If the check fails,
|
||||
<tt>__builtin_trap()</tt> is used to indicate failure.
|
||||
The checks are:
|
||||
<p>
|
||||
<li>Subscripting where the static type of one operand is variable
|
||||
which is decayed from an array type and the other operand is
|
||||
greater than the size of the array or less than zero.</li>
|
||||
<li>Shift operators where the amount shifted is greater or equal to the
|
||||
promoted bit-width of the left-hand-side or less than zero.</li>
|
||||
<li>If control flow reaches __builtin_unreachable.
|
||||
<li>When llvm implements more __builtin_object_size support, reads and
|
||||
writes for objects that __builtin_object_size indicates we aren't
|
||||
accessing valid memory. Bit-fields and vectors are not yet checked.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dt id="opt_fno-assume-sane-operator-new"><b>-fno-assume-sane-operator-new</b>:
|
||||
Don't assume that the C++'s new operator is sane.</dt>
|
||||
<dd>This option tells the compiler to do not assume that C++'s global new
|
||||
operator will always return a pointer that do not
|
||||
alias any other pointer when the function returns.</dd>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="c">C Language Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The support for standard C in clang is feature-complete except for the C99
|
||||
floating-point pragmas.</p>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="c_ext">Extensions supported by clang</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>See <a href="LanguageExtensions.html">clang language extensions</a>.</p>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="c_modes">Differences between various standard modes</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>clang supports the -std option, which changes what language mode clang uses.
|
||||
The supported modes for C are c89, gnu89, c94, c99, gnu99 and various aliases
|
||||
for those modes. If no -std option is specified, clang defaults to gnu99 mode.
|
||||
</p>
|
||||
|
||||
<p>Differences between all c* and gnu* modes:</p>
|
||||
<ul>
|
||||
<li>c* modes define "__STRICT_ANSI__".</li>
|
||||
<li>Target-specific defines not prefixed by underscores, like "linux", are
|
||||
defined in gnu* modes.</li>
|
||||
<li>Trigraphs default to being off in gnu* modes; they can be enabled by the
|
||||
-trigraphs option.</li>
|
||||
<li>The parser recognizes "asm" and "typeof" as keywords in gnu* modes; the
|
||||
variants "__asm__" and "__typeof__" are recognized in all modes.</li>
|
||||
<li>The Apple "blocks" extension is recognized by default in gnu* modes
|
||||
on some platforms; it can be enabled in any mode with the "-fblocks"
|
||||
option.</li>
|
||||
</ul>
|
||||
|
||||
<p>Differences between *89 and *99 modes:</p>
|
||||
<ul>
|
||||
<li>The *99 modes default to implementing "inline" as specified in C99, while
|
||||
the *89 modes implement the GNU version. This can be overridden for individual
|
||||
functions with the __gnu_inline__ attribute.</li>
|
||||
<li>Digraphs are not recognized in c89 mode.</li>
|
||||
<li>The scope of names defined inside a "for", "if", "switch", "while", or "do"
|
||||
statement is different. (example: "if ((struct x {int x;}*)0) {}".)</li>
|
||||
<li>__STDC_VERSION__ is not defined in *89 modes.</li>
|
||||
<li>"inline" is not recognized as a keyword in c89 mode.</li>
|
||||
<li>"restrict" is not recognized as a keyword in *89 modes.</li>
|
||||
<li>Commas are allowed in integer constant expressions in *99 modes.</li>
|
||||
<li>Arrays which are not lvalues are not implicitly promoted to pointers in
|
||||
*89 modes.</li>
|
||||
<li>Some warnings are different.</li>
|
||||
</ul>
|
||||
|
||||
<p>c94 mode is identical to c89 mode except that digraphs are enabled in
|
||||
c94 mode (FIXME: And __STDC_VERSION__ should be defined!).</p>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="c_unimpl_gcc">GCC extensions not implemented yet</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>clang tries to be compatible with gcc as much as possible, but some gcc
|
||||
extensions are not implemented yet:</p>
|
||||
|
||||
<ul>
|
||||
<li>clang does not support __label__
|
||||
(<a href="http://llvm.org/bugs/show_bug.cgi?id=3429">bug 3429</a>). This is
|
||||
a relatively small feature, so it is likely to be implemented relatively
|
||||
soon.</li>
|
||||
|
||||
<li>clang does not support #pragma weak
|
||||
(<a href="http://llvm.org/bugs/show_bug.cgi?id=3679">bug 3679</a>). Due to
|
||||
the uses described in the bug, this is likely to be implemented at some
|
||||
point, at least partially.</li>
|
||||
|
||||
<li>clang does not support code generation for local variables pinned to
|
||||
registers (<a href="http://llvm.org/bugs/show_bug.cgi?id=3933">bug 3933</a>).
|
||||
This is a relatively small feature, so it is likely to be implemented
|
||||
relatively soon.</li>
|
||||
|
||||
<li>clang does not support decimal floating point types (_Decimal32 and
|
||||
friends) or fixed-point types (_Fract and friends); nobody has expressed
|
||||
interest in these features yet, so it's hard to say when they will be
|
||||
implemented.</li>
|
||||
|
||||
<li>clang does not support nested functions; this is a complex feature which
|
||||
is infrequently used, so it is unlikely to be implemented anytime soon.</li>
|
||||
|
||||
<li>clang does not support global register variables, this is unlikely
|
||||
to be implemented soon because it requires additional LLVM backend support.
|
||||
</li>
|
||||
|
||||
<li>clang does not support static initialization of flexible array
|
||||
members. This appears to be a rarely used extension, but could be
|
||||
implemented pending user demand.</li>
|
||||
|
||||
<li>clang does not support __builtin_va_arg_pack/__builtin_va_arg_pack_len.
|
||||
This is used rarely, but in some potentially interesting places, like the
|
||||
glibc headers, so it may be implemented pending user demand. Note that
|
||||
because clang pretends to be like GCC 4.2, and this extension was introduced
|
||||
in 4.3, the glibc headers will not try to use this extension with clang at
|
||||
the moment.</li>
|
||||
|
||||
<li>clang does not support the gcc extension for forward-declaring function
|
||||
parameters; this has not showed up in any real-world code yet, though, so it
|
||||
might never be implemented.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>This is not a complete list; if you find an unsupported extension
|
||||
missing from this list, please send an e-mail to cfe-dev. This list
|
||||
currently excludes C++; see <a href="#cxx">C++ Language Features</a>.
|
||||
Also, this list does not include bugs in mostly-implemented features; please
|
||||
see the <a href="http://llvm.org/bugs/buglist.cgi?quicksearch=product%3Aclang+component%3A-New%2BBugs%2CAST%2CBasic%2CDriver%2CHeaders%2CLLVM%2BCodeGen%2Cparser%2Cpreprocessor%2CSemantic%2BAnalyzer">
|
||||
bug tracker</a> for known existing bugs (FIXME: Is there a section for
|
||||
bug-reporting guidelines somewhere?).</p>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="c_unsupp_gcc">Intentionally unsupported GCC extensions</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<ul>
|
||||
|
||||
<li>clang does not support the gcc extension that allows variable-length arrays
|
||||
in structures. This is for a few of reasons: one, it is tricky
|
||||
to implement, two, the extension is completely undocumented, and three, the
|
||||
extension appears to be rarely used.</li>
|
||||
|
||||
<li>clang does not support duplicate definitions of a function where one is
|
||||
inline. This complicates clients of the AST which normally can expect there is
|
||||
at most one definition for each function. Source code using this feature should
|
||||
be changed to define the inline and out-of-line definitions in separate
|
||||
translation units.</li>
|
||||
|
||||
<li>clang does not have an equivalent to gcc's "fold"; this means that
|
||||
clang doesn't accept some constructs gcc might accept in contexts where a
|
||||
constant expression is required, like "x-x" where x is a variable, or calls
|
||||
to C library functions like strlen.</li>
|
||||
|
||||
<li>clang does not support multiple alternative constraints in inline asm; this
|
||||
is an extremely obscure feature which would be complicated to implement
|
||||
correctly.</li>
|
||||
|
||||
<li>clang does not support __builtin_apply and friends; this extension is
|
||||
extremely obscure and difficult to implement reliably.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="c_ms">Microsoft extensions</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>clang has some experimental support for extensions from
|
||||
Microsoft Visual C++; to enable it, use the -fms-extensions command-line
|
||||
option. This is the default for Windows targets. Note that the
|
||||
support is incomplete; enabling Microsoft extensions will silently drop
|
||||
certain constructs (including __declspec and Microsoft-style asm statements).
|
||||
</p>
|
||||
|
||||
<li>clang does not support the Microsoft extension where anonymous
|
||||
record members can be declared using user defined typedefs.</li>
|
||||
|
||||
<li>clang supports the Microsoft "#pragma pack" feature for
|
||||
controlling record layout. GCC also contains support for this feature,
|
||||
however where MSVC and GCC are incompatible clang follows the MSVC
|
||||
definition.</li>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="target_features">Target-Specific Features and Limitations</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="target_arch">CPU Architectures Features and Limitations</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<!-- ======================== -->
|
||||
<h4 id="target_arch_x86">X86</h4>
|
||||
<!-- ======================== -->
|
||||
<p>The support for X86 (both 32-bit and 64-bit) is considered stable
|
||||
on Darwin (Mac OS/X), Linux, FreeBSD, and Dragonfly BSD: it has been tested to
|
||||
correctly compile large C and Objective-C codebases. (FIXME: Anything specific
|
||||
we want to say here? Possibly mention some LLVM x86 limitations?)
|
||||
|
||||
<!-- ======================== -->
|
||||
<h4 id="target_arch_arm">ARM</h4>
|
||||
<!-- ======================== -->
|
||||
ARM support is mostly feature-complete, but still experimental; it hasn't
|
||||
undergone significant testing.
|
||||
|
||||
<!-- ======================== -->
|
||||
<h4 id="target_arch_other">Other platforms</h4>
|
||||
<!-- ======================== -->
|
||||
clang currently contains some support for PPC and Sparc; however, significant
|
||||
pieces of code generation are still missing, and they haven't undergone
|
||||
significant testing.
|
||||
|
||||
<p>clang contains some support for the embedded PIC16 processor
|
||||
(FIXME: I haven't been keeping track of this; what should this say?).
|
||||
|
||||
<p>clang contains limited support for the MSP430 embedded processor, but both
|
||||
the clang support and the LLVM backend support are highly experimental.
|
||||
|
||||
<p>Other platforms are completely unsupported at the moment. Adding the
|
||||
minimal support needed for parsing and semantic analysis on a new platform
|
||||
is quite easy; see lib/Basic/Targets.cpp in the clang source tree. This level
|
||||
of support is also sufficient for conversion to LLVM IR for simple programs.
|
||||
Proper support for conversion to LLVM IR requires adding code to
|
||||
lib/CodeGen/CGCall.cpp at the moment; this is likely to change soon, though.
|
||||
Generating assembly requires a suitable LLVM backend.
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="target_os">Operating System Features and Limitations</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<!-- ======================================= -->
|
||||
<h4 id="target_os_darwin">Darwin (Mac OS/X)</h4>
|
||||
<!-- ======================================= -->
|
||||
|
||||
<p>No __thread support, 64-bit ObjC support requires SL tools.</p>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,378 +0,0 @@
|
||||
BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
|
||||
font-family: Verdana,Geneva,Arial,Helvetica,sans-serif;
|
||||
}
|
||||
BODY,TD {
|
||||
font-size: 90%;
|
||||
}
|
||||
H1 {
|
||||
text-align: center;
|
||||
font-size: 140%;
|
||||
font-weight: bold;
|
||||
}
|
||||
H2 {
|
||||
font-size: 120%;
|
||||
font-style: italic;
|
||||
}
|
||||
H3 {
|
||||
font-size: 100%;
|
||||
}
|
||||
CAPTION { font-weight: bold }
|
||||
DIV.qindex {
|
||||
width: 100%;
|
||||
background-color: #eeeeff;
|
||||
border: 1px solid #b0b0b0;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 140%;
|
||||
}
|
||||
DIV.nav {
|
||||
width: 100%;
|
||||
background-color: #eeeeff;
|
||||
border: 1px solid #b0b0b0;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 140%;
|
||||
}
|
||||
DIV.navtab {
|
||||
background-color: #eeeeff;
|
||||
border: 1px solid #b0b0b0;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
margin-right: 15px;
|
||||
padding: 2px;
|
||||
}
|
||||
TD.navtab {
|
||||
font-size: 70%;
|
||||
}
|
||||
A.qindex {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #1A419D;
|
||||
}
|
||||
A.qindex:visited {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #1A419D
|
||||
}
|
||||
A.qindex:hover {
|
||||
text-decoration: none;
|
||||
background-color: #ddddff;
|
||||
}
|
||||
A.qindexHL {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
border: 1px double #9295C2;
|
||||
}
|
||||
A.qindexHL:hover {
|
||||
text-decoration: none;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
}
|
||||
A.qindexHL:visited {
|
||||
text-decoration: none; background-color: #6666cc; color: #ffffff }
|
||||
A.el { text-decoration: none; font-weight: bold }
|
||||
A.elRef { font-weight: bold }
|
||||
A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
|
||||
A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
|
||||
A.codeRef:link { font-weight: normal; color: #0000FF}
|
||||
A.codeRef:visited { font-weight: normal; color: #0000FF}
|
||||
A:hover { text-decoration: none; background-color: #f2f2ff }
|
||||
DL.el { margin-left: -1cm }
|
||||
.fragment {
|
||||
font-family: Fixed, monospace;
|
||||
font-size: 95%;
|
||||
}
|
||||
PRE.fragment {
|
||||
border: 1px solid #CCCCCC;
|
||||
background-color: #f5f5f5;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
margin-left: 2px;
|
||||
margin-right: 8px;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
|
||||
TD.md { background-color: #F4F4FB; font-weight: bold; }
|
||||
TD.mdPrefix {
|
||||
background-color: #F4F4FB;
|
||||
color: #606060;
|
||||
font-size: 80%;
|
||||
}
|
||||
TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }
|
||||
TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; }
|
||||
DIV.groupHeader {
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
|
||||
BODY {
|
||||
background: white;
|
||||
color: black;
|
||||
margin-right: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
TD.indexkey {
|
||||
background-color: #eeeeff;
|
||||
font-weight: bold;
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px;
|
||||
border: 1px solid #CCCCCC;
|
||||
}
|
||||
TD.indexvalue {
|
||||
background-color: #eeeeff;
|
||||
font-style: italic;
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px;
|
||||
border: 1px solid #CCCCCC;
|
||||
}
|
||||
TR.memlist {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
P.formulaDsp { text-align: center; }
|
||||
IMG.formulaDsp { }
|
||||
IMG.formulaInl { vertical-align: middle; }
|
||||
SPAN.keyword { color: #008000 }
|
||||
SPAN.keywordtype { color: #604020 }
|
||||
SPAN.keywordflow { color: #e08000 }
|
||||
SPAN.comment { color: #800000 }
|
||||
SPAN.preprocessor { color: #806020 }
|
||||
SPAN.stringliteral { color: #002080 }
|
||||
SPAN.charliteral { color: #008080 }
|
||||
.mdTable {
|
||||
border: 1px solid #868686;
|
||||
background-color: #F4F4FB;
|
||||
}
|
||||
.mdRow {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
.mdescLeft {
|
||||
padding: 0px 8px 4px 8px;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1px none #E0E0E0;
|
||||
border-right: 1px none #E0E0E0;
|
||||
border-bottom: 1px none #E0E0E0;
|
||||
border-left: 1px none #E0E0E0;
|
||||
margin: 0px;
|
||||
}
|
||||
.mdescRight {
|
||||
padding: 0px 8px 4px 8px;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1px none #E0E0E0;
|
||||
border-right: 1px none #E0E0E0;
|
||||
border-bottom: 1px none #E0E0E0;
|
||||
border-left: 1px none #E0E0E0;
|
||||
margin: 0px;
|
||||
}
|
||||
.memItemLeft {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memItemRight {
|
||||
padding: 1px 8px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplItemLeft {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: none;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplItemRight {
|
||||
padding: 1px 8px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: none;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplParams {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
color: #606060;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.search { color: #003399;
|
||||
font-weight: bold;
|
||||
}
|
||||
FORM.search {
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
INPUT.search { font-size: 75%;
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
background-color: #eeeeff;
|
||||
}
|
||||
TD.tiny { font-size: 75%;
|
||||
}
|
||||
a {
|
||||
color: #252E78;
|
||||
}
|
||||
a:visited {
|
||||
color: #3D2185;
|
||||
}
|
||||
.dirtab { padding: 4px;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #b0b0b0;
|
||||
}
|
||||
TH.dirtab { background: #eeeeff;
|
||||
font-weight: bold;
|
||||
}
|
||||
HR { height: 1px;
|
||||
border: none;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
/*
|
||||
* LLVM Modifications.
|
||||
* Note: Everything above here is generated with "doxygen -w htlm" command. See
|
||||
* "doxygen --help" for details. What follows are CSS overrides for LLVM
|
||||
* specific formatting. We want to keep the above so it can be replaced with
|
||||
* subsequent doxygen upgrades.
|
||||
*/
|
||||
|
||||
.footer {
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.title {
|
||||
font-size: 25pt;
|
||||
color: black; background: url("http://llvm.org/img/lines.gif");
|
||||
font-weight: bold;
|
||||
border-width: 1px;
|
||||
border-style: solid none solid none;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
padding-left: 8pt;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 2px
|
||||
}
|
||||
A:link {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-weight: bolder;
|
||||
}
|
||||
A:visited {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
font-weight: bolder;
|
||||
}
|
||||
A:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
font-weight: bolder;
|
||||
}
|
||||
A:active {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
font-weight: bolder;
|
||||
font-style: italic;
|
||||
}
|
||||
H1 {
|
||||
text-align: center;
|
||||
font-size: 140%;
|
||||
font-weight: bold;
|
||||
}
|
||||
H2 {
|
||||
font-size: 120%;
|
||||
font-style: italic;
|
||||
}
|
||||
H3 {
|
||||
font-size: 100%;
|
||||
}
|
||||
A.qindex {}
|
||||
A.qindexRef {}
|
||||
A.el { text-decoration: none; font-weight: bold }
|
||||
A.elRef { font-weight: bold }
|
||||
A.code { text-decoration: none; font-weight: normal; color: #4444ee }
|
||||
A.codeRef { font-weight: normal; color: #4444ee }
|
||||
@@ -1,10 +0,0 @@
|
||||
<hr>
|
||||
<p class="footer">
|
||||
Generated on $datetime by <a href="http://www.doxygen.org">Doxygen
|
||||
$doxygenversion</a>.</p>
|
||||
|
||||
<p class="footer">
|
||||
See the <a href="http://clang.llvm.org">Main Clang Web Page</a> for more
|
||||
information.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,9 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
|
||||
<meta name="keywords" content="clang,LLVM,Low Level Virtual Machine,C,C++,doxygen,API,frontend,documentation"/>
|
||||
<meta name="description" content="C++ source code API documentation for clang."/>
|
||||
<title>clang: $title</title>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css"/>
|
||||
</head><body>
|
||||
<p class="title">clang API Documentation</p>
|
||||
@@ -1,15 +0,0 @@
|
||||
/// @mainpage clang
|
||||
///
|
||||
/// @section main_intro Introduction
|
||||
/// Welcome to the clang project.
|
||||
///
|
||||
/// This documentation describes the @b internal software that makes
|
||||
/// up clang, not the @b external use of clang. There are no instructions
|
||||
/// here on how to use clang, only the APIs that make up the software. For
|
||||
/// usage instructions, please see the programmer's guide or reference
|
||||
/// manual.
|
||||
///
|
||||
/// @section main_caveat Caveat
|
||||
/// This documentation is generated directly from the source code with doxygen.
|
||||
/// Since clang is constantly under active development, what you're about to
|
||||
/// read is out of date!
|
||||
@@ -1,4 +0,0 @@
|
||||
<title>'clang' C frontend documentation</title>
|
||||
|
||||
None yet, sorry :(
|
||||
|
||||
@@ -1,267 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>The Index Library</title>
|
||||
<link type="text/css" rel="stylesheet" href="../menu.css" />
|
||||
<link type="text/css" rel="stylesheet" href="../content.css" />
|
||||
<style type="text/css">
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!--#include virtual="../menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>The Index Library</h1>
|
||||
|
||||
<p><b>Table of Contents</b></p>
|
||||
<ul>
|
||||
<li><a href="#philosophy">Design Philosophy</a></li>
|
||||
<li><a href="#classes">Classes</a>
|
||||
<ul>
|
||||
<li><a href="#entity">Entity</a></li>
|
||||
<li><a href="#astlocation">ASTLocation</a></li>
|
||||
<li><a href="#declreferencemap">DeclReferenceMap</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#functions">Functions</a>
|
||||
<ul>
|
||||
<li><a href="#resolveloc">ResolveLocationInAST</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#astfiles">AST Files</a></li>
|
||||
<li><a href="#indextest">index-test tool</a>
|
||||
<ul>
|
||||
<li><a href="#indextestusage">Usage</a></li>
|
||||
<li><a href="#indextestexamples">Examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="philosophy">Design Philosophy</h2>
|
||||
|
||||
<p> The Index library is meant to provide the basic infrastructure for
|
||||
cross-translation-unit analysis and is primarily focused on indexing
|
||||
related functionality. It provides an API for clients that need to
|
||||
accurately map the AST nodes of the ASTContext to the locations in the source files.
|
||||
It also allows them to analyze information across multiple translation units.</p>
|
||||
|
||||
<p>As a "general rule", ASTContexts are considered the primary source of
|
||||
information that a client wants about a translation unit. There will be no such class as an
|
||||
"indexing database" that stores, for example, source locations of identifiers separately from ASTContext.
|
||||
All the information that a client needs from a translation unit will be extracted from the ASTContext.</p>
|
||||
|
||||
<h2 id="classes">Classes</h2>
|
||||
|
||||
<h3 id="entity">Entity</h3>
|
||||
|
||||
<p>To be able to reason about semantically the same Decls that are contained in multiple ASTContexts, the 'Entity' class was introduced.
|
||||
An Entity is an ASTContext-independent "token" that can be created from a Decl (and a typename in the future) with
|
||||
the purpose to "resolve" it into a Decl belonging to another ASTContext. Some examples to make the concept of Entities more clear:</p>
|
||||
|
||||
<p>
|
||||
t1.c:
|
||||
<pre class="code_example">
|
||||
void foo(void);
|
||||
void bar(void);
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
t2.c:
|
||||
<pre class="code_example">
|
||||
void foo(void) {
|
||||
}
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Translation unit <code>t1.c</code> contains 2 Entities <code>foo</code> and <code>bar</code>, while <code>t2.c</code> contains 1 Entity <code>foo</code>.
|
||||
Entities are uniqued in such a way that the Entity* pointer for <code>t1.c/foo</code> is the same as the Entity* pointer for <code>t2.c/foo</code>.
|
||||
An Entity doesn't convey any information about the declaration, it is more like an opaque pointer used only to get the
|
||||
associated Decl out of an ASTContext so that the actual information for the declaration can be accessed.
|
||||
Another important aspect of Entities is that they can only be created/associated for declarations that are visible outside the
|
||||
translation unit. This means that for:
|
||||
</p>
|
||||
<p>
|
||||
t3.c:
|
||||
<pre class="code_example">
|
||||
static void foo(void);
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
there can be no Entity (if you ask for the Entity* of the static function <code>foo</code> you'll get a null pointer).
|
||||
This is for 2 reasons:
|
||||
<ul>
|
||||
<li>To preserve the invariant that the same Entity* pointers refer to the same semantic Decls.
|
||||
In the above example <code>t1.c/foo</code> and <code>t2.c/foo</code> are the same, while <code>t3.c/foo</code> is different.</li>
|
||||
<li>The purpose of Entity is to get the same semantic Decl from multiple ASTContexts. For a Decl that is not visible
|
||||
outside of its own translation unit, you don't need an Entity since it won't appear in another ASTContext.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h3 id="astlocation">ASTLocation</h3>
|
||||
|
||||
Encapsulates a "point" in the AST tree of the ASTContext.
|
||||
It represents either a Decl*, or a Stmt* along with its immediate Decl* parent.
|
||||
An example for its usage is that libIndex will provide the references of <code>foo</code> in the form of ASTLocations,
|
||||
"pointing" at the expressions that reference <code>foo</code>.
|
||||
|
||||
<h3 id="declreferencemap">DeclReferenceMap</h3>
|
||||
|
||||
Accepts an ASTContext and creates a mapping from NamedDecls to the ASTLocations that reference them (in the same ASTContext).
|
||||
|
||||
<h2 id="functions">Functions</h2>
|
||||
|
||||
<h3 id="resolveloc">ResolveLocationInAST</h3>
|
||||
|
||||
A function that accepts an ASTContext and a SourceLocation which it resolves into an ASTLocation.
|
||||
|
||||
<h2 id="astfiles">AST Files</h2>
|
||||
|
||||
The precompiled headers implementation of clang (<a href="http://clang.llvm.org/docs/PCHInternals.html">PCH</a>) is ideal for storing an ASTContext in a compact form that
|
||||
will be loaded later for AST analysis. An "AST file" refers to a translation unit that was "compiled" into a precompiled header file.
|
||||
|
||||
<h2 id="indextest">index-test tool</h2>
|
||||
|
||||
<h3 id="indextestusage">Usage</h3>
|
||||
|
||||
A command-line tool that exercises the libIndex API, useful for testing its features.
|
||||
As input it accepts multiple AST files (representing multiple translation units) and a few options:
|
||||
|
||||
<p>
|
||||
<pre class="code_example">
|
||||
-point-at [file:line:column]
|
||||
</pre>
|
||||
Resolves a [file:line:column] triplet into a ASTLocation from the first AST file. If no other option is specified, it prints the ASTLocation.
|
||||
It also prints a declaration's associated doxygen comment, if one is available.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<pre class="code_example">
|
||||
-print-refs
|
||||
</pre>
|
||||
Prints the ASTLocations that reference the declaration that was resolved out of the [file:line:column] triplet
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<pre class="code_example">
|
||||
-print-defs
|
||||
</pre>
|
||||
Prints the ASTLocations that define the resolved declaration
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<pre class="code_example">
|
||||
-print-decls
|
||||
</pre>
|
||||
Prints the ASTLocations that declare the resolved declaration
|
||||
</p>
|
||||
|
||||
<h3 id="indextestexamples">Examples</h3>
|
||||
|
||||
<p>
|
||||
Here's an example of using index-test:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We have 3 files,
|
||||
</p>
|
||||
|
||||
<p>
|
||||
foo.h:
|
||||
<pre class="code_example">
|
||||
extern int global_var;
|
||||
|
||||
void foo_func(int param1);
|
||||
void bar_func(void);
|
||||
</pre>
|
||||
|
||||
t1.c:
|
||||
<pre class="code_example">
|
||||
#include "foo.h"
|
||||
|
||||
void foo_func(int param1) {
|
||||
int local_var = global_var;
|
||||
for (int for_var = 100; for_var < 500; ++for_var) {
|
||||
local_var = param1 + for_var;
|
||||
}
|
||||
bar_func();
|
||||
}
|
||||
</pre>
|
||||
|
||||
t2.c:
|
||||
<pre class="code_example">
|
||||
#include "foo.h"
|
||||
|
||||
int global_var = 10;
|
||||
|
||||
void bar_func(void) {
|
||||
global_var += 100;
|
||||
foo_func(global_var);
|
||||
}
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You first get AST files out of <code>t1.c</code> and <code>t2.c</code>:
|
||||
|
||||
<pre class="code_example">
|
||||
$ clang -emit-ast t1.c -o t1.ast
|
||||
$ clang -emit-ast t2.c -o t2.ast
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Find the ASTLocation under this position of <code>t1.c</code>:
|
||||
<pre class="code_example">
|
||||
[...]
|
||||
void foo_func(int param1) {
|
||||
int local_var = global_var;
|
||||
^
|
||||
[...]
|
||||
</pre>
|
||||
|
||||
<pre class="code_example">
|
||||
$ index-test t1.ast -point-at t1.c:4:23
|
||||
> [Decl: Var local_var | Stmt: DeclRefExpr global_var] <t1.c:4:19, t1.c:4:19>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Find the declaration:
|
||||
|
||||
<pre class="code_example">
|
||||
$ index-test t1.ast -point-at t1.c:4:23 -print-decls
|
||||
> [Decl: Var global_var] <foo.h:1:12, foo.h:1:12>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Find the references:
|
||||
|
||||
<pre class="code_example">
|
||||
$ index-test t1.ast t2.ast -point-at t1.c:4:23 -print-refs
|
||||
> [Decl: Var local_var | Stmt: DeclRefExpr global_var] <t1.c:4:19, t1.c:4:19>
|
||||
> [Decl: Function bar_func | Stmt: DeclRefExpr global_var] <t2.c:6:3, t2.c:6:3>
|
||||
> [Decl: Function bar_func | Stmt: DeclRefExpr global_var] <t2.c:7:12, t2.c:7:12>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Find definitions:
|
||||
|
||||
<pre class="code_example">
|
||||
$ index-test t1.ast t2.ast -point-at t1.c:4:23 -print-defs
|
||||
> [Decl: Var global_var] <t2.c:3:5, t2.c:3:18>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,116 +0,0 @@
|
||||
##===- docs/tools/Makefile ---------------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
ifdef BUILD_FOR_WEBSITE
|
||||
|
||||
# FIXME: This was copied from the CommandGuide makefile. Figure out
|
||||
# how to get this stuff on the website.
|
||||
|
||||
# This special case is for keeping the CommandGuide on the LLVM web site
|
||||
# up to date automatically as the documents are checked in. It must build
|
||||
# the POD files to HTML only and keep them in the src directories. It must also
|
||||
# build in an unconfigured tree, hence the ifdef. To use this, run
|
||||
# make -s BUILD_FOR_WEBSITE=1 inside the cvs commit script.
|
||||
SRC_DOC_DIR=
|
||||
DST_HTML_DIR=html/
|
||||
DST_MAN_DIR=man/man1/
|
||||
DST_PS_DIR=ps/
|
||||
CLANG_VERSION := trunk
|
||||
|
||||
# If we are in BUILD_FOR_WEBSITE mode, default to the all target.
|
||||
all:: html man ps
|
||||
|
||||
clean:
|
||||
rm -f pod2htm*.*~~ $(HTML) $(MAN) $(PS)
|
||||
|
||||
# To create other directories, as needed, and timestamp their creation
|
||||
%/.dir:
|
||||
-mkdir $* > /dev/null
|
||||
date > $@
|
||||
|
||||
else
|
||||
|
||||
# Otherwise, if not in BUILD_FOR_WEBSITE mode, use the project info.
|
||||
CLANG_LEVEL := ../..
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
||||
CLANG_VERSION := $(word 3,$(shell grep "CLANG_VERSION " \
|
||||
$(PROJ_OBJ_DIR)/$(CLANG_LEVEL)/include/clang/Basic/Version.inc))
|
||||
|
||||
SRC_DOC_DIR=$(PROJ_SRC_DIR)/
|
||||
DST_HTML_DIR=$(PROJ_OBJ_DIR)/
|
||||
DST_MAN_DIR=$(PROJ_OBJ_DIR)/
|
||||
DST_PS_DIR=$(PROJ_OBJ_DIR)/
|
||||
|
||||
endif
|
||||
|
||||
|
||||
POD := $(wildcard $(SRC_DOC_DIR)*.pod)
|
||||
HTML := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_HTML_DIR)%.html, $(POD))
|
||||
MAN := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_MAN_DIR)%.1, $(POD))
|
||||
PS := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_PS_DIR)%.ps, $(POD))
|
||||
|
||||
ifdef ONLY_MAN_DOCS
|
||||
INSTALL_TARGETS := install-man
|
||||
else
|
||||
INSTALL_TARGETS := install-html install-man install-ps
|
||||
endif
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .html .pod .1 .ps
|
||||
|
||||
$(DST_HTML_DIR)%.html: %.pod $(DST_HTML_DIR)/.dir
|
||||
pod2html --css=manpage.css --htmlroot=. \
|
||||
--podpath=. --infile=$< --outfile=$@ --title=$*
|
||||
|
||||
$(DST_MAN_DIR)%.1: %.pod $(DST_MAN_DIR)/.dir
|
||||
pod2man --release "clang $(CLANG_VERSION)" --center="Clang Tools Documentation" $< $@
|
||||
|
||||
$(DST_PS_DIR)%.ps: $(DST_MAN_DIR)%.1 $(DST_PS_DIR)/.dir
|
||||
groff -Tps -man $< > $@
|
||||
|
||||
|
||||
html: $(HTML)
|
||||
man: $(MAN)
|
||||
ps: $(PS)
|
||||
|
||||
EXTRA_DIST := $(POD)
|
||||
|
||||
clean-local::
|
||||
$(Verb) $(RM) -f pod2htm*.*~~ $(HTML) $(MAN) $(PS)
|
||||
|
||||
HTML_DIR := $(DESTDIR)$(PROJ_docsdir)/html/clang
|
||||
MAN_DIR := $(DESTDIR)$(PROJ_mandir)/man1
|
||||
PS_DIR := $(DESTDIR)$(PROJ_docsdir)/ps
|
||||
|
||||
install-html:: $(HTML)
|
||||
$(Echo) Installing HTML Clang Tools Documentation
|
||||
$(Verb) $(MKDIR) $(HTML_DIR)
|
||||
$(Verb) $(DataInstall) $(HTML) $(HTML_DIR)
|
||||
$(Verb) $(DataInstall) $(PROJ_SRC_DIR)/manpage.css $(HTML_DIR)
|
||||
|
||||
install-man:: $(MAN)
|
||||
$(Echo) Installing MAN Clang Tools Documentation
|
||||
$(Verb) $(MKDIR) $(MAN_DIR)
|
||||
$(Verb) $(DataInstall) $(MAN) $(MAN_DIR)
|
||||
|
||||
install-ps:: $(PS)
|
||||
$(Echo) Installing PS Clang Tools Documentation
|
||||
$(Verb) $(MKDIR) $(PS_DIR)
|
||||
$(Verb) $(DataInstall) $(PS) $(PS_DIR)
|
||||
|
||||
install-local:: $(INSTALL_TARGETS)
|
||||
|
||||
uninstall-local::
|
||||
$(Echo) Uninstalling Clang Tools Documentation
|
||||
$(Verb) $(RM) -rf $(HTML_DIR) $(MAN_DIR) $(PS_DIR)
|
||||
|
||||
printvars::
|
||||
$(Echo) "POD : " '$(POD)'
|
||||
$(Echo) "HTML : " '$(HTML)'
|
||||
@@ -1,535 +0,0 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
clang - the Clang C and Objective-C compiler
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<clang> [B<-c>|B<-S>|B<-E>] B<-std=>I<standard> B<-g>
|
||||
[B<-O0>|B<-O1>|B<-O2>|B<-Os>|B<-O3>|B<-O4>]
|
||||
B<-W>I<warnings...> B<-pedantic>
|
||||
B<-I>I<dir...> B<-L>I<dir...>
|
||||
B<-D>I<macro[=defn]>
|
||||
B<-f>I<feature-option...>
|
||||
B<-m>I<machine-option...>
|
||||
B<-o> I<output-file>
|
||||
I<input-filenames>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<clang> is a C and Objective-C compiler which encompasses preprocessing,
|
||||
parsing, optimization, code generation, assembly, and linking. Depending on
|
||||
which high-level mode setting is passed, Clang will stop before doing a full
|
||||
link. While Clang is highly integrated, it is important to understand the
|
||||
stages of compilation, to understand how to invoke it. These stages are:
|
||||
|
||||
=over
|
||||
|
||||
=item B<Driver>
|
||||
|
||||
The B<clang> executable is actually a small driver which controls the overall
|
||||
execution of other tools such as the compiler, assembler and linker. Typically
|
||||
you do not need to interact with the driver, but you transparently use it to run
|
||||
the other tools.
|
||||
|
||||
=item B<Preprocessing>
|
||||
|
||||
This stage handles tokenization of the input source file, macro expansion,
|
||||
#include expansion and handling of other preprocessor directives. The output of
|
||||
this stage is typically called a ".i" (for C) or ".mi" (for Objective-C) file.
|
||||
|
||||
=item B<Parsing and Semantic Analysis>
|
||||
|
||||
This stage parses the input file, translating preprocessor tokens into a parse
|
||||
tree. Once in the form of a parser tree, it applies semantic analysis to compute
|
||||
types for expressions as well and determine whether the code is well formed. This
|
||||
stage is responsible for generating most of the compiler warnings as well as
|
||||
parse errors. The output of this stage is an "Abstract Syntax Tree" (AST).
|
||||
|
||||
=item B<Code Generation and Optimization>
|
||||
|
||||
This stage translates an AST into low-level intermediate code (known as "LLVM
|
||||
IR") and ultimately to machine code. This phase is responsible for optimizing
|
||||
the generated code and handling target-specfic code generation. The output of
|
||||
this stage is typically called a ".s" file or "assembly" file.
|
||||
|
||||
Clang also supports the use of an integrated assembler, in which the code
|
||||
generator produces object files directly. This avoids the overhead of generating
|
||||
the ".s" file and of calling the target assembler.
|
||||
|
||||
=item B<Assembler>
|
||||
|
||||
This stage runs the target assembler to translate the output of the compiler
|
||||
into a target object file. The output of this stage is typically called a ".o"
|
||||
file or "object" file.
|
||||
|
||||
=item B<Linker>
|
||||
|
||||
This stage runs the target linker to merge multiple object files into an
|
||||
executable or dynamic library. The output of this stage is typically called an
|
||||
"a.out", ".dylib" or ".so" file.
|
||||
|
||||
=back
|
||||
|
||||
The Clang compiler supports a large number of options to control each of these
|
||||
stages. In addition to compilation of code, Clang also supports other tools:
|
||||
|
||||
B<Clang Static Analyzer>
|
||||
|
||||
The Clang Static Analyzer is a tool that scans source code to try to find bugs
|
||||
though code analysis. This tool uses many parts of Clang and is built into the
|
||||
same driver.
|
||||
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=head2 Stage Selection Options
|
||||
|
||||
=over
|
||||
|
||||
=item B<-E>
|
||||
|
||||
Run the preprocessor stage.
|
||||
|
||||
=item B<-fsyntax-only>
|
||||
|
||||
Run the preprocessor, parser and type checking stages.
|
||||
|
||||
=item B<-S>
|
||||
|
||||
Run the previous stages as well as LLVM generation and optimization stages and
|
||||
target-specific code generation, producing an assembly file.
|
||||
|
||||
=item B<-c>
|
||||
|
||||
Run all of the above, plus the assembler, generating a target ".o" object file.
|
||||
|
||||
=item B<no stage selection option>
|
||||
|
||||
If no stage selection option is specified, all stages above are run, and the
|
||||
linker is run to combine the results into an executable or shared library.
|
||||
|
||||
=item B<--analyze>
|
||||
|
||||
Run the Clang Static Analyzer.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
|
||||
=head2 Language Selection and Mode Options
|
||||
|
||||
=over
|
||||
|
||||
=item B<-x> I<language>
|
||||
|
||||
Treat subsequent input files as having type I<language>.
|
||||
|
||||
=item B<-std>=I<language>
|
||||
|
||||
Specify the language standard to compile for.
|
||||
|
||||
=item B<-ansi>
|
||||
|
||||
Same as B<-std=c89>.
|
||||
|
||||
=item B<-ObjC++>
|
||||
|
||||
Treat source input files as Objective-C++ inputs.
|
||||
|
||||
=item B<-ObjC>
|
||||
|
||||
Treat source input files as Objective-C inputs.
|
||||
|
||||
=item B<-trigraphs>
|
||||
|
||||
Enable trigraphs.
|
||||
|
||||
=item B<-ffreestanding>
|
||||
|
||||
Indicate that the file should be compiled for a freestanding, not a hosted,
|
||||
environment.
|
||||
|
||||
=item B<-fno-builtin>
|
||||
|
||||
Disable special handling and optimizations of builtin functions like strlen and
|
||||
malloc.
|
||||
|
||||
=item B<-fmath-errno>
|
||||
|
||||
Indicate that math functions should be treated as updating errno.
|
||||
|
||||
=item B<-fpascal-strings>
|
||||
|
||||
Enable support for Pascal-style strings with "\pfoo".
|
||||
|
||||
=item B<-fms-extensions>
|
||||
|
||||
Enable support for Microsoft extensions.
|
||||
|
||||
=item B<-fborland-extensions>
|
||||
|
||||
Enable support for Borland extensions.
|
||||
|
||||
=item B<-fwritable-strings>
|
||||
|
||||
Make all string literals default to writable. This disables uniquing of
|
||||
strings and other optimizations.
|
||||
|
||||
=item B<-flax-vector-conversions>
|
||||
|
||||
Allow loose type checking rules for implicit vector conversions.
|
||||
|
||||
=item B<-fblocks>
|
||||
|
||||
Enable the "Blocks" language feature.
|
||||
|
||||
|
||||
=item B<-fobjc-gc-only>
|
||||
|
||||
Indicate that Objective-C code should be compiled in GC-only mode, which only
|
||||
works when Objective-C Garbage Collection is enabled.
|
||||
|
||||
=item B<-fobjc-gc>
|
||||
|
||||
Indicate that Objective-C code should be compiled in hybrid-GC mode, which works
|
||||
with both GC and non-GC mode.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
|
||||
=head2 Target Selection Options
|
||||
|
||||
Clang fully supports cross compilation as an inherent part of its design.
|
||||
Depending on how your version of Clang is configured, it may have support for
|
||||
a number of cross compilers, or may only support a native target.
|
||||
|
||||
=over
|
||||
|
||||
=item B<-arch> I<architecture>
|
||||
|
||||
Specify the architecture to build for.
|
||||
|
||||
=item B<-mmacosx-version-min>=I<version>
|
||||
|
||||
When building for Mac OS/X, specify the minimum version supported by your
|
||||
application.
|
||||
|
||||
=item B<-miphoneos-version-min>
|
||||
|
||||
When building for iPhone OS, specify the minimum version supported by your
|
||||
application.
|
||||
|
||||
|
||||
=item B<-march>=I<cpu>
|
||||
|
||||
Specify that Clang should generate code for a specific processor family member
|
||||
and later. For example, if you specify -march=i486, the compiler is allowed to
|
||||
generate instructions that are valid on i486 and later processors, but which
|
||||
may not exist on earlier ones.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Code Generation Options
|
||||
|
||||
=over
|
||||
|
||||
=item B<-O0> B<-O1> B<-O2> B<-Os> B<-O3> B<-O4>
|
||||
|
||||
Specify which optimization level to use. B<-O0> means "no optimization": this
|
||||
level compiles the fastest and generates the most debuggable code. B<-O2> is a
|
||||
moderate level of optimization which enables most optimizations. B<-Os> is like
|
||||
B<-O2> with extra optimizations to reduce code size. B<-O3> is like B<-O2>,
|
||||
except that it enables optimizations that take longer to perform or that may
|
||||
generate larger code (in an attempt to make the program run faster). On
|
||||
supported platforms, B<-O4> enables link-time optimization; object files are
|
||||
stored in the LLVM bitcode file format and whole program optimization is done at
|
||||
link time. B<-O1> is somewhere between B<-O0> and B<-O2>.
|
||||
|
||||
=item B<-g>
|
||||
|
||||
Generate debug information. Note that Clang debug information works best at
|
||||
B<-O0>. At higher optimization levels, only line number information is
|
||||
currently available.
|
||||
|
||||
=item B<-fexceptions>
|
||||
|
||||
Enable generation of unwind information, this allows exceptions to be thrown
|
||||
through Clang compiled stack frames. This is on by default in x86-64.
|
||||
|
||||
=item B<-ftrapv>
|
||||
|
||||
Generate code to catch integer overflow errors. Signed integer overflow is
|
||||
undefined in C, with this flag, extra code is generated to detect this and abort
|
||||
when it happens.
|
||||
|
||||
|
||||
=item B<-fvisibility>
|
||||
|
||||
This flag sets the default visibility level.
|
||||
|
||||
=item B<-fcommon>
|
||||
|
||||
This flag specifies that variables without initializers get common linkage. It
|
||||
can be disabled with B<-fno-common>.
|
||||
|
||||
=item B<-flto> B<-emit-llvm>
|
||||
|
||||
Generate output files in LLVM formats, suitable for link time optimization. When
|
||||
used with B<-S> this generates LLVM intermediate language assembly files,
|
||||
otherwise this generates LLVM bitcode format object files (which may be passed
|
||||
to the linker depending on the stage selection options).
|
||||
|
||||
=cut
|
||||
|
||||
##=item B<-fnext-runtime> B<-fobjc-nonfragile-abi> B<-fgnu-runtime>
|
||||
##These options specify which Objective-C runtime the code generator should
|
||||
##target. FIXME: we don't want people poking these generally.
|
||||
|
||||
=pod
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Driver Options
|
||||
|
||||
=over
|
||||
|
||||
=item B<-###>
|
||||
|
||||
Print the commands to run for this compilation.
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Display available options.
|
||||
|
||||
=item B<-Qunused-arguments>
|
||||
|
||||
Don't emit warning for unused driver arguments.
|
||||
|
||||
=item B<-Wa,>I<args>
|
||||
|
||||
Pass the comma separated arguments in I<args> to the assembler.
|
||||
|
||||
=item B<-Wl,>I<args>
|
||||
|
||||
Pass the comma separated arguments in I<args> to the linker.
|
||||
|
||||
=item B<-Wp,>I<args>
|
||||
|
||||
Pass the comma separated arguments in I<args> to the preprocessor.
|
||||
|
||||
=item B<-Xanalyzer> I<arg>
|
||||
|
||||
Pass I<arg> to the static analyzer.
|
||||
|
||||
=item B<-Xassembler> I<arg>
|
||||
|
||||
Pass I<arg> to the assembler.
|
||||
|
||||
=item B<-Xclang> I<arg>
|
||||
|
||||
Pass I<arg> to the clang compiler frontend.
|
||||
|
||||
=item B<-Xlinker> I<arg>
|
||||
|
||||
Pass I<arg> to the linker.
|
||||
|
||||
=item B<-mllvm> I<arg>
|
||||
|
||||
Pass I<arg> to the LLVM backend.
|
||||
|
||||
=item B<-Xpreprocessor> I<arg>
|
||||
|
||||
Pass I<arg> to the preprocessor.
|
||||
|
||||
=item B<-o> I<file>
|
||||
|
||||
Write output to I<file>.
|
||||
|
||||
=item B<-print-file-name>=I<file>
|
||||
|
||||
Print the full library path of I<file>.
|
||||
|
||||
=item B<-print-libgcc-file-name>
|
||||
|
||||
Print the library path for "libgcc.a".
|
||||
|
||||
=item B<-print-prog-name>=I<name>
|
||||
|
||||
Print the full program path of I<name>.
|
||||
|
||||
=item B<-print-search-dirs>
|
||||
|
||||
Print the paths used for finding libraries and programs.
|
||||
|
||||
=item B<-save-temps>
|
||||
|
||||
Save intermediate compilation results.
|
||||
|
||||
=item B<-integrated-as> B<-no-integrated-as>
|
||||
|
||||
Used to enable and disable, respectively, the use of the integrated
|
||||
assembler. Whether the integrated assembler is on by default is target
|
||||
dependent.
|
||||
|
||||
=item B<-time>
|
||||
|
||||
Time individual commands.
|
||||
|
||||
=item B<-ftime-report>
|
||||
|
||||
Print timing summary of each stage of compilation.
|
||||
|
||||
=item B<-v>
|
||||
|
||||
Show commands to run and use verbose output.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Diagnostics Options
|
||||
|
||||
=over
|
||||
|
||||
=item B<-fshow-column>
|
||||
B<-fshow-source-location>
|
||||
B<-fcaret-diagnostics>
|
||||
B<-fdiagnostics-fixit-info>
|
||||
B<-fdiagnostics-parseable-fixits>
|
||||
B<-fdiagnostics-print-source-range-info>
|
||||
B<-fprint-source-range-info>
|
||||
B<-fdiagnostics-show-option>
|
||||
B<-fmessage-length>
|
||||
|
||||
These options control how Clang prints out information about diagnostics (errors
|
||||
and warnings). Please see the Clang User's Manual for more information.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Preprocessor Options
|
||||
|
||||
=over
|
||||
|
||||
=item B<-D>I<macroname=value>
|
||||
|
||||
Adds an implicit #define into the predefines buffer which is read before the
|
||||
source file is preprocessed.
|
||||
|
||||
=item B<-U>I<macroname>
|
||||
|
||||
Adds an implicit #undef into the predefines buffer which is read before the
|
||||
source file is preprocessed.
|
||||
|
||||
=item B<-include> I<filename>
|
||||
|
||||
Adds an implicit #include into the predefines buffer which is read before the
|
||||
source file is preprocessed.
|
||||
|
||||
=item B<-I>I<directory>
|
||||
|
||||
Add the specified directory to the search path for include files.
|
||||
|
||||
=item B<-F>I<directory>
|
||||
|
||||
Add the specified directory to the search path for framework include files.
|
||||
|
||||
=item B<-nostdinc>
|
||||
|
||||
Do not search the standard system directories for include files.
|
||||
|
||||
=item B<-nobuiltininc>
|
||||
|
||||
Do not search clang's builtin directory for include files.
|
||||
|
||||
=cut
|
||||
|
||||
## TODO, but do we really want people using this stuff?
|
||||
#=item B<-idirafter>I<directory>
|
||||
#=item B<-iquote>I<directory>
|
||||
#=item B<-isystem>I<directory>
|
||||
#=item B<-iprefix>I<directory>
|
||||
#=item B<-iwithprefix>I<directory>
|
||||
#=item B<-iwithprefixbefore>I<directory>
|
||||
#=item B<-isysroot>
|
||||
|
||||
=pod
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
|
||||
=cut
|
||||
|
||||
### TODO someday.
|
||||
#=head2 Warning Control Options
|
||||
#=over
|
||||
#=back
|
||||
#=head2 Code Generation and Optimization Options
|
||||
#=over
|
||||
#=back
|
||||
#=head2 Assembler Options
|
||||
#=over
|
||||
#=back
|
||||
#=head2 Linker Options
|
||||
#=over
|
||||
#=back
|
||||
#=head2 Static Analyzer Options
|
||||
#=over
|
||||
#=back
|
||||
|
||||
=pod
|
||||
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
=over
|
||||
|
||||
=item B<TMPDIR>, B<TEMP>, B<TMP>
|
||||
|
||||
These environment variables are checked, in order, for the location to
|
||||
write temporary files used during the compilation process.
|
||||
|
||||
=item B<CPATH>
|
||||
|
||||
If this environment variable is present, it is treated as a delimited
|
||||
list of paths to be added to the default system include path list. The
|
||||
delimiter is the platform dependent delimitor, as used in the I<PATH>
|
||||
environment variable.
|
||||
|
||||
Empty components in the environment variable are ignored.
|
||||
|
||||
=item B<C_INCLUDE_PATH>, B<OBJC_INCLUDE_PATH>, B<CPLUS_INCLUDE_PATH>,
|
||||
B<OBJCPLUS_INCLUDE_PATH>
|
||||
|
||||
These environment variables specify additional paths, as for CPATH,
|
||||
which are only used when processing the appropriate language.
|
||||
|
||||
=item B<MACOSX_DEPLOYMENT_TARGET>
|
||||
|
||||
If -mmacosx-version-min is unspecified, the default deployment target
|
||||
is read from this environment variable. This option only affects darwin
|
||||
targets.
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
To report bugs, please visit L<http://llvm.org/bugs/>. Most bug reports should
|
||||
include preprocessed source files (use the B<-E> option) and the full output of
|
||||
the compiler, along with information to reproduce.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
as(1), ld(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Maintained by the Clang / LLVM Team (L<http://clang.llvm.org>).
|
||||
|
||||
=cut
|
||||
@@ -1,256 +0,0 @@
|
||||
/* Based on http://www.perldoc.com/css/perldoc.css */
|
||||
|
||||
@import url("../llvm.css");
|
||||
|
||||
body { font-family: Arial,Helvetica; }
|
||||
|
||||
blockquote { margin: 10pt; }
|
||||
|
||||
h1, a { color: #336699; }
|
||||
|
||||
|
||||
/*** Top menu style ****/
|
||||
.mmenuon {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #ff6600; font-size: 10pt;
|
||||
}
|
||||
.mmenuoff {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #ffffff; font-size: 10pt;
|
||||
}
|
||||
.cpyright {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #ffffff; font-size: xx-small;
|
||||
}
|
||||
.cpyrightText {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #ffffff; font-size: xx-small;
|
||||
}
|
||||
.sections {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: 11pt;
|
||||
}
|
||||
.dsections {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: 12pt;
|
||||
}
|
||||
.slink {
|
||||
font-family: Arial,Helvetica; font-weight: normal; text-decoration: none;
|
||||
color: #000000; font-size: 9pt;
|
||||
}
|
||||
|
||||
.slink2 { font-family: Arial,Helvetica; text-decoration: none; color: #336699; }
|
||||
|
||||
.maintitle {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: 18pt;
|
||||
}
|
||||
.dblArrow {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: small;
|
||||
}
|
||||
.menuSec {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: small;
|
||||
}
|
||||
|
||||
.newstext {
|
||||
font-family: Arial,Helvetica; font-size: small;
|
||||
}
|
||||
|
||||
.linkmenu {
|
||||
font-family: Arial,Helvetica; color: #000000; font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
P {
|
||||
font-family: Arial,Helvetica;
|
||||
}
|
||||
|
||||
PRE {
|
||||
font-size: 10pt;
|
||||
}
|
||||
.quote {
|
||||
font-family: Times; text-decoration: none;
|
||||
color: #000000; font-size: 9pt; font-style: italic;
|
||||
}
|
||||
.smstd { font-family: Arial,Helvetica; color: #000000; font-size: x-small; }
|
||||
.std { font-family: Arial,Helvetica; color: #000000; }
|
||||
.meerkatTitle {
|
||||
font-family: sans-serif; font-size: x-small; color: black; }
|
||||
|
||||
.meerkatDescription { font-family: sans-serif; font-size: 10pt; color: black }
|
||||
.meerkatCategory {
|
||||
font-family: sans-serif; font-size: 9pt; font-weight: bold; font-style: italic;
|
||||
color: brown; }
|
||||
.meerkatChannel {
|
||||
font-family: sans-serif; font-size: 9pt; font-style: italic; color: brown; }
|
||||
.meerkatDate { font-family: sans-serif; font-size: xx-small; color: #336699; }
|
||||
|
||||
.tocTitle {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #333333; font-size: 10pt;
|
||||
}
|
||||
|
||||
.toc-item {
|
||||
font-family: Arial,Helvetica; font-weight: bold;
|
||||
color: #336699; font-size: 10pt; text-decoration: underline;
|
||||
}
|
||||
|
||||
.perlVersion {
|
||||
font-family: Arial,Helvetica; font-weight: bold;
|
||||
color: #336699; font-size: 10pt; text-decoration: none;
|
||||
}
|
||||
|
||||
.podTitle {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.docTitle {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #000000; font-size: 10pt;
|
||||
}
|
||||
.dotDot {
|
||||
font-family: Arial,Helvetica; font-weight: bold;
|
||||
color: #000000; font-size: 9pt;
|
||||
}
|
||||
|
||||
.docSec {
|
||||
font-family: Arial,Helvetica; font-weight: normal;
|
||||
color: #333333; font-size: 9pt;
|
||||
}
|
||||
.docVersion {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: 10pt;
|
||||
}
|
||||
|
||||
.docSecs-on {
|
||||
font-family: Arial,Helvetica; font-weight: normal; text-decoration: none;
|
||||
color: #ff0000; font-size: 10pt;
|
||||
}
|
||||
.docSecs-off {
|
||||
font-family: Arial,Helvetica; font-weight: normal; text-decoration: none;
|
||||
color: #333333; font-size: 10pt;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: medium;
|
||||
}
|
||||
h1 {
|
||||
font-family: Verdana,Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: large;
|
||||
}
|
||||
|
||||
DL {
|
||||
font-family: Arial,Helvetica; font-weight: normal; text-decoration: none;
|
||||
color: #333333; font-size: 10pt;
|
||||
}
|
||||
|
||||
UL > LI > A {
|
||||
font-family: Arial,Helvetica; font-weight: bold;
|
||||
color: #336699; font-size: 10pt;
|
||||
}
|
||||
|
||||
.moduleInfo {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #333333; font-size: 11pt;
|
||||
}
|
||||
|
||||
.moduleInfoSec {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: 10pt;
|
||||
}
|
||||
|
||||
.moduleInfoVal {
|
||||
font-family: Arial,Helvetica; font-weight: normal; text-decoration: underline;
|
||||
color: #000000; font-size: 10pt;
|
||||
}
|
||||
|
||||
.cpanNavTitle {
|
||||
font-family: Arial,Helvetica; font-weight: bold;
|
||||
color: #ffffff; font-size: 10pt;
|
||||
}
|
||||
.cpanNavLetter {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #333333; font-size: 9pt;
|
||||
}
|
||||
.cpanCat {
|
||||
font-family: Arial,Helvetica; font-weight: bold; text-decoration: none;
|
||||
color: #336699; font-size: 9pt;
|
||||
}
|
||||
|
||||
.bttndrkblue-bkgd-top {
|
||||
background-color: #225688;
|
||||
background-image: url(/global/mvc_objects/images/bttndrkblue_bgtop.gif);
|
||||
}
|
||||
.bttndrkblue-bkgd-left {
|
||||
background-color: #225688;
|
||||
background-image: url(/global/mvc_objects/images/bttndrkblue_bgleft.gif);
|
||||
}
|
||||
.bttndrkblue-bkgd {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
background-repeat: no-repeat;
|
||||
background-color: #225688;
|
||||
background-image: url(/global/mvc_objects/images/bttndrkblue_bgmiddle.gif);
|
||||
vertical-align: top;
|
||||
}
|
||||
.bttndrkblue-bkgd-right {
|
||||
background-color: #225688;
|
||||
background-image: url(/global/mvc_objects/images/bttndrkblue_bgright.gif);
|
||||
}
|
||||
.bttndrkblue-bkgd-bottom {
|
||||
background-color: #225688;
|
||||
background-image: url(/global/mvc_objects/images/bttndrkblue_bgbottom.gif);
|
||||
}
|
||||
.bttndrkblue-text a {
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
}
|
||||
a.bttndrkblue-text:hover {
|
||||
color: #ffDD3C;
|
||||
text-decoration: none;
|
||||
}
|
||||
.bg-ltblue {
|
||||
background-color: #f0f5fa;
|
||||
}
|
||||
|
||||
.border-left-b {
|
||||
background: #f0f5fa url(/i/corner-leftline.gif) repeat-y;
|
||||
}
|
||||
|
||||
.border-right-b {
|
||||
background: #f0f5fa url(/i/corner-rightline.gif) repeat-y;
|
||||
}
|
||||
|
||||
.border-top-b {
|
||||
background: #f0f5fa url(/i/corner-topline.gif) repeat-x;
|
||||
}
|
||||
|
||||
.border-bottom-b {
|
||||
background: #f0f5fa url(/i/corner-botline.gif) repeat-x;
|
||||
}
|
||||
|
||||
.border-right-w {
|
||||
background: #ffffff url(/i/corner-rightline.gif) repeat-y;
|
||||
}
|
||||
|
||||
.border-top-w {
|
||||
background: #ffffff url(/i/corner-topline.gif) repeat-x;
|
||||
}
|
||||
|
||||
.border-bottom-w {
|
||||
background: #ffffff url(/i/corner-botline.gif) repeat-x;
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.border-left-w {
|
||||
background: #ffffff url(/i/corner-leftline.gif) repeat-y;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
add_subdirectory(clang-interpreter)
|
||||
add_subdirectory(PrintFunctionNames)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
##===- examples/Makefile -----------------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
CLANG_LEVEL := ..
|
||||
|
||||
PARALLEL_DIRS := clang-interpreter PrintFunctionNames
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
@@ -1,10 +0,0 @@
|
||||
set(MODULE TRUE)
|
||||
|
||||
set(LLVM_NO_RTTI 1)
|
||||
|
||||
add_clang_library(PrintFunctionNames PrintFunctionNames.cpp)
|
||||
|
||||
set_target_properties(PrintFunctionNames
|
||||
PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
PREFIX "")
|
||||
@@ -1,24 +0,0 @@
|
||||
##===- examples/PrintFunctionNames/Makefile ----------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
CLANG_LEVEL := ../..
|
||||
LIBRARYNAME = PrintFunctionNames
|
||||
|
||||
# If we don't need RTTI or EH, there's no reason to export anything
|
||||
# from the plugin.
|
||||
ifneq ($(REQUIRES_RTTI), 1)
|
||||
ifneq ($(REQUIRES_EH), 1)
|
||||
EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/PrintFunctionNames.exports
|
||||
endif
|
||||
endif
|
||||
|
||||
LINK_LIBS_IN_SHARED = 1
|
||||
SHARED_LIBRARY = 1
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
@@ -1,69 +0,0 @@
|
||||
//===- PrintFunctionNames.cpp ---------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Example clang plugin which simply prints the names of all the top-level decls
|
||||
// in the input file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Frontend/FrontendPluginRegistry.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/AST.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace clang;
|
||||
|
||||
namespace {
|
||||
|
||||
class PrintFunctionsConsumer : public ASTConsumer {
|
||||
public:
|
||||
virtual void HandleTopLevelDecl(DeclGroupRef DG) {
|
||||
for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
|
||||
const Decl *D = *i;
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
|
||||
llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class PrintFunctionNamesAction : public PluginASTAction {
|
||||
protected:
|
||||
ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) {
|
||||
return new PrintFunctionsConsumer();
|
||||
}
|
||||
|
||||
bool ParseArgs(const CompilerInstance &CI,
|
||||
const std::vector<std::string>& args) {
|
||||
for (unsigned i = 0, e = args.size(); i != e; ++i) {
|
||||
llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n";
|
||||
|
||||
// Example error handling.
|
||||
if (args[i] == "-an-error") {
|
||||
Diagnostic &D = CI.getDiagnostics();
|
||||
unsigned DiagID = D.getCustomDiagID(
|
||||
Diagnostic::Error, "invalid argument '" + args[i] + "'");
|
||||
D.Report(DiagID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (args.size() && args[0] == "help")
|
||||
PrintHelp(llvm::errs());
|
||||
|
||||
return true;
|
||||
}
|
||||
void PrintHelp(llvm::raw_ostream& ros) {
|
||||
ros << "Help for PrintFunctionNames plugin goes here\n";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
|
||||
X("print-fns", "print function names");
|
||||
@@ -1 +0,0 @@
|
||||
_ZN4llvm8Registry*
|
||||
@@ -1,10 +0,0 @@
|
||||
This is a simple example demonstrating how to use clang's facility for
|
||||
providing AST consumers using a plugin.
|
||||
|
||||
You will probably need to build clang so that it exports all symbols (disable
|
||||
TOOL_NO_EXPORT in the tools/clang Makefile).
|
||||
|
||||
Once the plugin is built, you can run it using:
|
||||
--
|
||||
$ clang -cc1 -load path/to/PrintFunctionNames.so -plugin print-fns some-input-file.c
|
||||
--
|
||||
@@ -1,34 +0,0 @@
|
||||
set(LLVM_NO_RTTI 1)
|
||||
|
||||
set(LLVM_USED_LIBS
|
||||
clangFrontend
|
||||
clangSerialization
|
||||
clangDriver
|
||||
clangCodeGen
|
||||
clangSema
|
||||
clangChecker
|
||||
clangIndex
|
||||
clangAnalysis
|
||||
clangRewrite
|
||||
clangAST
|
||||
clangParse
|
||||
clangLex
|
||||
clangBasic
|
||||
)
|
||||
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
jit
|
||||
interpreter
|
||||
nativecodegen
|
||||
asmparser
|
||||
bitreader
|
||||
bitwriter
|
||||
codegen
|
||||
ipo
|
||||
selectiondag
|
||||
)
|
||||
|
||||
add_clang_executable(clang-interpreter
|
||||
main.cpp
|
||||
)
|
||||
add_dependencies(clang-interpreter clang-headers)
|
||||
@@ -1,24 +0,0 @@
|
||||
##===- examples/clang-interpreter/Makefile -----------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
CLANG_LEVEL := ../..
|
||||
|
||||
TOOLNAME = clang-interpreter
|
||||
NO_INSTALL = 1
|
||||
|
||||
# No plugins, optimize startup time.
|
||||
TOOL_NO_EXPORTS = 1
|
||||
|
||||
LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \
|
||||
selectiondag asmparser
|
||||
USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a clangCodeGen.a \
|
||||
clangSema.a clangChecker.a clangAnalysis.a clangRewrite.a \
|
||||
clangAST.a clangParse.a clangLex.a clangBasic.a
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
@@ -1,17 +0,0 @@
|
||||
This is an example of Clang based interpreter, for executing standalone C
|
||||
programs.
|
||||
|
||||
It demonstrates the following features:
|
||||
1. Parsing standard compiler command line arguments using the Driver library.
|
||||
|
||||
2. Constructing a Clang compiler instance, using the appropriate arguments
|
||||
derived in step #1.
|
||||
|
||||
3. Invoking the Clang compiler to lex, parse, syntax check, and then generate
|
||||
LLVM code.
|
||||
|
||||
4. Use the LLVM JIT functionality to execute the final module.
|
||||
|
||||
The implementation has many limitations and is not designed to be a full fledged
|
||||
C interpreter. It is designed to demonstrate a simple but functional use of the
|
||||
Clang compiler libraries.
|
||||
@@ -1,155 +0,0 @@
|
||||
//===-- examples/clang-interpreter/main.cpp - Clang C Interpreter Example -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/CodeGen/CodeGenAction.h"
|
||||
#include "clang/Driver/Compilation.h"
|
||||
#include "clang/Driver/Driver.h"
|
||||
#include "clang/Driver/Tool.h"
|
||||
#include "clang/Frontend/CompilerInvocation.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/DiagnosticOptions.h"
|
||||
#include "clang/Frontend/FrontendDiagnostic.h"
|
||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/System/Host.h"
|
||||
#include "llvm/System/Path.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
using namespace clang;
|
||||
using namespace clang::driver;
|
||||
|
||||
llvm::sys::Path 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::Path::GetMainExecutable(Argv0, MainAddr);
|
||||
}
|
||||
|
||||
int Execute(llvm::Module *Mod, char * const *envp) {
|
||||
llvm::InitializeNativeTarget();
|
||||
|
||||
std::string Error;
|
||||
llvm::OwningPtr<llvm::ExecutionEngine> EE(
|
||||
llvm::ExecutionEngine::createJIT(Mod, &Error));
|
||||
if (!EE) {
|
||||
llvm::errs() << "unable to make execution engine: " << Error << "\n";
|
||||
return 255;
|
||||
}
|
||||
|
||||
llvm::Function *EntryFn = Mod->getFunction("main");
|
||||
if (!EntryFn) {
|
||||
llvm::errs() << "'main' function not found in module.\n";
|
||||
return 255;
|
||||
}
|
||||
|
||||
// FIXME: Support passing arguments.
|
||||
std::vector<std::string> Args;
|
||||
Args.push_back(Mod->getModuleIdentifier());
|
||||
|
||||
return EE->runFunctionAsMain(EntryFn, Args, envp);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv, char * const *envp) {
|
||||
void *MainAddr = (void*) (intptr_t) GetExecutablePath;
|
||||
llvm::sys::Path Path = GetExecutablePath(argv[0]);
|
||||
TextDiagnosticPrinter *DiagClient =
|
||||
new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
|
||||
|
||||
Diagnostic Diags(DiagClient);
|
||||
Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
|
||||
"a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false,
|
||||
Diags);
|
||||
TheDriver.setTitle("clang interpreter");
|
||||
|
||||
// FIXME: This is a hack to try to force the driver to do something we can
|
||||
// recognize. We need to extend the driver library to support this use model
|
||||
// (basically, exactly one input, and the operation mode is hard wired).
|
||||
llvm::SmallVector<const char *, 16> Args(argv, argv + argc);
|
||||
Args.push_back("-fsyntax-only");
|
||||
llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(Args.size(),
|
||||
Args.data()));
|
||||
if (!C)
|
||||
return 0;
|
||||
|
||||
// FIXME: This is copied from ASTUnit.cpp; simplify and eliminate.
|
||||
|
||||
// We expect to get back exactly one command job, if we didn't something
|
||||
// failed. Extract that job from the compilation.
|
||||
const driver::JobList &Jobs = C->getJobs();
|
||||
if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
|
||||
llvm::SmallString<256> Msg;
|
||||
llvm::raw_svector_ostream OS(Msg);
|
||||
C->PrintJob(OS, C->getJobs(), "; ", true);
|
||||
Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
|
||||
return 1;
|
||||
}
|
||||
|
||||
const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
|
||||
if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
|
||||
Diags.Report(diag::err_fe_expected_clang_command);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Initialize a compiler invocation object from the clang (-cc1) arguments.
|
||||
const driver::ArgStringList &CCArgs = Cmd->getArguments();
|
||||
llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
|
||||
CompilerInvocation::CreateFromArgs(*CI,
|
||||
const_cast<const char **>(CCArgs.data()),
|
||||
const_cast<const char **>(CCArgs.data()) +
|
||||
CCArgs.size(),
|
||||
Diags);
|
||||
|
||||
// Show the invocation, with -v.
|
||||
if (CI->getHeaderSearchOpts().Verbose) {
|
||||
llvm::errs() << "clang invocation:\n";
|
||||
C->PrintJob(llvm::errs(), C->getJobs(), "\n", true);
|
||||
llvm::errs() << "\n";
|
||||
}
|
||||
|
||||
// FIXME: This is copied from cc1_main.cpp; simplify and eliminate.
|
||||
|
||||
// Create a compiler instance to handle the actual work.
|
||||
CompilerInstance Clang;
|
||||
Clang.setLLVMContext(new llvm::LLVMContext);
|
||||
Clang.setInvocation(CI.take());
|
||||
|
||||
// Create the compilers actual diagnostics engine.
|
||||
Clang.createDiagnostics(int(CCArgs.size()),const_cast<char**>(CCArgs.data()));
|
||||
if (!Clang.hasDiagnostics())
|
||||
return 1;
|
||||
|
||||
// Infer the builtin include path if unspecified.
|
||||
if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
|
||||
Clang.getHeaderSearchOpts().ResourceDir.empty())
|
||||
Clang.getHeaderSearchOpts().ResourceDir =
|
||||
CompilerInvocation::GetResourcesPath(argv[0], MainAddr);
|
||||
|
||||
// Create and execute the frontend to generate an LLVM bitcode module.
|
||||
llvm::OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction());
|
||||
if (!Clang.ExecuteAction(*Act))
|
||||
return 1;
|
||||
|
||||
int Res = 255;
|
||||
if (llvm::Module *Module = Act->takeModule())
|
||||
Res = Execute(Module, envp);
|
||||
|
||||
// Shutdown.
|
||||
|
||||
llvm::llvm_shutdown();
|
||||
|
||||
return Res;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
set(LLVM_NO_RTTI 1)
|
||||
|
||||
set(LLVM_USED_LIBS
|
||||
clangIndex
|
||||
clangFrontend
|
||||
clangDriver
|
||||
clangSema
|
||||
clangAnalysis
|
||||
clangSerialization
|
||||
clangChecker
|
||||
clangRewrite
|
||||
clangAST
|
||||
clangParse
|
||||
clangLex
|
||||
clangBasic)
|
||||
|
||||
set( LLVM_LINK_COMPONENTS
|
||||
bitreader
|
||||
mc
|
||||
core
|
||||
)
|
||||
|
||||
add_clang_executable(clang-wpa
|
||||
clang-wpa.cpp
|
||||
)
|
||||
add_dependencies(clang-wpa clang-headers)
|
||||
@@ -1,23 +0,0 @@
|
||||
##===- examples/wpa/Makefile -------------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
CLANG_LEVEL := ../..
|
||||
|
||||
TOOLNAME = clang-wpa
|
||||
NO_INSTALL = 1
|
||||
|
||||
# No plugins, optimize startup time.
|
||||
TOOL_NO_EXPORTS = 1
|
||||
|
||||
LINK_COMPONENTS := asmparser bitreader mc core
|
||||
USEDLIBS = clangChecker.a clangIndex.a clangFrontend.a clangDriver.a \
|
||||
clangSema.a clangAnalysis.a clangSerialization.a \
|
||||
clangAST.a clangParse.a clangLex.a clangBasic.a
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
@@ -1,150 +0,0 @@
|
||||
//===--- clang-wpa.cpp - clang whole program analyzer ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tool reads a sequence of precompiled AST files, and do various
|
||||
// cross translation unit analyses.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Checker/PathSensitive/AnalysisManager.h"
|
||||
#include "clang/Checker/PathSensitive/GRExprEngine.h"
|
||||
#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
|
||||
#include "clang/Checker/Checkers/LocalCheckers.h"
|
||||
#include "clang/Frontend/ASTUnit.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Index/CallGraph.h"
|
||||
#include "clang/Index/Indexer.h"
|
||||
#include "clang/Index/TranslationUnit.h"
|
||||
#include "clang/Index/DeclReferenceMap.h"
|
||||
#include "clang/Index/SelectorMap.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
static llvm::cl::list<std::string>
|
||||
InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input AST files>"));
|
||||
|
||||
static llvm::cl::opt<bool>
|
||||
ViewCallGraph("view-call-graph", llvm::cl::desc("Display the call graph."));
|
||||
|
||||
static llvm::cl::opt<std::string>
|
||||
AnalyzeFunction("analyze-function",
|
||||
llvm::cl::desc("Specify the entry function."));
|
||||
|
||||
namespace {
|
||||
// A thin wrapper over ASTUnit implementing the TranslationUnit interface.
|
||||
class ASTUnitTU : public TranslationUnit {
|
||||
ASTUnit *AST;
|
||||
DeclReferenceMap DeclRefMap;
|
||||
SelectorMap SelMap;
|
||||
|
||||
public:
|
||||
ASTUnitTU(ASTUnit *ast)
|
||||
: AST(ast), DeclRefMap(AST->getASTContext()), SelMap(AST->getASTContext()) {
|
||||
}
|
||||
|
||||
virtual ASTContext &getASTContext() {
|
||||
return AST->getASTContext();
|
||||
}
|
||||
|
||||
virtual Preprocessor &getPreprocessor() {
|
||||
return AST->getPreprocessor();
|
||||
}
|
||||
|
||||
virtual Diagnostic &getDiagnostic() {
|
||||
return AST->getDiagnostics();
|
||||
}
|
||||
|
||||
virtual DeclReferenceMap &getDeclReferenceMap() {
|
||||
return DeclRefMap;
|
||||
}
|
||||
|
||||
virtual SelectorMap &getSelectorMap() {
|
||||
return SelMap;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
llvm::cl::ParseCommandLineOptions(argc, argv, "clang-wpa");
|
||||
std::vector<ASTUnit*> ASTUnits;
|
||||
|
||||
Program Prog;
|
||||
Indexer Idxer(Prog);
|
||||
|
||||
if (InputFilenames.empty())
|
||||
return 0;
|
||||
|
||||
DiagnosticOptions DiagOpts;
|
||||
llvm::IntrusiveRefCntPtr<Diagnostic> Diags
|
||||
= CompilerInstance::createDiagnostics(DiagOpts, argc, argv);
|
||||
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
|
||||
const std::string &InFile = InputFilenames[i];
|
||||
llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromASTFile(InFile, Diags));
|
||||
if (!AST)
|
||||
return 1;
|
||||
|
||||
ASTUnits.push_back(AST.take());
|
||||
}
|
||||
|
||||
if (ViewCallGraph) {
|
||||
llvm::OwningPtr<CallGraph> CG;
|
||||
CG.reset(new CallGraph(Prog));
|
||||
|
||||
for (unsigned i = 0, e = ASTUnits.size(); i != e; ++i)
|
||||
CG->addTU(ASTUnits[i]->getASTContext());
|
||||
|
||||
CG->ViewCallGraph();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (AnalyzeFunction.empty())
|
||||
return 0;
|
||||
|
||||
// Feed all ASTUnits to the Indexer.
|
||||
for (unsigned i = 0, e = ASTUnits.size(); i != e; ++i) {
|
||||
ASTUnitTU *TU = new ASTUnitTU(ASTUnits[i]);
|
||||
Idxer.IndexAST(TU);
|
||||
}
|
||||
|
||||
Entity Ent = Entity::get(AnalyzeFunction, Prog);
|
||||
FunctionDecl *FD;
|
||||
TranslationUnit *TU;
|
||||
llvm::tie(FD, TU) = Idxer.getDefinitionFor(Ent);
|
||||
|
||||
if (!FD)
|
||||
return 0;
|
||||
|
||||
// Create an analysis engine.
|
||||
Preprocessor &PP = TU->getPreprocessor();
|
||||
|
||||
// Hard code options for now.
|
||||
AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(),
|
||||
PP.getLangOptions(), /* PathDiagnostic */ 0,
|
||||
CreateRegionStoreManager,
|
||||
CreateRangeConstraintManager, &Idxer,
|
||||
/* MaxNodes */ 300000, /* MaxLoop */ 3,
|
||||
/* VisualizeEG */ false, /* VisualizeEGUbi */ false,
|
||||
/* PurgeDead */ true, /* EagerlyAssume */ false,
|
||||
/* TrimGraph */ false, /* InlineCall */ true,
|
||||
/* UseUnoptimizedCFG */ false);
|
||||
|
||||
GRTransferFuncs* TF = MakeCFRefCountTF(AMgr.getASTContext(), /*GC*/false,
|
||||
AMgr.getLangOptions());
|
||||
GRExprEngine Eng(AMgr, TF);
|
||||
|
||||
Eng.ExecuteWorkList(AMgr.getStackFrame(FD, TU), AMgr.getMaxNodes());
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
add_subdirectory(clang)
|
||||
@@ -1,4 +0,0 @@
|
||||
CLANG_LEVEL := ..
|
||||
DIRS := clang clang-c
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,31 +0,0 @@
|
||||
CLANG_LEVEL := ../..
|
||||
DIRS :=
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
||||
install-local::
|
||||
$(Echo) Installing Clang C API include files
|
||||
$(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir)
|
||||
$(Verb) if test -d "$(PROJ_SRC_ROOT)/tools/clang/include/clang-c" ; then \
|
||||
cd $(PROJ_SRC_ROOT)/tools/clang/include && \
|
||||
for hdr in `find clang-c -type f '!' '(' -name '*~' \
|
||||
-o -name '.#*' -o -name '*.in' -o -name '*.txt' \
|
||||
-o -name 'Makefile' -o -name '*.td' ')' -print \
|
||||
| grep -v CVS | grep -v .svn | grep -v .dir` ; do \
|
||||
instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \
|
||||
if test \! -d "$$instdir" ; then \
|
||||
$(EchoCmd) Making install directory $$instdir ; \
|
||||
$(MKDIR) $$instdir ;\
|
||||
fi ; \
|
||||
$(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
|
||||
done ; \
|
||||
fi
|
||||
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
|
||||
$(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/clang/include/clang-c" ; then \
|
||||
cd $(PROJ_OBJ_ROOT)/tools/clang/include && \
|
||||
for hdr in `find clang-c -type f '!' '(' -name 'Makefile' ')' -print \
|
||||
| grep -v CVS | grep -v .tmp | grep -v .dir` ; do \
|
||||
$(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
|
||||
done ; \
|
||||
fi
|
||||
endif
|
||||
@@ -1,243 +0,0 @@
|
||||
//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the APValue class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_APVALUE_H
|
||||
#define LLVM_CLANG_AST_APVALUE_H
|
||||
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
|
||||
namespace clang {
|
||||
class CharUnits;
|
||||
class Expr;
|
||||
|
||||
/// APValue - This class implements a discriminated union of [uninitialized]
|
||||
/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset].
|
||||
class APValue {
|
||||
typedef llvm::APSInt APSInt;
|
||||
typedef llvm::APFloat APFloat;
|
||||
public:
|
||||
enum ValueKind {
|
||||
Uninitialized,
|
||||
Int,
|
||||
Float,
|
||||
ComplexInt,
|
||||
ComplexFloat,
|
||||
LValue,
|
||||
Vector
|
||||
};
|
||||
private:
|
||||
ValueKind Kind;
|
||||
|
||||
struct ComplexAPSInt {
|
||||
APSInt Real, Imag;
|
||||
ComplexAPSInt() : Real(1), Imag(1) {}
|
||||
};
|
||||
struct ComplexAPFloat {
|
||||
APFloat Real, Imag;
|
||||
ComplexAPFloat() : Real(0.0), Imag(0.0) {}
|
||||
};
|
||||
|
||||
struct Vec {
|
||||
APValue *Elts;
|
||||
unsigned NumElts;
|
||||
Vec() : Elts(0), NumElts(0) {}
|
||||
~Vec() { delete[] Elts; }
|
||||
};
|
||||
|
||||
enum {
|
||||
MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
|
||||
sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
|
||||
};
|
||||
|
||||
union {
|
||||
void *Aligner;
|
||||
char Data[MaxSize];
|
||||
};
|
||||
|
||||
public:
|
||||
APValue() : Kind(Uninitialized) {}
|
||||
explicit APValue(const APSInt &I) : Kind(Uninitialized) {
|
||||
MakeInt(); setInt(I);
|
||||
}
|
||||
explicit APValue(const APFloat &F) : Kind(Uninitialized) {
|
||||
MakeFloat(); setFloat(F);
|
||||
}
|
||||
explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
|
||||
MakeVector(); setVector(E, N);
|
||||
}
|
||||
APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
|
||||
MakeComplexInt(); setComplexInt(R, I);
|
||||
}
|
||||
APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
|
||||
MakeComplexFloat(); setComplexFloat(R, I);
|
||||
}
|
||||
APValue(const APValue &RHS) : Kind(Uninitialized) {
|
||||
*this = RHS;
|
||||
}
|
||||
APValue(Expr* B, const CharUnits &O) : Kind(Uninitialized) {
|
||||
MakeLValue(); setLValue(B, O);
|
||||
}
|
||||
APValue(Expr* B);
|
||||
|
||||
~APValue() {
|
||||
MakeUninit();
|
||||
}
|
||||
|
||||
ValueKind getKind() const { return Kind; }
|
||||
bool isUninit() const { return Kind == Uninitialized; }
|
||||
bool isInt() const { return Kind == Int; }
|
||||
bool isFloat() const { return Kind == Float; }
|
||||
bool isComplexInt() const { return Kind == ComplexInt; }
|
||||
bool isComplexFloat() const { return Kind == ComplexFloat; }
|
||||
bool isLValue() const { return Kind == LValue; }
|
||||
bool isVector() const { return Kind == Vector; }
|
||||
|
||||
void print(llvm::raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
|
||||
APSInt &getInt() {
|
||||
assert(isInt() && "Invalid accessor");
|
||||
return *(APSInt*)(char*)Data;
|
||||
}
|
||||
const APSInt &getInt() const {
|
||||
return const_cast<APValue*>(this)->getInt();
|
||||
}
|
||||
|
||||
APFloat &getFloat() {
|
||||
assert(isFloat() && "Invalid accessor");
|
||||
return *(APFloat*)(char*)Data;
|
||||
}
|
||||
const APFloat &getFloat() const {
|
||||
return const_cast<APValue*>(this)->getFloat();
|
||||
}
|
||||
|
||||
APValue &getVectorElt(unsigned i) {
|
||||
assert(isVector() && "Invalid accessor");
|
||||
return ((Vec*)(char*)Data)->Elts[i];
|
||||
}
|
||||
const APValue &getVectorElt(unsigned i) const {
|
||||
assert(isVector() && "Invalid accessor");
|
||||
return ((const Vec*)(const char*)Data)->Elts[i];
|
||||
}
|
||||
unsigned getVectorLength() const {
|
||||
assert(isVector() && "Invalid accessor");
|
||||
return ((const Vec*)(const void *)Data)->NumElts;
|
||||
}
|
||||
|
||||
APSInt &getComplexIntReal() {
|
||||
assert(isComplexInt() && "Invalid accessor");
|
||||
return ((ComplexAPSInt*)(char*)Data)->Real;
|
||||
}
|
||||
const APSInt &getComplexIntReal() const {
|
||||
return const_cast<APValue*>(this)->getComplexIntReal();
|
||||
}
|
||||
|
||||
APSInt &getComplexIntImag() {
|
||||
assert(isComplexInt() && "Invalid accessor");
|
||||
return ((ComplexAPSInt*)(char*)Data)->Imag;
|
||||
}
|
||||
const APSInt &getComplexIntImag() const {
|
||||
return const_cast<APValue*>(this)->getComplexIntImag();
|
||||
}
|
||||
|
||||
APFloat &getComplexFloatReal() {
|
||||
assert(isComplexFloat() && "Invalid accessor");
|
||||
return ((ComplexAPFloat*)(char*)Data)->Real;
|
||||
}
|
||||
const APFloat &getComplexFloatReal() const {
|
||||
return const_cast<APValue*>(this)->getComplexFloatReal();
|
||||
}
|
||||
|
||||
APFloat &getComplexFloatImag() {
|
||||
assert(isComplexFloat() && "Invalid accessor");
|
||||
return ((ComplexAPFloat*)(char*)Data)->Imag;
|
||||
}
|
||||
const APFloat &getComplexFloatImag() const {
|
||||
return const_cast<APValue*>(this)->getComplexFloatImag();
|
||||
}
|
||||
|
||||
Expr* getLValueBase() const;
|
||||
CharUnits getLValueOffset() const;
|
||||
|
||||
void setInt(const APSInt &I) {
|
||||
assert(isInt() && "Invalid accessor");
|
||||
*(APSInt*)(char*)Data = I;
|
||||
}
|
||||
void setFloat(const APFloat &F) {
|
||||
assert(isFloat() && "Invalid accessor");
|
||||
*(APFloat*)(char*)Data = F;
|
||||
}
|
||||
void setVector(const APValue *E, unsigned N) {
|
||||
assert(isVector() && "Invalid accessor");
|
||||
((Vec*)(char*)Data)->Elts = new APValue[N];
|
||||
((Vec*)(char*)Data)->NumElts = N;
|
||||
for (unsigned i = 0; i != N; ++i)
|
||||
((Vec*)(char*)Data)->Elts[i] = E[i];
|
||||
}
|
||||
void setComplexInt(const APSInt &R, const APSInt &I) {
|
||||
assert(R.getBitWidth() == I.getBitWidth() &&
|
||||
"Invalid complex int (type mismatch).");
|
||||
assert(isComplexInt() && "Invalid accessor");
|
||||
((ComplexAPSInt*)(char*)Data)->Real = R;
|
||||
((ComplexAPSInt*)(char*)Data)->Imag = I;
|
||||
}
|
||||
void setComplexFloat(const APFloat &R, const APFloat &I) {
|
||||
assert(&R.getSemantics() == &I.getSemantics() &&
|
||||
"Invalid complex float (type mismatch).");
|
||||
assert(isComplexFloat() && "Invalid accessor");
|
||||
((ComplexAPFloat*)(char*)Data)->Real = R;
|
||||
((ComplexAPFloat*)(char*)Data)->Imag = I;
|
||||
}
|
||||
void setLValue(Expr *B, const CharUnits &O);
|
||||
|
||||
const APValue &operator=(const APValue &RHS);
|
||||
|
||||
private:
|
||||
void MakeUninit();
|
||||
void MakeInt() {
|
||||
assert(isUninit() && "Bad state change");
|
||||
new ((void*)Data) APSInt(1);
|
||||
Kind = Int;
|
||||
}
|
||||
void MakeFloat() {
|
||||
assert(isUninit() && "Bad state change");
|
||||
new ((void*)(char*)Data) APFloat(0.0);
|
||||
Kind = Float;
|
||||
}
|
||||
void MakeVector() {
|
||||
assert(isUninit() && "Bad state change");
|
||||
new ((void*)(char*)Data) Vec();
|
||||
Kind = Vector;
|
||||
}
|
||||
void MakeComplexInt() {
|
||||
assert(isUninit() && "Bad state change");
|
||||
new ((void*)(char*)Data) ComplexAPSInt();
|
||||
Kind = ComplexInt;
|
||||
}
|
||||
void MakeComplexFloat() {
|
||||
assert(isUninit() && "Bad state change");
|
||||
new ((void*)(char*)Data) ComplexAPFloat();
|
||||
Kind = ComplexFloat;
|
||||
}
|
||||
void MakeLValue();
|
||||
};
|
||||
|
||||
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
|
||||
V.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
} // end namespace clang.
|
||||
|
||||
#endif
|
||||
@@ -1,28 +0,0 @@
|
||||
//===--- AST.h - "Umbrella" header for AST library --------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the interface to the AST classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_AST_H
|
||||
#define LLVM_CLANG_AST_AST_H
|
||||
|
||||
// This header exports all AST interfaces.
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
|
||||
#endif
|
||||
@@ -1,104 +0,0 @@
|
||||
//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the ASTConsumer class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
|
||||
#define LLVM_CLANG_AST_ASTCONSUMER_H
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class CXXRecordDecl;
|
||||
class DeclGroupRef;
|
||||
class HandleTagDeclDefinition;
|
||||
class ASTDeserializationListener; // layering violation because void* is ugly
|
||||
class SemaConsumer; // layering violation required for safe SemaConsumer
|
||||
class TagDecl;
|
||||
class VarDecl;
|
||||
|
||||
/// ASTConsumer - This is an abstract interface that should be implemented by
|
||||
/// clients that read ASTs. This abstraction layer allows the client to be
|
||||
/// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
|
||||
class ASTConsumer {
|
||||
/// \brief Whether this AST consumer also requires information about
|
||||
/// semantic analysis.
|
||||
bool SemaConsumer;
|
||||
|
||||
friend class SemaConsumer;
|
||||
|
||||
public:
|
||||
ASTConsumer() : SemaConsumer(false) { }
|
||||
|
||||
virtual ~ASTConsumer() {}
|
||||
|
||||
/// Initialize - This is called to initialize the consumer, providing the
|
||||
/// ASTContext.
|
||||
virtual void Initialize(ASTContext &Context) {}
|
||||
|
||||
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
|
||||
/// called by the parser to process every top-level Decl*. Note that D can be
|
||||
/// the head of a chain of Decls (e.g. for `int a, b` the chain will have two
|
||||
/// elements). Use Decl::getNextDeclarator() to walk the chain.
|
||||
virtual void HandleTopLevelDecl(DeclGroupRef D);
|
||||
|
||||
/// HandleInterestingDecl - Handle the specified interesting declaration. This
|
||||
/// is called by the AST reader when deserializing things that might interest
|
||||
/// the consumer. The default implementation forwards to HandleTopLevelDecl.
|
||||
virtual void HandleInterestingDecl(DeclGroupRef D);
|
||||
|
||||
/// HandleTranslationUnit - This method is called when the ASTs for entire
|
||||
/// translation unit have been parsed.
|
||||
virtual void HandleTranslationUnit(ASTContext &Ctx) {}
|
||||
|
||||
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
|
||||
/// (e.g. struct, union, enum, class) is completed. This allows the client to
|
||||
/// hack on the type, which can occur at any point in the file (because these
|
||||
/// can be defined in declspecs).
|
||||
virtual void HandleTagDeclDefinition(TagDecl *D) {}
|
||||
|
||||
/// CompleteTentativeDefinition - Callback invoked at the end of a translation
|
||||
/// unit to notify the consumer that the given tentative definition should be
|
||||
/// completed.
|
||||
///
|
||||
/// The variable declaration itself will be a tentative
|
||||
/// definition. If it had an incomplete array type, its type will
|
||||
/// have already been changed to an array of size 1. However, the
|
||||
/// declaration remains a tentative definition and has not been
|
||||
/// modified by the introduction of an implicit zero initializer.
|
||||
virtual void CompleteTentativeDefinition(VarDecl *D) {}
|
||||
|
||||
/// \brief Callback involved at the end of a translation unit to
|
||||
/// notify the consumer that a vtable for the given C++ class is
|
||||
/// required.
|
||||
///
|
||||
/// \param RD The class whose vtable was used.
|
||||
///
|
||||
/// \param DefinitionRequired Whether a definition of this vtable is
|
||||
/// required in this translation unit; otherwise, it is only needed if
|
||||
/// it was actually used.
|
||||
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
|
||||
|
||||
/// \brief If the consumer is interested in entities being deserialized from
|
||||
/// AST files, it should return a pointer to a ASTDeserializationListener here
|
||||
///
|
||||
/// The return type is void* because ASTDS lives in Frontend.
|
||||
virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; }
|
||||
|
||||
/// PrintStats - If desired, print any statistics.
|
||||
virtual void PrintStats() {}
|
||||
|
||||
// Support isa/cast/dyn_cast
|
||||
static bool classof(const ASTConsumer *) { return true; }
|
||||
};
|
||||
|
||||
} // end namespace clang.
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
//===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_DIAGNOSTICAST_H
|
||||
#define LLVM_CLANG_DIAGNOSTICAST_H
|
||||
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
|
||||
namespace clang {
|
||||
namespace diag {
|
||||
enum {
|
||||
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
|
||||
#define ASTSTART
|
||||
#include "clang/Basic/DiagnosticASTKinds.inc"
|
||||
#undef DIAG
|
||||
NUM_BUILTIN_AST_DIAGNOSTICS
|
||||
};
|
||||
} // end namespace diag
|
||||
|
||||
/// \brief Diagnostic argument formatting function for diagnostics that
|
||||
/// involve AST nodes.
|
||||
///
|
||||
/// This function formats diagnostic arguments for various AST nodes,
|
||||
/// including types, declaration names, nested name specifiers, and
|
||||
/// declaration contexts, into strings that can be printed as part of
|
||||
/// diagnostics. It is meant to be used as the argument to
|
||||
/// \c Diagnostic::SetArgToStringFn(), where the cookie is an \c ASTContext
|
||||
/// pointer.
|
||||
void FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind,
|
||||
intptr_t Val,
|
||||
const char *Modifier,
|
||||
unsigned ModLen,
|
||||
const char *Argument,
|
||||
unsigned ArgLen,
|
||||
const Diagnostic::ArgumentValue *PrevArgs,
|
||||
unsigned NumPrevArgs,
|
||||
llvm::SmallVectorImpl<char> &Output,
|
||||
void *Cookie);
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
@@ -1,240 +0,0 @@
|
||||
//===--- ASTImporter.h - Importing ASTs from other Contexts -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the ASTImporter class which imports AST nodes from one
|
||||
// context into another context.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
|
||||
#define LLVM_CLANG_AST_ASTIMPORTER_H
|
||||
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class Decl;
|
||||
class DeclContext;
|
||||
class Diagnostic;
|
||||
class Expr;
|
||||
class FileManager;
|
||||
class IdentifierInfo;
|
||||
class NestedNameSpecifier;
|
||||
class Stmt;
|
||||
class TypeSourceInfo;
|
||||
|
||||
/// \brief Imports selected nodes from one AST context into another context,
|
||||
/// merging AST nodes where appropriate.
|
||||
class ASTImporter {
|
||||
public:
|
||||
typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet;
|
||||
|
||||
private:
|
||||
/// \brief The contexts we're importing to and from.
|
||||
ASTContext &ToContext, &FromContext;
|
||||
|
||||
/// \brief The file managers we're importing to and from.
|
||||
FileManager &ToFileManager, &FromFileManager;
|
||||
|
||||
/// \brief The diagnostics object that we should use to emit diagnostics.
|
||||
Diagnostic &Diags;
|
||||
|
||||
/// \brief Mapping from the already-imported types in the "from" context
|
||||
/// to the corresponding types in the "to" context.
|
||||
llvm::DenseMap<Type *, Type *> ImportedTypes;
|
||||
|
||||
/// \brief Mapping from the already-imported declarations in the "from"
|
||||
/// context to the corresponding declarations in the "to" context.
|
||||
llvm::DenseMap<Decl *, Decl *> ImportedDecls;
|
||||
|
||||
/// \brief Mapping from the already-imported statements in the "from"
|
||||
/// context to the corresponding statements in the "to" context.
|
||||
llvm::DenseMap<Stmt *, Stmt *> ImportedStmts;
|
||||
|
||||
/// \brief Mapping from the already-imported FileIDs in the "from" source
|
||||
/// manager to the corresponding FileIDs in the "to" source manager.
|
||||
llvm::DenseMap<unsigned, FileID> ImportedFileIDs;
|
||||
|
||||
/// \brief Imported, anonymous tag declarations that are missing their
|
||||
/// corresponding typedefs.
|
||||
llvm::SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
|
||||
|
||||
/// \brief Declaration (from, to) pairs that are known not to be equivalent
|
||||
/// (which we have already complained about).
|
||||
NonEquivalentDeclSet NonEquivalentDecls;
|
||||
|
||||
public:
|
||||
ASTImporter(Diagnostic &Diags,
|
||||
ASTContext &ToContext, FileManager &ToFileManager,
|
||||
ASTContext &FromContext, FileManager &FromFileManager);
|
||||
|
||||
virtual ~ASTImporter();
|
||||
|
||||
/// \brief Import the given type from the "from" context into the "to"
|
||||
/// context.
|
||||
///
|
||||
/// \returns the equivalent type in the "to" context, or a NULL type if
|
||||
/// an error occurred.
|
||||
QualType Import(QualType FromT);
|
||||
|
||||
/// \brief Import the given type source information from the
|
||||
/// "from" context into the "to" context.
|
||||
///
|
||||
/// \returns the equivalent type source information in the "to"
|
||||
/// context, or NULL if an error occurred.
|
||||
TypeSourceInfo *Import(TypeSourceInfo *FromTSI);
|
||||
|
||||
/// \brief Import the given declaration from the "from" context into the
|
||||
/// "to" context.
|
||||
///
|
||||
/// \returns the equivalent declaration in the "to" context, or a NULL type
|
||||
/// if an error occurred.
|
||||
Decl *Import(Decl *FromD);
|
||||
|
||||
/// \brief Import the given declaration context from the "from"
|
||||
/// AST context into the "to" AST context.
|
||||
///
|
||||
/// \returns the equivalent declaration context in the "to"
|
||||
/// context, or a NULL type if an error occurred.
|
||||
DeclContext *ImportContext(DeclContext *FromDC);
|
||||
|
||||
/// \brief Import the given expression from the "from" context into the
|
||||
/// "to" context.
|
||||
///
|
||||
/// \returns the equivalent expression in the "to" context, or NULL if
|
||||
/// an error occurred.
|
||||
Expr *Import(Expr *FromE);
|
||||
|
||||
/// \brief Import the given statement from the "from" context into the
|
||||
/// "to" context.
|
||||
///
|
||||
/// \returns the equivalent statement in the "to" context, or NULL if
|
||||
/// an error occurred.
|
||||
Stmt *Import(Stmt *FromS);
|
||||
|
||||
/// \brief Import the given nested-name-specifier from the "from"
|
||||
/// context into the "to" context.
|
||||
///
|
||||
/// \returns the equivalent nested-name-specifier in the "to"
|
||||
/// context, or NULL if an error occurred.
|
||||
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
|
||||
|
||||
/// \brief Import the given source location from the "from" context into
|
||||
/// the "to" context.
|
||||
///
|
||||
/// \returns the equivalent source location in the "to" context, or an
|
||||
/// invalid source location if an error occurred.
|
||||
SourceLocation Import(SourceLocation FromLoc);
|
||||
|
||||
/// \brief Import the given source range from the "from" context into
|
||||
/// the "to" context.
|
||||
///
|
||||
/// \returns the equivalent source range in the "to" context, or an
|
||||
/// invalid source location if an error occurred.
|
||||
SourceRange Import(SourceRange FromRange);
|
||||
|
||||
/// \brief Import the given declaration name from the "from"
|
||||
/// context into the "to" context.
|
||||
///
|
||||
/// \returns the equivalent declaration name in the "to" context,
|
||||
/// or an empty declaration name if an error occurred.
|
||||
DeclarationName Import(DeclarationName FromName);
|
||||
|
||||
/// \brief Import the given identifier from the "from" context
|
||||
/// into the "to" context.
|
||||
///
|
||||
/// \returns the equivalent identifier in the "to" context.
|
||||
IdentifierInfo *Import(IdentifierInfo *FromId);
|
||||
|
||||
/// \brief Import the given Objective-C selector from the "from"
|
||||
/// context into the "to" context.
|
||||
///
|
||||
/// \returns the equivalent selector in the "to" context.
|
||||
Selector Import(Selector FromSel);
|
||||
|
||||
/// \brief Import the given file ID from the "from" context into the
|
||||
/// "to" context.
|
||||
///
|
||||
/// \returns the equivalent file ID in the source manager of the "to"
|
||||
/// context.
|
||||
FileID Import(FileID);
|
||||
|
||||
/// \brief Cope with a name conflict when importing a declaration into the
|
||||
/// given context.
|
||||
///
|
||||
/// This routine is invoked whenever there is a name conflict while
|
||||
/// importing a declaration. The returned name will become the name of the
|
||||
/// imported declaration. By default, the returned name is the same as the
|
||||
/// original name, leaving the conflict unresolve such that name lookup
|
||||
/// for this name is likely to find an ambiguity later.
|
||||
///
|
||||
/// Subclasses may override this routine to resolve the conflict, e.g., by
|
||||
/// renaming the declaration being imported.
|
||||
///
|
||||
/// \param Name the name of the declaration being imported, which conflicts
|
||||
/// with other declarations.
|
||||
///
|
||||
/// \param DC the declaration context (in the "to" AST context) in which
|
||||
/// the name is being imported.
|
||||
///
|
||||
/// \param IDNS the identifier namespace in which the name will be found.
|
||||
///
|
||||
/// \param Decls the set of declarations with the same name as the
|
||||
/// declaration being imported.
|
||||
///
|
||||
/// \param NumDecls the number of conflicting declarations in \p Decls.
|
||||
///
|
||||
/// \returns the name that the newly-imported declaration should have.
|
||||
virtual DeclarationName HandleNameConflict(DeclarationName Name,
|
||||
DeclContext *DC,
|
||||
unsigned IDNS,
|
||||
NamedDecl **Decls,
|
||||
unsigned NumDecls);
|
||||
|
||||
/// \brief Retrieve the context that AST nodes are being imported into.
|
||||
ASTContext &getToContext() const { return ToContext; }
|
||||
|
||||
/// \brief Retrieve the context that AST nodes are being imported from.
|
||||
ASTContext &getFromContext() const { return FromContext; }
|
||||
|
||||
/// \brief Retrieve the file manager that AST nodes are being imported into.
|
||||
FileManager &getToFileManager() const { return ToFileManager; }
|
||||
|
||||
/// \brief Retrieve the file manager that AST nodes are being imported from.
|
||||
FileManager &getFromFileManager() const { return FromFileManager; }
|
||||
|
||||
/// \brief Retrieve the diagnostic formatter.
|
||||
Diagnostic &getDiags() const { return Diags; }
|
||||
|
||||
/// \brief Report a diagnostic in the "to" context.
|
||||
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
|
||||
|
||||
/// \brief Report a diagnostic in the "from" context.
|
||||
DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID);
|
||||
|
||||
/// \brief Return the set of declarations that we know are not equivalent.
|
||||
NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; }
|
||||
|
||||
/// \brief Note that we have imported the "from" declaration by mapping it
|
||||
/// to the (potentially-newly-created) "to" declaration.
|
||||
///
|
||||
/// \returns \p To
|
||||
Decl *Imported(Decl *From, Decl *To);
|
||||
|
||||
/// \brief Determine whether the given types are structurally
|
||||
/// equivalent.
|
||||
bool IsStructurallyEquivalent(QualType From, QualType To);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LLVM_CLANG_AST_ASTIMPORTER_H
|
||||
@@ -1,397 +0,0 @@
|
||||
//===- ASTVector.h - Vector that uses ASTContext for allocation --*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides ASTVector, a vector ADT whose contents are
|
||||
// allocated using the allocator associated with an ASTContext..
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h.
|
||||
// We can refactor this core logic into something common.
|
||||
|
||||
#ifndef LLVM_CLANG_AST_VECTOR
|
||||
#define LLVM_CLANG_AST_VECTOR
|
||||
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
namespace std {
|
||||
#if _MSC_VER <= 1310
|
||||
// Work around flawed VC++ implementation of std::uninitialized_copy. Define
|
||||
// additional overloads so that elements with pointer types are recognized as
|
||||
// scalars and not objects, causing bizarre type conversion errors.
|
||||
template<class T1, class T2>
|
||||
inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
|
||||
_Scalar_ptr_iterator_tag _Cat;
|
||||
return _Cat;
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
|
||||
_Scalar_ptr_iterator_tag _Cat;
|
||||
return _Cat;
|
||||
}
|
||||
#else
|
||||
// FIXME: It is not clear if the problem is fixed in VS 2005. What is clear
|
||||
// is that the above hack won't work if it wasn't fixed.
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace clang {
|
||||
|
||||
template<typename T>
|
||||
class ASTVector {
|
||||
T *Begin, *End, *Capacity;
|
||||
|
||||
void setEnd(T *P) { this->End = P; }
|
||||
|
||||
public:
|
||||
// Default ctor - Initialize to empty.
|
||||
explicit ASTVector(ASTContext &C, unsigned N = 0)
|
||||
: Begin(NULL), End(NULL), Capacity(NULL) {
|
||||
reserve(C, N);
|
||||
}
|
||||
|
||||
~ASTVector() {
|
||||
if (llvm::is_class<T>::value) {
|
||||
// Destroy the constructed elements in the vector.
|
||||
destroy_range(Begin, End);
|
||||
}
|
||||
}
|
||||
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T value_type;
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
// forward iterator creation methods.
|
||||
iterator begin() { return Begin; }
|
||||
const_iterator begin() const { return Begin; }
|
||||
iterator end() { return End; }
|
||||
const_iterator end() const { return End; }
|
||||
|
||||
// reverse iterator creation methods.
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
|
||||
|
||||
bool empty() const { return Begin == End; }
|
||||
size_type size() const { return End-Begin; }
|
||||
|
||||
reference operator[](unsigned idx) {
|
||||
assert(Begin + idx < End);
|
||||
return Begin[idx];
|
||||
}
|
||||
const_reference operator[](unsigned idx) const {
|
||||
assert(Begin + idx < End);
|
||||
return Begin[idx];
|
||||
}
|
||||
|
||||
reference front() {
|
||||
return begin()[0];
|
||||
}
|
||||
const_reference front() const {
|
||||
return begin()[0];
|
||||
}
|
||||
|
||||
reference back() {
|
||||
return end()[-1];
|
||||
}
|
||||
const_reference back() const {
|
||||
return end()[-1];
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
--End;
|
||||
End->~T();
|
||||
}
|
||||
|
||||
T pop_back_val() {
|
||||
T Result = back();
|
||||
pop_back();
|
||||
return Result;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (llvm::is_class<T>::value) {
|
||||
destroy_range(Begin, End);
|
||||
}
|
||||
End = Begin;
|
||||
}
|
||||
|
||||
/// data - Return a pointer to the vector's buffer, even if empty().
|
||||
pointer data() {
|
||||
return pointer(Begin);
|
||||
}
|
||||
|
||||
/// data - Return a pointer to the vector's buffer, even if empty().
|
||||
const_pointer data() const {
|
||||
return const_pointer(Begin);
|
||||
}
|
||||
|
||||
void push_back(const_reference Elt, ASTContext &C) {
|
||||
if (End < Capacity) {
|
||||
Retry:
|
||||
new (End) T(Elt);
|
||||
++End;
|
||||
return;
|
||||
}
|
||||
grow(C);
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
void reserve(ASTContext &C, unsigned N) {
|
||||
if (unsigned(Capacity-Begin) < N)
|
||||
grow(C, N);
|
||||
}
|
||||
|
||||
/// capacity - Return the total number of elements in the currently allocated
|
||||
/// buffer.
|
||||
size_t capacity() const { return Capacity - Begin; }
|
||||
|
||||
/// append - Add the specified range to the end of the SmallVector.
|
||||
///
|
||||
template<typename in_iter>
|
||||
void append(ASTContext &C, in_iter in_start, in_iter in_end) {
|
||||
size_type NumInputs = std::distance(in_start, in_end);
|
||||
|
||||
if (NumInputs == 0)
|
||||
return;
|
||||
|
||||
// Grow allocated space if needed.
|
||||
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
|
||||
this->grow(C, this->size()+NumInputs);
|
||||
|
||||
// Copy the new elements over.
|
||||
// TODO: NEED To compile time dispatch on whether in_iter is a random access
|
||||
// iterator to use the fast uninitialized_copy.
|
||||
std::uninitialized_copy(in_start, in_end, this->end());
|
||||
this->setEnd(this->end() + NumInputs);
|
||||
}
|
||||
|
||||
/// append - Add the specified range to the end of the SmallVector.
|
||||
///
|
||||
void append(ASTContext &C, size_type NumInputs, const T &Elt) {
|
||||
// Grow allocated space if needed.
|
||||
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
|
||||
this->grow(C, this->size()+NumInputs);
|
||||
|
||||
// Copy the new elements over.
|
||||
std::uninitialized_fill_n(this->end(), NumInputs, Elt);
|
||||
this->setEnd(this->end() + NumInputs);
|
||||
}
|
||||
|
||||
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
|
||||
/// starting with "Dest", constructing elements into it as needed.
|
||||
template<typename It1, typename It2>
|
||||
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
|
||||
std::uninitialized_copy(I, E, Dest);
|
||||
}
|
||||
|
||||
iterator insert(ASTContext &C, iterator I, const T &Elt) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
push_back(Elt);
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
new (this->end()) T(this->back());
|
||||
this->setEnd(this->end()+1);
|
||||
// Push everything else over.
|
||||
std::copy_backward(I, this->end()-1, this->end());
|
||||
*I = Elt;
|
||||
return I;
|
||||
}
|
||||
size_t EltNo = I-this->begin();
|
||||
this->grow(C);
|
||||
I = this->begin()+EltNo;
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
iterator insert(ASTContext &C, iterator I, size_type NumToInsert,
|
||||
const T &Elt) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
append(C, NumToInsert, Elt);
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
|
||||
size_t InsertElt = I - this->begin();
|
||||
|
||||
// Ensure there is enough space.
|
||||
reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
|
||||
|
||||
// Uninvalidate the iterator.
|
||||
I = this->begin()+InsertElt;
|
||||
|
||||
// If there are more elements between the insertion point and the end of the
|
||||
// range than there are being inserted, we can use a simple approach to
|
||||
// insertion. Since we already reserved space, we know that this won't
|
||||
// reallocate the vector.
|
||||
if (size_t(this->end()-I) >= NumToInsert) {
|
||||
T *OldEnd = this->end();
|
||||
append(C, this->end()-NumToInsert, this->end());
|
||||
|
||||
// Copy the existing elements that get replaced.
|
||||
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
|
||||
|
||||
std::fill_n(I, NumToInsert, Elt);
|
||||
return I;
|
||||
}
|
||||
|
||||
// Otherwise, we're inserting more elements than exist already, and we're
|
||||
// not inserting at the end.
|
||||
|
||||
// Copy over the elements that we're about to overwrite.
|
||||
T *OldEnd = this->end();
|
||||
this->setEnd(this->end() + NumToInsert);
|
||||
size_t NumOverwritten = OldEnd-I;
|
||||
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
|
||||
|
||||
// Replace the overwritten part.
|
||||
std::fill_n(I, NumOverwritten, Elt);
|
||||
|
||||
// Insert the non-overwritten middle part.
|
||||
std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
|
||||
return I;
|
||||
}
|
||||
|
||||
template<typename ItTy>
|
||||
iterator insert(ASTContext &C, iterator I, ItTy From, ItTy To) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
append(C, From, To);
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
size_t NumToInsert = std::distance(From, To);
|
||||
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
|
||||
size_t InsertElt = I - this->begin();
|
||||
|
||||
// Ensure there is enough space.
|
||||
reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
|
||||
|
||||
// Uninvalidate the iterator.
|
||||
I = this->begin()+InsertElt;
|
||||
|
||||
// If there are more elements between the insertion point and the end of the
|
||||
// range than there are being inserted, we can use a simple approach to
|
||||
// insertion. Since we already reserved space, we know that this won't
|
||||
// reallocate the vector.
|
||||
if (size_t(this->end()-I) >= NumToInsert) {
|
||||
T *OldEnd = this->end();
|
||||
append(C, this->end()-NumToInsert, this->end());
|
||||
|
||||
// Copy the existing elements that get replaced.
|
||||
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
|
||||
|
||||
std::copy(From, To, I);
|
||||
return I;
|
||||
}
|
||||
|
||||
// Otherwise, we're inserting more elements than exist already, and we're
|
||||
// not inserting at the end.
|
||||
|
||||
// Copy over the elements that we're about to overwrite.
|
||||
T *OldEnd = this->end();
|
||||
this->setEnd(this->end() + NumToInsert);
|
||||
size_t NumOverwritten = OldEnd-I;
|
||||
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
|
||||
|
||||
// Replace the overwritten part.
|
||||
for (; NumOverwritten > 0; --NumOverwritten) {
|
||||
*I = *From;
|
||||
++I; ++From;
|
||||
}
|
||||
|
||||
// Insert the non-overwritten middle part.
|
||||
this->uninitialized_copy(From, To, OldEnd);
|
||||
return I;
|
||||
}
|
||||
|
||||
void resize(ASTContext &C, unsigned N, const T &NV) {
|
||||
if (N < this->size()) {
|
||||
this->destroy_range(this->begin()+N, this->end());
|
||||
this->setEnd(this->begin()+N);
|
||||
} else if (N > this->size()) {
|
||||
if (this->capacity() < N)
|
||||
this->grow(C, N);
|
||||
construct_range(this->end(), this->begin()+N, NV);
|
||||
this->setEnd(this->begin()+N);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// grow - double the size of the allocated memory, guaranteeing space for at
|
||||
/// least one more element or MinSize if specified.
|
||||
void grow(ASTContext &C, size_type MinSize = 1);
|
||||
|
||||
void construct_range(T *S, T *E, const T &Elt) {
|
||||
for (; S != E; ++S)
|
||||
new (S) T(Elt);
|
||||
}
|
||||
|
||||
void destroy_range(T *S, T *E) {
|
||||
while (S != E) {
|
||||
--E;
|
||||
E->~T();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
iterator capacity_ptr() { return (iterator)this->Capacity; }
|
||||
};
|
||||
|
||||
// Define this out-of-line to dissuade the C++ compiler from inlining it.
|
||||
template <typename T>
|
||||
void ASTVector<T>::grow(ASTContext &C, size_t MinSize) {
|
||||
size_t CurCapacity = Capacity-Begin;
|
||||
size_t CurSize = size();
|
||||
size_t NewCapacity = 2*CurCapacity;
|
||||
if (NewCapacity < MinSize)
|
||||
NewCapacity = MinSize;
|
||||
|
||||
// Allocate the memory from the ASTContext.
|
||||
T *NewElts = new (C) T[NewCapacity];
|
||||
|
||||
// Copy the elements over.
|
||||
if (llvm::is_class<T>::value) {
|
||||
std::uninitialized_copy(Begin, End, NewElts);
|
||||
// Destroy the original elements.
|
||||
destroy_range(Begin, End);
|
||||
}
|
||||
else {
|
||||
// Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
|
||||
memcpy(NewElts, Begin, CurSize * sizeof(T));
|
||||
}
|
||||
|
||||
C.Deallocate(Begin);
|
||||
Begin = NewElts;
|
||||
End = NewElts+CurSize;
|
||||
Capacity = Begin+NewCapacity;
|
||||
}
|
||||
|
||||
} // end: clang namespace
|
||||
#endif
|
||||
@@ -1,222 +0,0 @@
|
||||
//===--- Attr.h - Classes for representing expressions ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the Attr interface and subclasses.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_ATTR_H
|
||||
#define LLVM_CLANG_AST_ATTR_H
|
||||
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "clang/Basic/AttrKinds.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
using llvm::dyn_cast;
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class IdentifierInfo;
|
||||
class ObjCInterfaceDecl;
|
||||
class Expr;
|
||||
class QualType;
|
||||
class FunctionDecl;
|
||||
class TypeSourceInfo;
|
||||
}
|
||||
|
||||
// Defined in ASTContext.h
|
||||
void *operator new(size_t Bytes, clang::ASTContext &C,
|
||||
size_t Alignment = 16) throw ();
|
||||
// FIXME: Being forced to not have a default argument here due to redeclaration
|
||||
// rules on default arguments sucks
|
||||
void *operator new[](size_t Bytes, clang::ASTContext &C,
|
||||
size_t Alignment) throw ();
|
||||
|
||||
// It is good practice to pair new/delete operators. Also, MSVC gives many
|
||||
// warnings if a matching delete overload is not declared, even though the
|
||||
// throw() spec guarantees it will not be implicitly called.
|
||||
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
|
||||
throw ();
|
||||
void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
|
||||
throw ();
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// Attr - This represents one attribute.
|
||||
class Attr {
|
||||
private:
|
||||
SourceLocation Loc;
|
||||
unsigned AttrKind : 16;
|
||||
bool Inherited : 1;
|
||||
|
||||
protected:
|
||||
virtual ~Attr();
|
||||
|
||||
void* operator new(size_t bytes) throw() {
|
||||
assert(0 && "Attrs cannot be allocated with regular 'new'.");
|
||||
return 0;
|
||||
}
|
||||
void operator delete(void* data) throw() {
|
||||
assert(0 && "Attrs cannot be released with regular 'delete'.");
|
||||
}
|
||||
|
||||
public:
|
||||
// Forward so that the regular new and delete do not hide global ones.
|
||||
void* operator new(size_t Bytes, ASTContext &C,
|
||||
size_t Alignment = 16) throw() {
|
||||
return ::operator new(Bytes, C, Alignment);
|
||||
}
|
||||
void operator delete(void *Ptr, ASTContext &C,
|
||||
size_t Alignment) throw() {
|
||||
return ::operator delete(Ptr, C, Alignment);
|
||||
}
|
||||
|
||||
protected:
|
||||
Attr(attr::Kind AK, SourceLocation L)
|
||||
: Loc(L), AttrKind(AK), Inherited(false) {}
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Whether this attribute should be merged to new
|
||||
/// declarations.
|
||||
virtual bool isMerged() const { return true; }
|
||||
|
||||
attr::Kind getKind() const {
|
||||
return static_cast<attr::Kind>(AttrKind);
|
||||
}
|
||||
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
|
||||
bool isInherited() const { return Inherited; }
|
||||
void setInherited(bool I) { Inherited = I; }
|
||||
|
||||
// Clone this attribute.
|
||||
virtual Attr* clone(ASTContext &C) const = 0;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Attr *) { return true; }
|
||||
};
|
||||
|
||||
#include "clang/AST/Attrs.inc"
|
||||
|
||||
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
|
||||
typedef llvm::SmallVector<Attr*, 2> AttrVec;
|
||||
typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
|
||||
|
||||
/// DestroyAttrs - Destroy the contents of an AttrVec.
|
||||
inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
|
||||
}
|
||||
|
||||
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
|
||||
/// providing attributes that are of a specifc type.
|
||||
template <typename SpecificAttr>
|
||||
class specific_attr_iterator {
|
||||
/// Current - The current, underlying iterator.
|
||||
/// In order to ensure we don't dereference an invalid iterator unless
|
||||
/// specifically requested, we don't necessarily advance this all the
|
||||
/// way. Instead, we advance it when an operation is requested; if the
|
||||
/// operation is acting on what should be a past-the-end iterator,
|
||||
/// then we offer no guarantees, but this way we do not dererence a
|
||||
/// past-the-end iterator when we move to a past-the-end position.
|
||||
mutable AttrVec::const_iterator Current;
|
||||
|
||||
void AdvanceToNext() const {
|
||||
while (!llvm::isa<SpecificAttr>(*Current))
|
||||
++Current;
|
||||
}
|
||||
|
||||
void AdvanceToNext(AttrVec::const_iterator I) const {
|
||||
while (Current != I && !llvm::isa<SpecificAttr>(*Current))
|
||||
++Current;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef SpecificAttr* value_type;
|
||||
typedef SpecificAttr* reference;
|
||||
typedef SpecificAttr* pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
specific_attr_iterator() : Current() { }
|
||||
explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
|
||||
|
||||
reference operator*() const {
|
||||
AdvanceToNext();
|
||||
return llvm::cast<SpecificAttr>(*Current);
|
||||
}
|
||||
pointer operator->() const {
|
||||
AdvanceToNext();
|
||||
return llvm::cast<SpecificAttr>(*Current);
|
||||
}
|
||||
|
||||
specific_attr_iterator& operator++() {
|
||||
++Current;
|
||||
return *this;
|
||||
}
|
||||
specific_attr_iterator operator++(int) {
|
||||
specific_attr_iterator Tmp(*this);
|
||||
++(*this);
|
||||
return Tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(specific_attr_iterator Left,
|
||||
specific_attr_iterator Right) {
|
||||
if (Left.Current < Right.Current)
|
||||
Left.AdvanceToNext(Right.Current);
|
||||
else
|
||||
Right.AdvanceToNext(Left.Current);
|
||||
return Left.Current == Right.Current;
|
||||
}
|
||||
friend bool operator!=(specific_attr_iterator Left,
|
||||
specific_attr_iterator Right) {
|
||||
return !(Left == Right);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
|
||||
return specific_attr_iterator<T>(vec.begin());
|
||||
}
|
||||
template <typename T>
|
||||
inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
|
||||
return specific_attr_iterator<T>(vec.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool hasSpecificAttr(const AttrVec& vec) {
|
||||
return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
|
||||
}
|
||||
template <typename T>
|
||||
inline T *getSpecificAttr(const AttrVec& vec) {
|
||||
specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
|
||||
if (i != specific_attr_end<T>(vec))
|
||||
return *i;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getMaxAlignment - Returns the highest alignment value found among
|
||||
/// AlignedAttrs in an AttrVec, or 0 if there are none.
|
||||
inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
|
||||
unsigned Align = 0;
|
||||
specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
|
||||
for(; i != e; ++i)
|
||||
Align = std::max(Align, i->getAlignment(Ctx));
|
||||
return Align;
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
@@ -1,24 +0,0 @@
|
||||
set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td)
|
||||
tablegen(Attrs.inc
|
||||
-gen-clang-attr-classes
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
add_custom_target(ClangAttrClasses
|
||||
DEPENDS Attrs.inc)
|
||||
|
||||
tablegen(AttrImpl.inc
|
||||
-gen-clang-attr-impl
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
add_custom_target(ClangAttrImpl
|
||||
DEPENDS AttrImpl.inc)
|
||||
|
||||
set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td)
|
||||
tablegen(StmtNodes.inc
|
||||
-gen-clang-stmt-nodes)
|
||||
add_custom_target(ClangStmtNodes
|
||||
DEPENDS StmtNodes.inc)
|
||||
|
||||
set(LLVM_TARGET_DEFINITIONS ../Basic/DeclNodes.td)
|
||||
tablegen(DeclNodes.inc
|
||||
-gen-clang-decl-nodes)
|
||||
add_custom_target(ClangDeclNodes
|
||||
DEPENDS DeclNodes.inc)
|
||||
@@ -1,365 +0,0 @@
|
||||
//===------ CXXInheritance.h - C++ Inheritance ------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides routines that help analyzing C++ inheritance hierarchies.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_CXXINHERITANCE_H
|
||||
#define LLVM_CLANG_AST_CXXINHERITANCE_H
|
||||
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TypeOrdering.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class CXXBaseSpecifier;
|
||||
class CXXMethodDecl;
|
||||
class CXXRecordDecl;
|
||||
class NamedDecl;
|
||||
|
||||
/// \brief Represents an element in a path from a derived class to a
|
||||
/// base class.
|
||||
///
|
||||
/// Each step in the path references the link from a
|
||||
/// derived class to one of its direct base classes, along with a
|
||||
/// base "number" that identifies which base subobject of the
|
||||
/// original derived class we are referencing.
|
||||
struct CXXBasePathElement {
|
||||
/// \brief The base specifier that states the link from a derived
|
||||
/// class to a base class, which will be followed by this base
|
||||
/// path element.
|
||||
const CXXBaseSpecifier *Base;
|
||||
|
||||
/// \brief The record decl of the class that the base is a base of.
|
||||
const CXXRecordDecl *Class;
|
||||
|
||||
/// \brief Identifies which base class subobject (of type
|
||||
/// \c Base->getType()) this base path element refers to.
|
||||
///
|
||||
/// This value is only valid if \c !Base->isVirtual(), because there
|
||||
/// is no base numbering for the zero or one virtual bases of a
|
||||
/// given type.
|
||||
int SubobjectNumber;
|
||||
};
|
||||
|
||||
/// \brief Represents a path from a specific derived class
|
||||
/// (which is not represented as part of the path) to a particular
|
||||
/// (direct or indirect) base class subobject.
|
||||
///
|
||||
/// Individual elements in the path are described by the \c CXXBasePathElement
|
||||
/// structure, which captures both the link from a derived class to one of its
|
||||
/// direct bases and identification describing which base class
|
||||
/// subobject is being used.
|
||||
class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
|
||||
public:
|
||||
CXXBasePath() : Access(AS_public) {}
|
||||
|
||||
/// \brief The access along this inheritance path. This is only
|
||||
/// calculated when recording paths. AS_none is a special value
|
||||
/// used to indicate a path which permits no legal access.
|
||||
AccessSpecifier Access;
|
||||
|
||||
/// \brief The set of declarations found inside this base class
|
||||
/// subobject.
|
||||
DeclContext::lookup_result Decls;
|
||||
|
||||
void clear() {
|
||||
llvm::SmallVectorImpl<CXXBasePathElement>::clear();
|
||||
Access = AS_public;
|
||||
}
|
||||
};
|
||||
|
||||
/// BasePaths - Represents the set of paths from a derived class to
|
||||
/// one of its (direct or indirect) bases. For example, given the
|
||||
/// following class hierachy:
|
||||
///
|
||||
/// @code
|
||||
/// class A { };
|
||||
/// class B : public A { };
|
||||
/// class C : public A { };
|
||||
/// class D : public B, public C{ };
|
||||
/// @endcode
|
||||
///
|
||||
/// There are two potential BasePaths to represent paths from D to a
|
||||
/// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0)
|
||||
/// and another is (D,0)->(C,0)->(A,1). These two paths actually
|
||||
/// refer to two different base class subobjects of the same type,
|
||||
/// so the BasePaths object refers to an ambiguous path. On the
|
||||
/// other hand, consider the following class hierarchy:
|
||||
///
|
||||
/// @code
|
||||
/// class A { };
|
||||
/// class B : public virtual A { };
|
||||
/// class C : public virtual A { };
|
||||
/// class D : public B, public C{ };
|
||||
/// @endcode
|
||||
///
|
||||
/// Here, there are two potential BasePaths again, (D, 0) -> (B, 0)
|
||||
/// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them
|
||||
/// refer to the same base class subobject of type A (the virtual
|
||||
/// one), there is no ambiguity.
|
||||
class CXXBasePaths {
|
||||
/// \brief The type from which this search originated.
|
||||
CXXRecordDecl *Origin;
|
||||
|
||||
/// Paths - The actual set of paths that can be taken from the
|
||||
/// derived class to the same base class.
|
||||
std::list<CXXBasePath> Paths;
|
||||
|
||||
/// ClassSubobjects - Records the class subobjects for each class
|
||||
/// type that we've seen. The first element in the pair says
|
||||
/// whether we found a path to a virtual base for that class type,
|
||||
/// while the element contains the number of non-virtual base
|
||||
/// class subobjects for that class type. The key of the map is
|
||||
/// the cv-unqualified canonical type of the base class subobject.
|
||||
std::map<QualType, std::pair<bool, unsigned>, QualTypeOrdering>
|
||||
ClassSubobjects;
|
||||
|
||||
/// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
|
||||
/// ambiguous paths while it is looking for a path from a derived
|
||||
/// type to a base type.
|
||||
bool FindAmbiguities;
|
||||
|
||||
/// RecordPaths - Whether Sema::IsDerivedFrom should record paths
|
||||
/// while it is determining whether there are paths from a derived
|
||||
/// type to a base type.
|
||||
bool RecordPaths;
|
||||
|
||||
/// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search
|
||||
/// if it finds a path that goes across a virtual base. The virtual class
|
||||
/// is also recorded.
|
||||
bool DetectVirtual;
|
||||
|
||||
/// ScratchPath - A BasePath that is used by Sema::lookupInBases
|
||||
/// to help build the set of paths.
|
||||
CXXBasePath ScratchPath;
|
||||
|
||||
/// DetectedVirtual - The base class that is virtual.
|
||||
const RecordType *DetectedVirtual;
|
||||
|
||||
/// \brief Array of the declarations that have been found. This
|
||||
/// array is constructed only if needed, e.g., to iterate over the
|
||||
/// results within LookupResult.
|
||||
NamedDecl **DeclsFound;
|
||||
unsigned NumDeclsFound;
|
||||
|
||||
friend class CXXRecordDecl;
|
||||
|
||||
void ComputeDeclsFound();
|
||||
|
||||
bool lookupInBases(ASTContext &Context,
|
||||
const CXXRecordDecl *Record,
|
||||
CXXRecordDecl::BaseMatchesCallback *BaseMatches,
|
||||
void *UserData);
|
||||
public:
|
||||
typedef std::list<CXXBasePath>::iterator paths_iterator;
|
||||
typedef std::list<CXXBasePath>::const_iterator const_paths_iterator;
|
||||
typedef NamedDecl **decl_iterator;
|
||||
|
||||
/// BasePaths - Construct a new BasePaths structure to record the
|
||||
/// paths for a derived-to-base search.
|
||||
explicit CXXBasePaths(bool FindAmbiguities = true,
|
||||
bool RecordPaths = true,
|
||||
bool DetectVirtual = true)
|
||||
: FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
|
||||
DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0),
|
||||
NumDeclsFound(0) { }
|
||||
|
||||
~CXXBasePaths() { delete [] DeclsFound; }
|
||||
|
||||
paths_iterator begin() { return Paths.begin(); }
|
||||
paths_iterator end() { return Paths.end(); }
|
||||
const_paths_iterator begin() const { return Paths.begin(); }
|
||||
const_paths_iterator end() const { return Paths.end(); }
|
||||
|
||||
CXXBasePath& front() { return Paths.front(); }
|
||||
const CXXBasePath& front() const { return Paths.front(); }
|
||||
|
||||
decl_iterator found_decls_begin();
|
||||
decl_iterator found_decls_end();
|
||||
|
||||
/// \brief Determine whether the path from the most-derived type to the
|
||||
/// given base type is ambiguous (i.e., it refers to multiple subobjects of
|
||||
/// the same base type).
|
||||
bool isAmbiguous(CanQualType BaseType);
|
||||
|
||||
/// \brief Whether we are finding multiple paths to detect ambiguities.
|
||||
bool isFindingAmbiguities() const { return FindAmbiguities; }
|
||||
|
||||
/// \brief Whether we are recording paths.
|
||||
bool isRecordingPaths() const { return RecordPaths; }
|
||||
|
||||
/// \brief Specify whether we should be recording paths or not.
|
||||
void setRecordingPaths(bool RP) { RecordPaths = RP; }
|
||||
|
||||
/// \brief Whether we are detecting virtual bases.
|
||||
bool isDetectingVirtual() const { return DetectVirtual; }
|
||||
|
||||
/// \brief The virtual base discovered on the path (if we are merely
|
||||
/// detecting virtuals).
|
||||
const RecordType* getDetectedVirtual() const {
|
||||
return DetectedVirtual;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the type from which this base-paths search
|
||||
/// began
|
||||
CXXRecordDecl *getOrigin() const { return Origin; }
|
||||
void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; }
|
||||
|
||||
/// \brief Clear the base-paths results.
|
||||
void clear();
|
||||
|
||||
/// \brief Swap this data structure's contents with another CXXBasePaths
|
||||
/// object.
|
||||
void swap(CXXBasePaths &Other);
|
||||
};
|
||||
|
||||
/// \brief Uniquely identifies a virtual method within a class
|
||||
/// hierarchy by the method itself and a class subobject number.
|
||||
struct UniqueVirtualMethod {
|
||||
UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { }
|
||||
|
||||
UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
|
||||
const CXXRecordDecl *InVirtualSubobject)
|
||||
: Method(Method), Subobject(Subobject),
|
||||
InVirtualSubobject(InVirtualSubobject) { }
|
||||
|
||||
/// \brief The overriding virtual method.
|
||||
CXXMethodDecl *Method;
|
||||
|
||||
/// \brief The subobject in which the overriding virtual method
|
||||
/// resides.
|
||||
unsigned Subobject;
|
||||
|
||||
/// \brief The virtual base class subobject of which this overridden
|
||||
/// virtual method is a part. Note that this records the closest
|
||||
/// derived virtual base class subobject.
|
||||
const CXXRecordDecl *InVirtualSubobject;
|
||||
|
||||
friend bool operator==(const UniqueVirtualMethod &X,
|
||||
const UniqueVirtualMethod &Y) {
|
||||
return X.Method == Y.Method && X.Subobject == Y.Subobject &&
|
||||
X.InVirtualSubobject == Y.InVirtualSubobject;
|
||||
}
|
||||
|
||||
friend bool operator!=(const UniqueVirtualMethod &X,
|
||||
const UniqueVirtualMethod &Y) {
|
||||
return !(X == Y);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief The set of methods that override a given virtual method in
|
||||
/// each subobject where it occurs.
|
||||
///
|
||||
/// The first part of the pair is the subobject in which the
|
||||
/// overridden virtual function occurs, while the second part of the
|
||||
/// pair is the virtual method that overrides it (including the
|
||||
/// subobject in which that virtual function occurs).
|
||||
class OverridingMethods {
|
||||
llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
|
||||
Overrides;
|
||||
|
||||
public:
|
||||
// Iterate over the set of subobjects that have overriding methods.
|
||||
typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
|
||||
::iterator iterator;
|
||||
typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
|
||||
::const_iterator const_iterator;
|
||||
iterator begin() { return Overrides.begin(); }
|
||||
const_iterator begin() const { return Overrides.begin(); }
|
||||
iterator end() { return Overrides.end(); }
|
||||
const_iterator end() const { return Overrides.end(); }
|
||||
unsigned size() const { return Overrides.size(); }
|
||||
|
||||
// Iterate over the set of overriding virtual methods in a given
|
||||
// subobject.
|
||||
typedef llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
|
||||
overriding_iterator;
|
||||
typedef llvm::SmallVector<UniqueVirtualMethod, 4>::const_iterator
|
||||
overriding_const_iterator;
|
||||
|
||||
// Add a new overriding method for a particular subobject.
|
||||
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding);
|
||||
|
||||
// Add all of the overriding methods from "other" into overrides for
|
||||
// this method. Used when merging the overrides from multiple base
|
||||
// class subobjects.
|
||||
void add(const OverridingMethods &Other);
|
||||
|
||||
// Replace all overriding virtual methods in all subobjects with the
|
||||
// given virtual method.
|
||||
void replaceAll(UniqueVirtualMethod Overriding);
|
||||
};
|
||||
|
||||
/// \brief A mapping from each virtual member function to its set of
|
||||
/// final overriders.
|
||||
///
|
||||
/// Within a class hierarchy for a given derived class, each virtual
|
||||
/// member function in that hierarchy has one or more "final
|
||||
/// overriders" (C++ [class.virtual]p2). A final overrider for a
|
||||
/// virtual function "f" is the virtual function that will actually be
|
||||
/// invoked when dispatching a call to "f" through the
|
||||
/// vtable. Well-formed classes have a single final overrider for each
|
||||
/// virtual function; in abstract classes, the final overrider for at
|
||||
/// least one virtual function is a pure virtual function. Due to
|
||||
/// multiple, virtual inheritance, it is possible for a class to have
|
||||
/// more than one final overrider. Athough this is an error (per C++
|
||||
/// [class.virtual]p2), it is not considered an error here: the final
|
||||
/// overrider map can represent multiple final overriders for a
|
||||
/// method, and it is up to the client to determine whether they are
|
||||
/// problem. For example, the following class \c D has two final
|
||||
/// overriders for the virtual function \c A::f(), one in \c C and one
|
||||
/// in \c D:
|
||||
///
|
||||
/// \code
|
||||
/// struct A { virtual void f(); };
|
||||
/// struct B : virtual A { virtual void f(); };
|
||||
/// struct C : virtual A { virtual void f(); };
|
||||
/// struct D : B, C { };
|
||||
/// \endcode
|
||||
///
|
||||
/// This data structure contaings a mapping from every virtual
|
||||
/// function *that does not override an existing virtual function* and
|
||||
/// in every subobject where that virtual function occurs to the set
|
||||
/// of virtual functions that override it. Thus, the same virtual
|
||||
/// function \c A::f can actually occur in multiple subobjects of type
|
||||
/// \c A due to multiple inheritance, and may be overriden by
|
||||
/// different virtual functions in each, as in the following example:
|
||||
///
|
||||
/// \code
|
||||
/// struct A { virtual void f(); };
|
||||
/// struct B : A { virtual void f(); };
|
||||
/// struct C : A { virtual void f(); };
|
||||
/// struct D : B, C { };
|
||||
/// \endcode
|
||||
///
|
||||
/// Unlike in the previous example, where the virtual functions \c
|
||||
/// B::f and \c C::f both overrode \c A::f in the same subobject of
|
||||
/// type \c A, in this example the two virtual functions both override
|
||||
/// \c A::f but in *different* subobjects of type A. This is
|
||||
/// represented by numbering the subobjects in which the overridden
|
||||
/// and the overriding virtual member functions are located. Subobject
|
||||
/// 0 represents the virtua base class subobject of that type, while
|
||||
/// subobject numbers greater than 0 refer to non-virtual base class
|
||||
/// subobjects of that type.
|
||||
class CXXFinalOverriderMap
|
||||
: public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { };
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
@@ -1,748 +0,0 @@
|
||||
//===-- CanonicalType.h - C Language Family Type Representation -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the CanQual class template, which provides access to
|
||||
// canonical types.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H
|
||||
#define LLVM_CLANG_AST_CANONICAL_TYPE_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <iterator>
|
||||
|
||||
namespace clang {
|
||||
|
||||
template<typename T> class CanProxy;
|
||||
template<typename T> struct CanProxyAdaptor;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Canonical, qualified type template
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
/// \brief Represents a canonical, potentially-qualified type.
|
||||
///
|
||||
/// The CanQual template is a lightweight smart pointer that provides access
|
||||
/// to the canonical representation of a type, where all typedefs and other
|
||||
/// syntactic sugar has been eliminated. A CanQualType may also have various
|
||||
/// qualifiers (const, volatile, restrict) attached to it.
|
||||
///
|
||||
/// The template type parameter @p T is one of the Type classes (PointerType,
|
||||
/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that
|
||||
/// type (or some subclass of that type). The typedef @c CanQualType is just
|
||||
/// a shorthand for @c CanQual<Type>.
|
||||
///
|
||||
/// An instance of @c CanQual<T> can be implicitly converted to a
|
||||
/// @c CanQual<U> when T is derived from U, which essentially provides an
|
||||
/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be
|
||||
/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
|
||||
/// be implicitly converted to a QualType, but the reverse operation requires
|
||||
/// a call to ASTContext::getCanonicalType().
|
||||
///
|
||||
///
|
||||
template<typename T = Type>
|
||||
class CanQual {
|
||||
/// \brief The actual, canonical type.
|
||||
QualType Stored;
|
||||
|
||||
public:
|
||||
/// \brief Constructs a NULL canonical type.
|
||||
CanQual() : Stored() { }
|
||||
|
||||
/// \brief Converting constructor that permits implicit upcasting of
|
||||
/// canonical type pointers.
|
||||
template<typename U>
|
||||
CanQual(const CanQual<U>& Other,
|
||||
typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
|
||||
|
||||
/// \brief Retrieve the underlying type pointer, which refers to a
|
||||
/// canonical type.
|
||||
T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
|
||||
|
||||
/// \brief Implicit conversion to a qualified type.
|
||||
operator QualType() const { return Stored; }
|
||||
|
||||
/// \brief Implicit conversion to bool.
|
||||
operator bool() const { return !isNull(); }
|
||||
|
||||
bool isNull() const {
|
||||
return Stored.isNull();
|
||||
}
|
||||
|
||||
/// \brief Retrieve a canonical type pointer with a different static type,
|
||||
/// upcasting or downcasting as needed.
|
||||
///
|
||||
/// The getAs() function is typically used to try to downcast to a
|
||||
/// more specific (canonical) type in the type system. For example:
|
||||
///
|
||||
/// @code
|
||||
/// void f(CanQual<Type> T) {
|
||||
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) {
|
||||
/// // look at Ptr's pointee type
|
||||
/// }
|
||||
/// }
|
||||
/// @endcode
|
||||
///
|
||||
/// \returns A proxy pointer to the same type, but with the specified
|
||||
/// static type (@p U). If the dynamic type is not the specified static type
|
||||
/// or a derived class thereof, a NULL canonical type.
|
||||
template<typename U> CanProxy<U> getAs() const;
|
||||
|
||||
/// \brief Overloaded arrow operator that produces a canonical type
|
||||
/// proxy.
|
||||
CanProxy<T> operator->() const;
|
||||
|
||||
/// \brief Retrieve all qualifiers.
|
||||
Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
|
||||
|
||||
/// \brief Retrieve the const/volatile/restrict qualifiers.
|
||||
unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
|
||||
|
||||
/// \brief Determines whether this type has any qualifiers
|
||||
bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
|
||||
|
||||
bool isConstQualified() const {
|
||||
return Stored.isLocalConstQualified();
|
||||
}
|
||||
bool isVolatileQualified() const {
|
||||
return Stored.isLocalVolatileQualified();
|
||||
}
|
||||
bool isRestrictQualified() const {
|
||||
return Stored.isLocalRestrictQualified();
|
||||
}
|
||||
|
||||
/// \brief Determines if this canonical type is furthermore
|
||||
/// canonical as a parameter. The parameter-canonicalization
|
||||
/// process decays arrays to pointers and drops top-level qualifiers.
|
||||
bool isCanonicalAsParam() const {
|
||||
return Stored.isCanonicalAsParam();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the unqualified form of this type.
|
||||
CanQual<T> getUnqualifiedType() const;
|
||||
|
||||
/// \brief Retrieves a version of this type with const applied.
|
||||
/// Note that this does not always yield a canonical type.
|
||||
QualType withConst() const {
|
||||
return Stored.withConst();
|
||||
}
|
||||
|
||||
/// \brief Determines whether this canonical type is more qualified than
|
||||
/// the @p Other canonical type.
|
||||
bool isMoreQualifiedThan(CanQual<T> Other) const {
|
||||
return Stored.isMoreQualifiedThan(Other.Stored);
|
||||
}
|
||||
|
||||
/// \brief Determines whether this canonical type is at least as qualified as
|
||||
/// the @p Other canonical type.
|
||||
bool isAtLeastAsQualifiedAs(CanQual<T> Other) const {
|
||||
return Stored.isAtLeastAsQualifiedAs(Other.Stored);
|
||||
}
|
||||
|
||||
/// \brief If the canonical type is a reference type, returns the type that
|
||||
/// it refers to; otherwise, returns the type itself.
|
||||
CanQual<Type> getNonReferenceType() const;
|
||||
|
||||
/// \brief Retrieve the internal representation of this canonical type.
|
||||
void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
|
||||
|
||||
/// \brief Construct a canonical type from its internal representation.
|
||||
static CanQual<T> getFromOpaquePtr(void *Ptr);
|
||||
|
||||
/// \brief Builds a canonical type from a QualType.
|
||||
///
|
||||
/// This routine is inherently unsafe, because it requires the user to
|
||||
/// ensure that the given type is a canonical type with the correct
|
||||
// (dynamic) type.
|
||||
static CanQual<T> CreateUnsafe(QualType Other);
|
||||
|
||||
void dump() const { Stored.dump(); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
ID.AddPointer(getAsOpaquePtr());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator==(CanQual<T> x, CanQual<U> y) {
|
||||
return x.getAsOpaquePtr() == y.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator!=(CanQual<T> x, CanQual<U> y) {
|
||||
return x.getAsOpaquePtr() != y.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
/// \brief Represents a canonical, potentially-qualified type.
|
||||
typedef CanQual<Type> CanQualType;
|
||||
|
||||
inline CanQualType Type::getCanonicalTypeUnqualified() const {
|
||||
return CanQualType::CreateUnsafe(getCanonicalTypeInternal());
|
||||
}
|
||||
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
CanQualType T) {
|
||||
DB << static_cast<QualType>(T);
|
||||
return DB;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Internal proxy classes used by canonical types
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \
|
||||
CanQualType Accessor() const { \
|
||||
return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \
|
||||
}
|
||||
|
||||
#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \
|
||||
Type Accessor() const { return this->getTypePtr()->Accessor(); }
|
||||
|
||||
/// \brief Base class of all canonical proxy types, which is responsible for
|
||||
/// storing the underlying canonical type and providing basic conversions.
|
||||
template<typename T>
|
||||
class CanProxyBase {
|
||||
protected:
|
||||
CanQual<T> Stored;
|
||||
|
||||
public:
|
||||
/// \brief Retrieve the pointer to the underlying Type
|
||||
T* getTypePtr() const { return Stored.getTypePtr(); }
|
||||
|
||||
/// \brief Implicit conversion to the underlying pointer.
|
||||
///
|
||||
/// Also provides the ability to use canonical type proxies in a Boolean
|
||||
// context,e.g.,
|
||||
/// @code
|
||||
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
|
||||
/// @endcode
|
||||
operator const T*() const { return this->Stored.getTypePtr(); }
|
||||
|
||||
/// \brief Try to convert the given canonical type to a specific structural
|
||||
/// type.
|
||||
template<typename U> CanProxy<U> getAs() const {
|
||||
return this->Stored.template getAs<U>();
|
||||
}
|
||||
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass)
|
||||
|
||||
// Type predicates
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
|
||||
|
||||
/// \brief Retrieve the proxy-adaptor type.
|
||||
///
|
||||
/// This arrow operator is used when CanProxyAdaptor has been specialized
|
||||
/// for the given type T. In that case, we reference members of the
|
||||
/// CanProxyAdaptor specialization. Otherwise, this operator will be hidden
|
||||
/// by the arrow operator in the primary CanProxyAdaptor template.
|
||||
const CanProxyAdaptor<T> *operator->() const {
|
||||
return static_cast<const CanProxyAdaptor<T> *>(this);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Replacable canonical proxy adaptor class that provides the link
|
||||
/// between a canonical type and the accessors of the type.
|
||||
///
|
||||
/// The CanProxyAdaptor is a replaceable class template that is instantiated
|
||||
/// as part of each canonical proxy type. The primary template merely provides
|
||||
/// redirection to the underlying type (T), e.g., @c PointerType. One can
|
||||
/// provide specializations of this class template for each underlying type
|
||||
/// that provide accessors returning canonical types (@c CanQualType) rather
|
||||
/// than the more typical @c QualType, to propagate the notion of "canonical"
|
||||
/// through the system.
|
||||
template<typename T>
|
||||
struct CanProxyAdaptor : CanProxyBase<T> { };
|
||||
|
||||
/// \brief Canonical proxy type returned when retrieving the members of a
|
||||
/// canonical type or as the result of the @c CanQual<T>::getAs member
|
||||
/// function.
|
||||
///
|
||||
/// The CanProxy type mainly exists as a proxy through which operator-> will
|
||||
/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy
|
||||
/// type that provides canonical-type access to the fields of the type.
|
||||
template<typename T>
|
||||
class CanProxy : public CanProxyAdaptor<T> {
|
||||
public:
|
||||
/// \brief Build a NULL proxy.
|
||||
CanProxy() { }
|
||||
|
||||
/// \brief Build a proxy to the given canonical type.
|
||||
CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
|
||||
|
||||
/// \brief Implicit conversion to the stored canonical type.
|
||||
operator CanQual<T>() const { return this->Stored; }
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from
|
||||
/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
|
||||
/// to return smart pointer (proxies?).
|
||||
template<typename T>
|
||||
struct simplify_type<const ::clang::CanQual<T> > {
|
||||
typedef T* SimpleType;
|
||||
static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
|
||||
return Val.getTypePtr();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct simplify_type< ::clang::CanQual<T> >
|
||||
: public simplify_type<const ::clang::CanQual<T> > {};
|
||||
|
||||
// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
|
||||
template<typename T>
|
||||
class PointerLikeTypeTraits<clang::CanQual<T> > {
|
||||
public:
|
||||
static inline void *getAsVoidPointer(clang::CanQual<T> P) {
|
||||
return P.getAsOpaquePtr();
|
||||
}
|
||||
static inline clang::CanQual<T> getFromVoidPointer(void *P) {
|
||||
return clang::CanQual<T>::getFromOpaquePtr(P);
|
||||
}
|
||||
// qualifier information is encoded in the low bits.
|
||||
enum { NumLowBitsAvailable = 0 };
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace clang {
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Canonical proxy adaptors for canonical type nodes.
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
/// \brief Iterator adaptor that turns an iterator over canonical QualTypes
|
||||
/// into an iterator over CanQualTypes.
|
||||
template<typename InputIterator>
|
||||
class CanTypeIterator {
|
||||
InputIterator Iter;
|
||||
|
||||
public:
|
||||
typedef CanQualType value_type;
|
||||
typedef value_type reference;
|
||||
typedef CanProxy<Type> pointer;
|
||||
typedef typename std::iterator_traits<InputIterator>::difference_type
|
||||
difference_type;
|
||||
typedef typename std::iterator_traits<InputIterator>::iterator_category
|
||||
iterator_category;
|
||||
|
||||
CanTypeIterator() : Iter() { }
|
||||
explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { }
|
||||
|
||||
// Input iterator
|
||||
reference operator*() const {
|
||||
return CanQualType::CreateUnsafe(*Iter);
|
||||
}
|
||||
|
||||
pointer operator->() const;
|
||||
|
||||
CanTypeIterator &operator++() {
|
||||
++Iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CanTypeIterator operator++(int) {
|
||||
CanTypeIterator Tmp(*this);
|
||||
++Iter;
|
||||
return Tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) {
|
||||
return X.Iter == Y.Iter;
|
||||
}
|
||||
friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) {
|
||||
return X.Iter != Y.Iter;
|
||||
}
|
||||
|
||||
// Bidirectional iterator
|
||||
CanTypeIterator &operator--() {
|
||||
--Iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CanTypeIterator operator--(int) {
|
||||
CanTypeIterator Tmp(*this);
|
||||
--Iter;
|
||||
return Tmp;
|
||||
}
|
||||
|
||||
// Random access iterator
|
||||
reference operator[](difference_type n) const {
|
||||
return CanQualType::CreateUnsafe(Iter[n]);
|
||||
}
|
||||
|
||||
CanTypeIterator &operator+=(difference_type n) {
|
||||
Iter += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CanTypeIterator &operator-=(difference_type n) {
|
||||
Iter -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) {
|
||||
X += n;
|
||||
return X;
|
||||
}
|
||||
|
||||
friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) {
|
||||
X += n;
|
||||
return X;
|
||||
}
|
||||
|
||||
friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) {
|
||||
X -= n;
|
||||
return X;
|
||||
}
|
||||
|
||||
friend difference_type operator-(const CanTypeIterator &X,
|
||||
const CanTypeIterator &Y) {
|
||||
return X - Y;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<BlockPointerType>
|
||||
: public CanProxyBase<BlockPointerType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<LValueReferenceType>
|
||||
: public CanProxyBase<LValueReferenceType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<RValueReferenceType>
|
||||
: public CanProxyBase<RValueReferenceType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<MemberPointerType>
|
||||
: public CanProxyBase<MemberPointerType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ArrayType> : public CanProxyBase<ArrayType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ConstantArrayType>
|
||||
: public CanProxyBase<ConstantArrayType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<IncompleteArrayType>
|
||||
: public CanProxyBase<IncompleteArrayType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<VariableArrayType>
|
||||
: public CanProxyBase<VariableArrayType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<DependentSizedArrayType>
|
||||
: public CanProxyBase<DependentSizedArrayType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<DependentSizedExtVectorType>
|
||||
: public CanProxyBase<DependentSizedExtVectorType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<FunctionNoProtoType>
|
||||
: public CanProxyBase<FunctionNoProtoType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<FunctionProtoType>
|
||||
: public CanProxyBase<FunctionProtoType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)
|
||||
CanQualType getArgType(unsigned i) const {
|
||||
return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
|
||||
}
|
||||
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
|
||||
|
||||
typedef CanTypeIterator<FunctionProtoType::arg_type_iterator>
|
||||
arg_type_iterator;
|
||||
|
||||
arg_type_iterator arg_type_begin() const {
|
||||
return arg_type_iterator(this->getTypePtr()->arg_type_begin());
|
||||
}
|
||||
|
||||
arg_type_iterator arg_type_end() const {
|
||||
return arg_type_iterator(this->getTypePtr()->arg_type_end());
|
||||
}
|
||||
|
||||
// Note: canonical function types never have exception specifications
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr)
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<TemplateTypeParmType>
|
||||
: public CanProxyBase<TemplateTypeParmType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ObjCObjectType>
|
||||
: public CanProxyBase<ObjCObjectType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *,
|
||||
getInterface)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass)
|
||||
|
||||
typedef ObjCObjectPointerType::qual_iterator qual_iterator;
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ObjCObjectPointerType>
|
||||
: public CanProxyBase<ObjCObjectPointerType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *,
|
||||
getInterfaceType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
|
||||
|
||||
typedef ObjCObjectPointerType::qual_iterator qual_iterator;
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Method and function definitions
|
||||
//----------------------------------------------------------------------------//
|
||||
template<typename T>
|
||||
inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
|
||||
return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
|
||||
if (CanQual<ReferenceType> RefType = getAs<ReferenceType>())
|
||||
return RefType->getPointeeType();
|
||||
else
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
|
||||
CanQual<T> Result;
|
||||
Result.Stored = QualType::getFromOpaquePtr(Ptr);
|
||||
assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
|
||||
Result.Stored.isCanonical()) && "Type is not canonical!");
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
|
||||
assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!");
|
||||
assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
|
||||
"Dynamic type does not meet the static type's requires");
|
||||
CanQual<T> Result;
|
||||
Result.Stored = Other;
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
CanProxy<U> CanQual<T>::getAs() const {
|
||||
if (Stored.isNull())
|
||||
return CanProxy<U>();
|
||||
|
||||
if (isa<U>(Stored.getTypePtr()))
|
||||
return CanQual<U>::CreateUnsafe(Stored);
|
||||
|
||||
return CanProxy<U>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CanProxy<T> CanQual<T>::operator->() const {
|
||||
return CanProxy<T>(*this);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
typename CanTypeIterator<InputIterator>::pointer
|
||||
CanTypeIterator<InputIterator>::operator->() const {
|
||||
return CanProxy<Type>(*this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H
|
||||
@@ -1,149 +0,0 @@
|
||||
//===--- CharUnits.h - Character units for sizes and offsets ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the CharUnits class
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_CHARUNITS_H
|
||||
#define LLVM_CLANG_AST_CHARUNITS_H
|
||||
|
||||
#include "llvm/System/DataTypes.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// CharUnits - This is an opaque type for sizes expressed in character units.
|
||||
/// Instances of this type represent a quantity as a multiple of the size
|
||||
/// of the standard C type, char, on the target architecture. As an opaque
|
||||
/// type, CharUnits protects you from accidentally combining operations on
|
||||
/// quantities in bit units and character units.
|
||||
///
|
||||
/// It should be noted that characters and bytes are distinct concepts. Bytes
|
||||
/// refer to addressable units of data storage on the target machine, and
|
||||
/// characters are members of a set of elements used for the organization,
|
||||
/// control, or representation of data. According to C99, bytes are allowed
|
||||
/// to exceed characters in size, although currently, clang only supports
|
||||
/// architectures where the two are the same size.
|
||||
///
|
||||
/// For portability, never assume that a target character is 8 bits wide. Use
|
||||
/// CharUnit values whereever you calculate sizes, offsets, or alignments
|
||||
/// in character units.
|
||||
class CharUnits {
|
||||
public:
|
||||
typedef int64_t QuantityType;
|
||||
|
||||
private:
|
||||
QuantityType Quantity;
|
||||
|
||||
explicit CharUnits(QuantityType C) : Quantity(C) {}
|
||||
|
||||
public:
|
||||
|
||||
/// CharUnits - A default constructor.
|
||||
CharUnits() : Quantity(0) {}
|
||||
|
||||
/// Zero - Construct a CharUnits quantity of zero.
|
||||
static CharUnits Zero() {
|
||||
return CharUnits(0);
|
||||
}
|
||||
|
||||
/// One - Construct a CharUnits quantity of one.
|
||||
static CharUnits One() {
|
||||
return CharUnits(1);
|
||||
}
|
||||
|
||||
/// fromQuantity - Construct a CharUnits quantity from a raw integer type.
|
||||
static CharUnits fromQuantity(QuantityType Quantity) {
|
||||
return CharUnits(Quantity);
|
||||
}
|
||||
|
||||
// Compound assignment.
|
||||
CharUnits& operator+= (const CharUnits &Other) {
|
||||
Quantity += Other.Quantity;
|
||||
return *this;
|
||||
}
|
||||
CharUnits& operator-= (const CharUnits &Other) {
|
||||
Quantity -= Other.Quantity;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Comparison operators.
|
||||
bool operator== (const CharUnits &Other) const {
|
||||
return Quantity == Other.Quantity;
|
||||
}
|
||||
bool operator!= (const CharUnits &Other) const {
|
||||
return Quantity != Other.Quantity;
|
||||
}
|
||||
|
||||
// Relational operators.
|
||||
bool operator< (const CharUnits &Other) const {
|
||||
return Quantity < Other.Quantity;
|
||||
}
|
||||
bool operator<= (const CharUnits &Other) const {
|
||||
return Quantity <= Other.Quantity;
|
||||
}
|
||||
bool operator> (const CharUnits &Other) const {
|
||||
return Quantity > Other.Quantity;
|
||||
}
|
||||
bool operator>= (const CharUnits &Other) const {
|
||||
return Quantity >= Other.Quantity;
|
||||
}
|
||||
|
||||
// Other predicates.
|
||||
|
||||
/// isZero - Test whether the quantity equals zero.
|
||||
bool isZero() const { return Quantity == 0; }
|
||||
|
||||
/// isOne - Test whether the quantity equals one.
|
||||
bool isOne() const { return Quantity == 1; }
|
||||
|
||||
/// isPositive - Test whether the quantity is greater than zero.
|
||||
bool isPositive() const { return Quantity > 0; }
|
||||
|
||||
/// isNegative - Test whether the quantity is less than zero.
|
||||
bool isNegative() const { return Quantity < 0; }
|
||||
|
||||
// Arithmetic operators.
|
||||
CharUnits operator* (QuantityType N) const {
|
||||
return CharUnits(Quantity * N);
|
||||
}
|
||||
CharUnits operator/ (QuantityType N) const {
|
||||
return CharUnits(Quantity / N);
|
||||
}
|
||||
QuantityType operator/ (const CharUnits &Other) const {
|
||||
return Quantity / Other.Quantity;
|
||||
}
|
||||
CharUnits operator% (QuantityType N) const {
|
||||
return CharUnits(Quantity % N);
|
||||
}
|
||||
QuantityType operator% (const CharUnits &Other) const {
|
||||
return Quantity % Other.Quantity;
|
||||
}
|
||||
CharUnits operator+ (const CharUnits &Other) const {
|
||||
return CharUnits(Quantity + Other.Quantity);
|
||||
}
|
||||
CharUnits operator- (const CharUnits &Other) const {
|
||||
return CharUnits(Quantity - Other.Quantity);
|
||||
}
|
||||
|
||||
// Conversions.
|
||||
|
||||
/// getQuantity - Get the raw integer representation of this quantity.
|
||||
QuantityType getQuantity() const { return Quantity; }
|
||||
|
||||
|
||||
}; // class CharUnit
|
||||
} // namespace clang
|
||||
|
||||
inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
|
||||
const clang::CharUnits &CU) {
|
||||
return CU * Scale;
|
||||
}
|
||||
|
||||
#endif // LLVM_CLANG_AST_CHARUNITS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,72 +0,0 @@
|
||||
//===--- DeclAccessPair.h - A decl bundled with its path access -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the DeclAccessPair class, which provides an
|
||||
// efficient representation of a pair of a NamedDecl* and an
|
||||
// AccessSpecifier. Generally the access specifier gives the
|
||||
// natural access of a declaration when named in a class, as
|
||||
// defined in C++ [class.access.base]p1.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H
|
||||
#define LLVM_CLANG_AST_DECLACCESSPAIR_H
|
||||
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class NamedDecl;
|
||||
|
||||
/// A POD class for pairing a NamedDecl* with an access specifier.
|
||||
/// Can be put into unions.
|
||||
class DeclAccessPair {
|
||||
NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial
|
||||
|
||||
enum { Mask = 0x3 };
|
||||
|
||||
public:
|
||||
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) {
|
||||
DeclAccessPair p;
|
||||
p.set(D, AS);
|
||||
return p;
|
||||
}
|
||||
|
||||
NamedDecl *getDecl() const {
|
||||
return (NamedDecl*) (~Mask & (uintptr_t) Ptr);
|
||||
}
|
||||
AccessSpecifier getAccess() const {
|
||||
return AccessSpecifier(Mask & (uintptr_t) Ptr);
|
||||
}
|
||||
|
||||
void setDecl(NamedDecl *D) {
|
||||
set(D, getAccess());
|
||||
}
|
||||
void setAccess(AccessSpecifier AS) {
|
||||
set(getDecl(), AS);
|
||||
}
|
||||
void set(NamedDecl *D, AccessSpecifier AS) {
|
||||
Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) |
|
||||
reinterpret_cast<uintptr_t>(D));
|
||||
}
|
||||
|
||||
operator NamedDecl*() const { return getDecl(); }
|
||||
NamedDecl *operator->() const { return getDecl(); }
|
||||
};
|
||||
}
|
||||
|
||||
// Take a moment to tell SmallVector that DeclAccessPair is POD.
|
||||
namespace llvm {
|
||||
template<typename> struct isPodLike;
|
||||
template<> struct isPodLike<clang::DeclAccessPair> {
|
||||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,223 +0,0 @@
|
||||
//===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the data structures used in the implementation
|
||||
// of DeclContext.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
|
||||
#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
|
||||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class DependentDiagnostic;
|
||||
|
||||
/// StoredDeclsList - This is an array of decls optimized a common case of only
|
||||
/// containing one entry.
|
||||
struct StoredDeclsList {
|
||||
|
||||
/// DeclsTy - When in vector form, this is what the Data pointer points to.
|
||||
typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy;
|
||||
|
||||
/// \brief The stored data, which will be either a pointer to a NamedDecl,
|
||||
/// or a pointer to a vector.
|
||||
llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
|
||||
|
||||
public:
|
||||
StoredDeclsList() {}
|
||||
|
||||
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
|
||||
if (DeclsTy *RHSVec = RHS.getAsVector())
|
||||
Data = new DeclsTy(*RHSVec);
|
||||
}
|
||||
|
||||
~StoredDeclsList() {
|
||||
// If this is a vector-form, free the vector.
|
||||
if (DeclsTy *Vector = getAsVector())
|
||||
delete Vector;
|
||||
}
|
||||
|
||||
StoredDeclsList &operator=(const StoredDeclsList &RHS) {
|
||||
if (DeclsTy *Vector = getAsVector())
|
||||
delete Vector;
|
||||
Data = RHS.Data;
|
||||
if (DeclsTy *RHSVec = RHS.getAsVector())
|
||||
Data = new DeclsTy(*RHSVec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isNull() const { return Data.isNull(); }
|
||||
|
||||
NamedDecl *getAsDecl() const {
|
||||
return Data.dyn_cast<NamedDecl *>();
|
||||
}
|
||||
|
||||
DeclsTy *getAsVector() const {
|
||||
return Data.dyn_cast<DeclsTy *>();
|
||||
}
|
||||
|
||||
void setOnlyValue(NamedDecl *ND) {
|
||||
assert(!getAsVector() && "Not inline");
|
||||
Data = ND;
|
||||
// Make sure that Data is a plain NamedDecl* so we can use its address
|
||||
// at getLookupResult.
|
||||
assert(*(NamedDecl **)&Data == ND &&
|
||||
"PointerUnion mangles the NamedDecl pointer!");
|
||||
}
|
||||
|
||||
void remove(NamedDecl *D) {
|
||||
assert(!isNull() && "removing from empty list");
|
||||
if (NamedDecl *Singleton = getAsDecl()) {
|
||||
assert(Singleton == D && "list is different singleton");
|
||||
(void)Singleton;
|
||||
Data = (NamedDecl *)0;
|
||||
return;
|
||||
}
|
||||
|
||||
DeclsTy &Vec = *getAsVector();
|
||||
DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
|
||||
assert(I != Vec.end() && "list does not contain decl");
|
||||
Vec.erase(I);
|
||||
|
||||
assert(std::find(Vec.begin(), Vec.end(), D)
|
||||
== Vec.end() && "list still contains decl");
|
||||
}
|
||||
|
||||
/// getLookupResult - Return an array of all the decls that this list
|
||||
/// represents.
|
||||
DeclContext::lookup_result getLookupResult() {
|
||||
if (isNull())
|
||||
return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
|
||||
DeclContext::lookup_iterator(0));
|
||||
|
||||
// If we have a single NamedDecl, return it.
|
||||
if (getAsDecl()) {
|
||||
assert(!isNull() && "Empty list isn't allowed");
|
||||
|
||||
// Data is a raw pointer to a NamedDecl*, return it.
|
||||
void *Ptr = &Data;
|
||||
return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
|
||||
}
|
||||
|
||||
assert(getAsVector() && "Must have a vector at this point");
|
||||
DeclsTy &Vector = *getAsVector();
|
||||
|
||||
// Otherwise, we have a range result.
|
||||
return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size());
|
||||
}
|
||||
|
||||
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
|
||||
/// replace the old one with D and return true. Otherwise return false.
|
||||
bool HandleRedeclaration(NamedDecl *D) {
|
||||
// Most decls only have one entry in their list, special case it.
|
||||
if (NamedDecl *OldD = getAsDecl()) {
|
||||
if (!D->declarationReplaces(OldD))
|
||||
return false;
|
||||
setOnlyValue(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine if this declaration is actually a redeclaration.
|
||||
DeclsTy &Vec = *getAsVector();
|
||||
for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
|
||||
OD != ODEnd; ++OD) {
|
||||
NamedDecl *OldD = *OD;
|
||||
if (D->declarationReplaces(OldD)) {
|
||||
*OD = D;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// AddSubsequentDecl - This is called on the second and later decl when it is
|
||||
/// not a redeclaration to merge it into the appropriate place in our list.
|
||||
///
|
||||
void AddSubsequentDecl(NamedDecl *D) {
|
||||
// If this is the second decl added to the list, convert this to vector
|
||||
// form.
|
||||
if (NamedDecl *OldD = getAsDecl()) {
|
||||
DeclsTy *VT = new DeclsTy();
|
||||
VT->push_back(OldD);
|
||||
Data = VT;
|
||||
}
|
||||
|
||||
DeclsTy &Vec = *getAsVector();
|
||||
|
||||
// Using directives end up in a special entry which contains only
|
||||
// other using directives, so all this logic is wasted for them.
|
||||
// But avoiding the logic wastes time in the far-more-common case
|
||||
// that we're *not* adding a new using directive.
|
||||
|
||||
// Tag declarations always go at the end of the list so that an
|
||||
// iterator which points at the first tag will start a span of
|
||||
// decls that only contains tags.
|
||||
if (D->hasTagIdentifierNamespace())
|
||||
Vec.push_back(D);
|
||||
|
||||
// Resolved using declarations go at the front of the list so that
|
||||
// they won't show up in other lookup results. Unresolved using
|
||||
// declarations (which are always in IDNS_Using | IDNS_Ordinary)
|
||||
// follow that so that the using declarations will be contiguous.
|
||||
else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
|
||||
DeclsTy::iterator I = Vec.begin();
|
||||
if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
|
||||
while (I != Vec.end() &&
|
||||
(*I)->getIdentifierNamespace() == Decl::IDNS_Using)
|
||||
++I;
|
||||
}
|
||||
Vec.insert(I, D);
|
||||
|
||||
// All other declarations go at the end of the list, but before any
|
||||
// tag declarations. But we can be clever about tag declarations
|
||||
// because there can only ever be one in a scope.
|
||||
} else if (Vec.back()->hasTagIdentifierNamespace()) {
|
||||
NamedDecl *TagD = Vec.back();
|
||||
Vec.back() = D;
|
||||
Vec.push_back(TagD);
|
||||
} else
|
||||
Vec.push_back(D);
|
||||
}
|
||||
};
|
||||
|
||||
class StoredDeclsMap
|
||||
: public llvm::DenseMap<DeclarationName, StoredDeclsList> {
|
||||
|
||||
public:
|
||||
static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
|
||||
|
||||
private:
|
||||
friend class ASTContext; // walks the chain deleting these
|
||||
friend class DeclContext;
|
||||
llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
|
||||
};
|
||||
|
||||
class DependentStoredDeclsMap : public StoredDeclsMap {
|
||||
public:
|
||||
DependentStoredDeclsMap() : FirstDiagnostic(0) {}
|
||||
|
||||
private:
|
||||
friend class DependentDiagnostic;
|
||||
friend class DeclContext; // iterates over diagnostics
|
||||
|
||||
DependentDiagnostic *FirstDiagnostic;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
@@ -1,166 +0,0 @@
|
||||
//===-- DeclFriend.h - Classes for C++ friend declarations -*- C++ -*------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the section of the AST representing C++ friend
|
||||
// declarations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_DECLFRIEND_H
|
||||
#define LLVM_CLANG_AST_DECLFRIEND_H
|
||||
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// FriendDecl - Represents the declaration of a friend entity,
|
||||
/// which can be a function, a type, or a templated function or type.
|
||||
// For example:
|
||||
///
|
||||
/// @code
|
||||
/// template <typename T> class A {
|
||||
/// friend int foo(T);
|
||||
/// friend class B;
|
||||
/// friend T; // only in C++0x
|
||||
/// template <typename U> friend class C;
|
||||
/// template <typename U> friend A& operator+=(A&, const U&) { ... }
|
||||
/// };
|
||||
/// @endcode
|
||||
///
|
||||
/// The semantic context of a friend decl is its declaring class.
|
||||
class FriendDecl : public Decl {
|
||||
public:
|
||||
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
|
||||
|
||||
private:
|
||||
// The declaration that's a friend of this class.
|
||||
FriendUnion Friend;
|
||||
|
||||
// A pointer to the next friend in the sequence.
|
||||
FriendDecl *NextFriend;
|
||||
|
||||
// Location of the 'friend' specifier.
|
||||
SourceLocation FriendLoc;
|
||||
|
||||
friend class CXXRecordDecl::friend_iterator;
|
||||
friend class CXXRecordDecl;
|
||||
|
||||
FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
|
||||
SourceLocation FriendL)
|
||||
: Decl(Decl::Friend, DC, L),
|
||||
Friend(Friend),
|
||||
NextFriend(0),
|
||||
FriendLoc(FriendL) {
|
||||
}
|
||||
|
||||
explicit FriendDecl(EmptyShell Empty)
|
||||
: Decl(Decl::Friend, Empty), NextFriend(0) { }
|
||||
|
||||
public:
|
||||
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, FriendUnion Friend_,
|
||||
SourceLocation FriendL);
|
||||
static FriendDecl *Create(ASTContext &C, EmptyShell Empty);
|
||||
|
||||
/// If this friend declaration names an (untemplated but possibly
|
||||
/// dependent) type, return the type; otherwise return null. This
|
||||
/// is used for elaborated-type-specifiers and, in C++0x, for
|
||||
/// arbitrary friend type declarations.
|
||||
TypeSourceInfo *getFriendType() const {
|
||||
return Friend.dyn_cast<TypeSourceInfo*>();
|
||||
}
|
||||
|
||||
/// If this friend declaration doesn't name a type, return the inner
|
||||
/// declaration.
|
||||
NamedDecl *getFriendDecl() const {
|
||||
return Friend.dyn_cast<NamedDecl*>();
|
||||
}
|
||||
|
||||
/// Retrieves the location of the 'friend' keyword.
|
||||
SourceLocation getFriendLoc() const {
|
||||
return FriendLoc;
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const FriendDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::Friend; }
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
};
|
||||
|
||||
/// An iterator over the friend declarations of a class.
|
||||
class CXXRecordDecl::friend_iterator {
|
||||
FriendDecl *Ptr;
|
||||
|
||||
friend class CXXRecordDecl;
|
||||
explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
|
||||
public:
|
||||
friend_iterator() {}
|
||||
|
||||
typedef FriendDecl *value_type;
|
||||
typedef FriendDecl *reference;
|
||||
typedef FriendDecl *pointer;
|
||||
typedef int difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
reference operator*() const { return Ptr; }
|
||||
|
||||
friend_iterator &operator++() {
|
||||
assert(Ptr && "attempt to increment past end of friend list");
|
||||
Ptr = Ptr->NextFriend;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend_iterator operator++(int) {
|
||||
friend_iterator tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const friend_iterator &Other) const {
|
||||
return Ptr == Other.Ptr;
|
||||
}
|
||||
|
||||
bool operator!=(const friend_iterator &Other) const {
|
||||
return Ptr != Other.Ptr;
|
||||
}
|
||||
|
||||
friend_iterator &operator+=(difference_type N) {
|
||||
assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
|
||||
while (N--)
|
||||
++*this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend_iterator operator+(difference_type N) const {
|
||||
friend_iterator tmp = *this;
|
||||
tmp += N;
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
|
||||
return friend_iterator(data().FirstFriend);
|
||||
}
|
||||
|
||||
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
|
||||
return friend_iterator(0);
|
||||
}
|
||||
|
||||
inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
|
||||
assert(FD->NextFriend == 0 && "friend already has next friend?");
|
||||
FD->NextFriend = data().FirstFriend;
|
||||
data().FirstFriend = FD;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,151 +0,0 @@
|
||||
//===--- DeclGroup.h - Classes for representing groups of Decls -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_DECLGROUP_H
|
||||
#define LLVM_CLANG_AST_DECLGROUP_H
|
||||
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class ASTContext;
|
||||
class Decl;
|
||||
class DeclGroup;
|
||||
class DeclGroupIterator;
|
||||
|
||||
class DeclGroup {
|
||||
// FIXME: Include a TypeSpecifier object.
|
||||
unsigned NumDecls;
|
||||
|
||||
private:
|
||||
DeclGroup() : NumDecls(0) {}
|
||||
DeclGroup(unsigned numdecls, Decl** decls);
|
||||
|
||||
public:
|
||||
static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
|
||||
|
||||
unsigned size() const { return NumDecls; }
|
||||
|
||||
Decl*& operator[](unsigned i) {
|
||||
assert (i < NumDecls && "Out-of-bounds access.");
|
||||
return *((Decl**) (this+1));
|
||||
}
|
||||
|
||||
Decl* const& operator[](unsigned i) const {
|
||||
assert (i < NumDecls && "Out-of-bounds access.");
|
||||
return *((Decl* const*) (this+1));
|
||||
}
|
||||
};
|
||||
|
||||
class DeclGroupRef {
|
||||
// Note this is not a PointerIntPair because we need the address of the
|
||||
// non-group case to be valid as a Decl** for iteration.
|
||||
enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
|
||||
Decl* D;
|
||||
|
||||
Kind getKind() const {
|
||||
return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
|
||||
}
|
||||
|
||||
public:
|
||||
DeclGroupRef() : D(0) {}
|
||||
|
||||
explicit DeclGroupRef(Decl* d) : D(d) {}
|
||||
explicit DeclGroupRef(DeclGroup* dg)
|
||||
: D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
|
||||
|
||||
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
|
||||
if (NumDecls == 0)
|
||||
return DeclGroupRef();
|
||||
if (NumDecls == 1)
|
||||
return DeclGroupRef(Decls[0]);
|
||||
return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
|
||||
}
|
||||
|
||||
typedef Decl** iterator;
|
||||
typedef Decl* const * const_iterator;
|
||||
|
||||
bool isNull() const { return D == 0; }
|
||||
bool isSingleDecl() const { return getKind() == SingleDeclKind; }
|
||||
bool isDeclGroup() const { return getKind() == DeclGroupKind; }
|
||||
|
||||
Decl *getSingleDecl() {
|
||||
assert(isSingleDecl() && "Isn't a declgroup");
|
||||
return D;
|
||||
}
|
||||
const Decl *getSingleDecl() const {
|
||||
return const_cast<DeclGroupRef*>(this)->getSingleDecl();
|
||||
}
|
||||
|
||||
DeclGroup &getDeclGroup() {
|
||||
assert(isDeclGroup() && "Isn't a declgroup");
|
||||
return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
|
||||
}
|
||||
const DeclGroup &getDeclGroup() const {
|
||||
return const_cast<DeclGroupRef*>(this)->getDeclGroup();
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
if (isSingleDecl())
|
||||
return D ? &D : 0;
|
||||
return &getDeclGroup()[0];
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
if (isSingleDecl())
|
||||
return D ? &D+1 : 0;
|
||||
DeclGroup &G = getDeclGroup();
|
||||
return &G[0] + G.size();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
if (isSingleDecl())
|
||||
return D ? &D : 0;
|
||||
return &getDeclGroup()[0];
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
if (isSingleDecl())
|
||||
return D ? &D+1 : 0;
|
||||
const DeclGroup &G = getDeclGroup();
|
||||
return &G[0] + G.size();
|
||||
}
|
||||
|
||||
void *getAsOpaquePtr() const { return D; }
|
||||
static DeclGroupRef getFromOpaquePtr(void *Ptr) {
|
||||
DeclGroupRef X;
|
||||
X.D = static_cast<Decl*>(Ptr);
|
||||
return X;
|
||||
}
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
namespace llvm {
|
||||
// DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
|
||||
template <typename T>
|
||||
class PointerLikeTypeTraits;
|
||||
template <>
|
||||
class PointerLikeTypeTraits<clang::DeclGroupRef> {
|
||||
public:
|
||||
static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
|
||||
return P.getAsOpaquePtr();
|
||||
}
|
||||
static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
|
||||
return clang::DeclGroupRef::getFromOpaquePtr(P);
|
||||
}
|
||||
enum { NumLowBitsAvailable = 0 };
|
||||
};
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the DeclVisitor interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_AST_DECLVISITOR_H
|
||||
#define LLVM_CLANG_AST_DECLVISITOR_H
|
||||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclFriend.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
#define DISPATCH(NAME, CLASS) \
|
||||
return static_cast<ImplClass*>(this)-> Visit##NAME(static_cast<CLASS*>(D))
|
||||
|
||||
/// \brief A simple visitor class that helps create declaration visitors.
|
||||
template<typename ImplClass, typename RetTy=void>
|
||||
class DeclVisitor {
|
||||
public:
|
||||
RetTy Visit(Decl *D) {
|
||||
switch (D->getKind()) {
|
||||
default: assert(false && "Decl that isn't part of DeclNodes.inc!");
|
||||
#define DECL(DERIVED, BASE) \
|
||||
case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl);
|
||||
#define ABSTRACT_DECL(DECL)
|
||||
#include "clang/AST/DeclNodes.inc"
|
||||
}
|
||||
}
|
||||
|
||||
// If the implementation chooses not to implement a certain visit
|
||||
// method, fall back to the parent.
|
||||
#define DECL(DERIVED, BASE) \
|
||||
RetTy Visit##DERIVED##Decl(DERIVED##Decl *D) { DISPATCH(BASE, BASE); }
|
||||
#include "clang/AST/DeclNodes.inc"
|
||||
|
||||
RetTy VisitDecl(Decl *D) { return RetTy(); }
|
||||
};
|
||||
|
||||
#undef DISPATCH
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_DECLVISITOR_H
|
||||
@@ -1,563 +0,0 @@
|
||||
//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the DeclarationName and DeclarationNameTable classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
|
||||
#define LLVM_CLANG_AST_DECLARATIONNAME_H
|
||||
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/CanonicalType.h"
|
||||
#include "clang/Basic/PartialDiagnostic.h"
|
||||
|
||||
namespace llvm {
|
||||
template <typename T> struct DenseMapInfo;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class CXXSpecialName;
|
||||
class CXXOperatorIdName;
|
||||
class CXXLiteralOperatorIdName;
|
||||
class DeclarationNameExtra;
|
||||
class IdentifierInfo;
|
||||
class MultiKeywordSelector;
|
||||
class UsingDirectiveDecl;
|
||||
class TypeSourceInfo;
|
||||
|
||||
/// DeclarationName - The name of a declaration. In the common case,
|
||||
/// this just stores an IdentifierInfo pointer to a normal
|
||||
/// name. However, it also provides encodings for Objective-C
|
||||
/// selectors (optimizing zero- and one-argument selectors, which make
|
||||
/// up 78% percent of all selectors in Cocoa.h) and special C++ names
|
||||
/// for constructors, destructors, and conversion functions.
|
||||
class DeclarationName {
|
||||
public:
|
||||
/// NameKind - The kind of name this object contains.
|
||||
enum NameKind {
|
||||
Identifier,
|
||||
ObjCZeroArgSelector,
|
||||
ObjCOneArgSelector,
|
||||
ObjCMultiArgSelector,
|
||||
CXXConstructorName,
|
||||
CXXDestructorName,
|
||||
CXXConversionFunctionName,
|
||||
CXXOperatorName,
|
||||
CXXLiteralOperatorName,
|
||||
CXXUsingDirective
|
||||
};
|
||||
|
||||
private:
|
||||
/// StoredNameKind - The kind of name that is actually stored in the
|
||||
/// upper bits of the Ptr field. This is only used internally.
|
||||
enum StoredNameKind {
|
||||
StoredIdentifier = 0,
|
||||
StoredObjCZeroArgSelector,
|
||||
StoredObjCOneArgSelector,
|
||||
StoredDeclarationNameExtra,
|
||||
PtrMask = 0x03
|
||||
};
|
||||
|
||||
/// Ptr - The lowest two bits are used to express what kind of name
|
||||
/// we're actually storing, using the values of NameKind. Depending
|
||||
/// on the kind of name this is, the upper bits of Ptr may have one
|
||||
/// of several different meanings:
|
||||
///
|
||||
/// StoredIdentifier - The name is a normal identifier, and Ptr is
|
||||
/// a normal IdentifierInfo pointer.
|
||||
///
|
||||
/// StoredObjCZeroArgSelector - The name is an Objective-C
|
||||
/// selector with zero arguments, and Ptr is an IdentifierInfo
|
||||
/// pointer pointing to the selector name.
|
||||
///
|
||||
/// StoredObjCOneArgSelector - The name is an Objective-C selector
|
||||
/// with one argument, and Ptr is an IdentifierInfo pointer
|
||||
/// pointing to the selector name.
|
||||
///
|
||||
/// StoredDeclarationNameExtra - Ptr is actually a pointer to a
|
||||
/// DeclarationNameExtra structure, whose first value will tell us
|
||||
/// whether this is an Objective-C selector, C++ operator-id name,
|
||||
/// or special C++ name.
|
||||
uintptr_t Ptr;
|
||||
|
||||
/// getStoredNameKind - Return the kind of object that is stored in
|
||||
/// Ptr.
|
||||
StoredNameKind getStoredNameKind() const {
|
||||
return static_cast<StoredNameKind>(Ptr & PtrMask);
|
||||
}
|
||||
|
||||
/// getExtra - Get the "extra" information associated with this
|
||||
/// multi-argument selector or C++ special name.
|
||||
DeclarationNameExtra *getExtra() const {
|
||||
assert(getStoredNameKind() == StoredDeclarationNameExtra &&
|
||||
"Declaration name does not store an Extra structure");
|
||||
return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask);
|
||||
}
|
||||
|
||||
/// getAsCXXSpecialName - If the stored pointer is actually a
|
||||
/// CXXSpecialName, returns a pointer to it. Otherwise, returns
|
||||
/// a NULL pointer.
|
||||
CXXSpecialName *getAsCXXSpecialName() const {
|
||||
if (getNameKind() >= CXXConstructorName &&
|
||||
getNameKind() <= CXXConversionFunctionName)
|
||||
return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getAsCXXOperatorIdName
|
||||
CXXOperatorIdName *getAsCXXOperatorIdName() const {
|
||||
if (getNameKind() == CXXOperatorName)
|
||||
return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
|
||||
if (getNameKind() == CXXLiteralOperatorName)
|
||||
return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Construct a declaration name from the name of a C++ constructor,
|
||||
// destructor, or conversion function.
|
||||
DeclarationName(CXXSpecialName *Name)
|
||||
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
|
||||
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
|
||||
Ptr |= StoredDeclarationNameExtra;
|
||||
}
|
||||
|
||||
// Construct a declaration name from the name of a C++ overloaded
|
||||
// operator.
|
||||
DeclarationName(CXXOperatorIdName *Name)
|
||||
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
|
||||
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
|
||||
Ptr |= StoredDeclarationNameExtra;
|
||||
}
|
||||
|
||||
DeclarationName(CXXLiteralOperatorIdName *Name)
|
||||
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
|
||||
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId");
|
||||
Ptr |= StoredDeclarationNameExtra;
|
||||
}
|
||||
|
||||
/// Construct a declaration name from a raw pointer.
|
||||
DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
|
||||
|
||||
friend class DeclarationNameTable;
|
||||
friend class NamedDecl;
|
||||
|
||||
/// getFETokenInfoAsVoid - Retrieves the front end-specified pointer
|
||||
/// for this name as a void pointer.
|
||||
void *getFETokenInfoAsVoid() const;
|
||||
|
||||
public:
|
||||
/// DeclarationName - Used to create an empty selector.
|
||||
DeclarationName() : Ptr(0) { }
|
||||
|
||||
// Construct a declaration name from an IdentifierInfo *.
|
||||
DeclarationName(const IdentifierInfo *II)
|
||||
: Ptr(reinterpret_cast<uintptr_t>(II)) {
|
||||
assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
|
||||
}
|
||||
|
||||
// Construct a declaration name from an Objective-C selector.
|
||||
DeclarationName(Selector Sel);
|
||||
|
||||
/// getUsingDirectiveName - Return name for all using-directives.
|
||||
static DeclarationName getUsingDirectiveName();
|
||||
|
||||
// operator bool() - Evaluates true when this declaration name is
|
||||
// non-empty.
|
||||
operator bool() const {
|
||||
return ((Ptr & PtrMask) != 0) ||
|
||||
(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
|
||||
}
|
||||
|
||||
/// Predicate functions for querying what type of name this is.
|
||||
bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; }
|
||||
bool isObjCZeroArgSelector() const {
|
||||
return getStoredNameKind() == StoredObjCZeroArgSelector;
|
||||
}
|
||||
bool isObjCOneArgSelector() const {
|
||||
return getStoredNameKind() == StoredObjCOneArgSelector;
|
||||
}
|
||||
|
||||
/// getNameKind - Determine what kind of name this is.
|
||||
NameKind getNameKind() const;
|
||||
|
||||
/// \brief Determines whether the name itself is dependent, e.g., because it
|
||||
/// involves a C++ type that is itself dependent.
|
||||
///
|
||||
/// Note that this does not capture all of the notions of "dependent name",
|
||||
/// because an identifier can be a dependent name if it is used as the
|
||||
/// callee in a call expression with dependent arguments.
|
||||
bool isDependentName() const;
|
||||
|
||||
/// getNameAsString - Retrieve the human-readable string for this name.
|
||||
std::string getAsString() const;
|
||||
|
||||
/// printName - Print the human-readable name to a stream.
|
||||
void printName(llvm::raw_ostream &OS) const;
|
||||
|
||||
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
|
||||
/// this declaration name, or NULL if this declaration name isn't a
|
||||
/// simple identifier.
|
||||
IdentifierInfo *getAsIdentifierInfo() const {
|
||||
if (isIdentifier())
|
||||
return reinterpret_cast<IdentifierInfo *>(Ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getAsOpaqueInteger - Get the representation of this declaration
|
||||
/// name as an opaque integer.
|
||||
uintptr_t getAsOpaqueInteger() const { return Ptr; }
|
||||
|
||||
/// getAsOpaquePtr - Get the representation of this declaration name as
|
||||
/// an opaque pointer.
|
||||
void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
|
||||
|
||||
static DeclarationName getFromOpaquePtr(void *P) {
|
||||
DeclarationName N;
|
||||
N.Ptr = reinterpret_cast<uintptr_t> (P);
|
||||
return N;
|
||||
}
|
||||
|
||||
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
|
||||
DeclarationName N;
|
||||
N.Ptr = P;
|
||||
return N;
|
||||
}
|
||||
|
||||
/// getCXXNameType - If this name is one of the C++ names (of a
|
||||
/// constructor, destructor, or conversion function), return the
|
||||
/// type associated with that name.
|
||||
QualType getCXXNameType() const;
|
||||
|
||||
/// getCXXOverloadedOperator - If this name is the name of an
|
||||
/// overloadable operator in C++ (e.g., @c operator+), retrieve the
|
||||
/// kind of overloaded operator.
|
||||
OverloadedOperatorKind getCXXOverloadedOperator() const;
|
||||
|
||||
/// getCXXLiteralIdentifier - If this name is the name of a literal
|
||||
/// operator, retrieve the identifier associated with it.
|
||||
IdentifierInfo *getCXXLiteralIdentifier() const;
|
||||
|
||||
/// getObjCSelector - Get the Objective-C selector stored in this
|
||||
/// declaration name.
|
||||
Selector getObjCSelector() const;
|
||||
|
||||
/// getFETokenInfo/setFETokenInfo - The language front-end is
|
||||
/// allowed to associate arbitrary metadata with some kinds of
|
||||
/// declaration names, including normal identifiers and C++
|
||||
/// constructors, destructors, and conversion functions.
|
||||
template<typename T>
|
||||
T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); }
|
||||
|
||||
void setFETokenInfo(void *T);
|
||||
|
||||
/// operator== - Determine whether the specified names are identical..
|
||||
friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
|
||||
return LHS.Ptr == RHS.Ptr;
|
||||
}
|
||||
|
||||
/// operator!= - Determine whether the specified names are different.
|
||||
friend bool operator!=(DeclarationName LHS, DeclarationName RHS) {
|
||||
return LHS.Ptr != RHS.Ptr;
|
||||
}
|
||||
|
||||
static DeclarationName getEmptyMarker() {
|
||||
return DeclarationName(uintptr_t(-1));
|
||||
}
|
||||
|
||||
static DeclarationName getTombstoneMarker() {
|
||||
return DeclarationName(uintptr_t(-2));
|
||||
}
|
||||
|
||||
static int compare(DeclarationName LHS, DeclarationName RHS);
|
||||
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
/// Ordering on two declaration names. If both names are identifiers,
|
||||
/// this provides a lexicographical ordering.
|
||||
inline bool operator<(DeclarationName LHS, DeclarationName RHS) {
|
||||
return DeclarationName::compare(LHS, RHS) < 0;
|
||||
}
|
||||
|
||||
/// Ordering on two declaration names. If both names are identifiers,
|
||||
/// this provides a lexicographical ordering.
|
||||
inline bool operator>(DeclarationName LHS, DeclarationName RHS) {
|
||||
return DeclarationName::compare(LHS, RHS) > 0;
|
||||
}
|
||||
|
||||
/// Ordering on two declaration names. If both names are identifiers,
|
||||
/// this provides a lexicographical ordering.
|
||||
inline bool operator<=(DeclarationName LHS, DeclarationName RHS) {
|
||||
return DeclarationName::compare(LHS, RHS) <= 0;
|
||||
}
|
||||
|
||||
/// Ordering on two declaration names. If both names are identifiers,
|
||||
/// this provides a lexicographical ordering.
|
||||
inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
|
||||
return DeclarationName::compare(LHS, RHS) >= 0;
|
||||
}
|
||||
|
||||
/// DeclarationNameTable - Used to store and retrieve DeclarationName
|
||||
/// instances for the various kinds of declaration names, e.g., normal
|
||||
/// identifiers, C++ constructor names, etc. This class contains
|
||||
/// uniqued versions of each of the C++ special names, which can be
|
||||
/// retrieved using its member functions (e.g.,
|
||||
/// getCXXConstructorName).
|
||||
class DeclarationNameTable {
|
||||
ASTContext &Ctx;
|
||||
void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
|
||||
CXXOperatorIdName *CXXOperatorNames; // Operator names
|
||||
void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
|
||||
|
||||
DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE
|
||||
DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
|
||||
|
||||
public:
|
||||
DeclarationNameTable(ASTContext &C);
|
||||
~DeclarationNameTable();
|
||||
|
||||
/// getIdentifier - Create a declaration name that is a simple
|
||||
/// identifier.
|
||||
DeclarationName getIdentifier(const IdentifierInfo *ID) {
|
||||
return DeclarationName(ID);
|
||||
}
|
||||
|
||||
/// getCXXConstructorName - Returns the name of a C++ constructor
|
||||
/// for the given Type.
|
||||
DeclarationName getCXXConstructorName(CanQualType Ty) {
|
||||
return getCXXSpecialName(DeclarationName::CXXConstructorName,
|
||||
Ty.getUnqualifiedType());
|
||||
}
|
||||
|
||||
/// getCXXDestructorName - Returns the name of a C++ destructor
|
||||
/// for the given Type.
|
||||
DeclarationName getCXXDestructorName(CanQualType Ty) {
|
||||
return getCXXSpecialName(DeclarationName::CXXDestructorName,
|
||||
Ty.getUnqualifiedType());
|
||||
}
|
||||
|
||||
/// getCXXConversionFunctionName - Returns the name of a C++
|
||||
/// conversion function for the given Type.
|
||||
DeclarationName getCXXConversionFunctionName(CanQualType Ty) {
|
||||
return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
|
||||
}
|
||||
|
||||
/// getCXXSpecialName - Returns a declaration name for special kind
|
||||
/// of C++ name, e.g., for a constructor, destructor, or conversion
|
||||
/// function.
|
||||
DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
|
||||
CanQualType Ty);
|
||||
|
||||
/// getCXXOperatorName - Get the name of the overloadable C++
|
||||
/// operator corresponding to Op.
|
||||
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
|
||||
|
||||
/// getCXXLiteralOperatorName - Get the name of the literal operator function
|
||||
/// with II as the identifier.
|
||||
DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
|
||||
};
|
||||
|
||||
/// DeclarationNameLoc - Additional source/type location info
|
||||
/// for a declaration name. Needs a DeclarationName in order
|
||||
/// to be interpreted correctly.
|
||||
struct DeclarationNameLoc {
|
||||
union {
|
||||
// The source location for identifier stored elsewhere.
|
||||
// struct {} Identifier;
|
||||
|
||||
// Type info for constructors, destructors and conversion functions.
|
||||
// Locations (if any) for the tilde (destructor) or operator keyword
|
||||
// (conversion) are stored elsewhere.
|
||||
struct {
|
||||
TypeSourceInfo* TInfo;
|
||||
} NamedType;
|
||||
|
||||
// The location (if any) of the operator keyword is stored elsewhere.
|
||||
struct {
|
||||
unsigned BeginOpNameLoc;
|
||||
unsigned EndOpNameLoc;
|
||||
} CXXOperatorName;
|
||||
|
||||
// The location (if any) of the operator keyword is stored elsewhere.
|
||||
struct {
|
||||
unsigned OpNameLoc;
|
||||
} CXXLiteralOperatorName;
|
||||
|
||||
// struct {} CXXUsingDirective;
|
||||
// struct {} ObjCZeroArgSelector;
|
||||
// struct {} ObjCOneArgSelector;
|
||||
// struct {} ObjCMultiArgSelector;
|
||||
};
|
||||
|
||||
DeclarationNameLoc(DeclarationName Name);
|
||||
// FIXME: this should go away once all DNLocs are properly initialized.
|
||||
DeclarationNameLoc() { NamedType.TInfo = 0; }
|
||||
}; // struct DeclarationNameLoc
|
||||
|
||||
|
||||
/// DeclarationNameInfo - A collector data type for bundling together
|
||||
/// a DeclarationName and the correspnding source/type location info.
|
||||
struct DeclarationNameInfo {
|
||||
private:
|
||||
/// Name - The declaration name, also encoding name kind.
|
||||
DeclarationName Name;
|
||||
/// Loc - The main source location for the declaration name.
|
||||
SourceLocation NameLoc;
|
||||
/// Info - Further source/type location info for special kinds of names.
|
||||
DeclarationNameLoc LocInfo;
|
||||
|
||||
public:
|
||||
// FIXME: remove it.
|
||||
DeclarationNameInfo() {}
|
||||
|
||||
DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc)
|
||||
: Name(Name), NameLoc(NameLoc), LocInfo(Name) {}
|
||||
|
||||
DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc,
|
||||
DeclarationNameLoc LocInfo)
|
||||
: Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}
|
||||
|
||||
/// getName - Returns the embedded declaration name.
|
||||
DeclarationName getName() const { return Name; }
|
||||
/// setName - Sets the embedded declaration name.
|
||||
void setName(DeclarationName N) { Name = N; }
|
||||
|
||||
/// getLoc - Returns the main location of the declaration name.
|
||||
SourceLocation getLoc() const { return NameLoc; }
|
||||
/// setLoc - Sets the main location of the declaration name.
|
||||
void setLoc(SourceLocation L) { NameLoc = L; }
|
||||
|
||||
const DeclarationNameLoc &getInfo() const { return LocInfo; }
|
||||
DeclarationNameLoc &getInfo() { return LocInfo; }
|
||||
void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; }
|
||||
|
||||
/// getNamedTypeInfo - Returns the source type info associated to
|
||||
/// the name. Assumes it is a constructor, destructor or conversion.
|
||||
TypeSourceInfo *getNamedTypeInfo() const {
|
||||
assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
|
||||
Name.getNameKind() == DeclarationName::CXXDestructorName ||
|
||||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
|
||||
return LocInfo.NamedType.TInfo;
|
||||
}
|
||||
/// setNamedTypeInfo - Sets the source type info associated to
|
||||
/// the name. Assumes it is a constructor, destructor or conversion.
|
||||
void setNamedTypeInfo(TypeSourceInfo *TInfo) {
|
||||
assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
|
||||
Name.getNameKind() == DeclarationName::CXXDestructorName ||
|
||||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
|
||||
LocInfo.NamedType.TInfo = TInfo;
|
||||
}
|
||||
|
||||
/// getCXXOperatorNameRange - Gets the range of the operator name
|
||||
/// (without the operator keyword). Assumes it is a (non-literal) operator.
|
||||
SourceRange getCXXOperatorNameRange() const {
|
||||
assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
|
||||
return SourceRange(
|
||||
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc),
|
||||
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
|
||||
);
|
||||
}
|
||||
/// setCXXOperatorNameRange - Sets the range of the operator name
|
||||
/// (without the operator keyword). Assumes it is a C++ operator.
|
||||
void setCXXOperatorNameRange(SourceRange R) {
|
||||
assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
|
||||
LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding();
|
||||
LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding();
|
||||
}
|
||||
|
||||
/// getCXXLiteralOperatorNameLoc - Returns the location of the literal
|
||||
/// operator name (not the operator keyword).
|
||||
/// Assumes it is a literal operator.
|
||||
SourceLocation getCXXLiteralOperatorNameLoc() const {
|
||||
assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
|
||||
return SourceLocation::
|
||||
getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
|
||||
}
|
||||
/// setCXXLiteralOperatorNameLoc - Sets the location of the literal
|
||||
/// operator name (not the operator keyword).
|
||||
/// Assumes it is a literal operator.
|
||||
void setCXXLiteralOperatorNameLoc(SourceLocation Loc) {
|
||||
assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
|
||||
LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
|
||||
}
|
||||
|
||||
/// getAsString - Retrieve the human-readable string for this name.
|
||||
std::string getAsString() const;
|
||||
|
||||
/// printName - Print the human-readable name to a stream.
|
||||
void printName(llvm::raw_ostream &OS) const;
|
||||
|
||||
/// getBeginLoc - Retrieve the location of the first token.
|
||||
SourceLocation getBeginLoc() const { return NameLoc; }
|
||||
/// getEndLoc - Retrieve the location of the last token.
|
||||
SourceLocation getEndLoc() const;
|
||||
/// getSourceRange - The range of the declaration name.
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange(getBeginLoc(), getEndLoc());
|
||||
}
|
||||
};
|
||||
|
||||
/// Insertion operator for diagnostics. This allows sending DeclarationName's
|
||||
/// into a diagnostic with <<.
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
DeclarationName N) {
|
||||
DB.AddTaggedVal(N.getAsOpaqueInteger(),
|
||||
Diagnostic::ak_declarationname);
|
||||
return DB;
|
||||
}
|
||||
|
||||
/// Insertion operator for partial diagnostics. This allows binding
|
||||
/// DeclarationName's into a partial diagnostic with <<.
|
||||
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
DeclarationName N) {
|
||||
PD.AddTaggedVal(N.getAsOpaqueInteger(),
|
||||
Diagnostic::ak_declarationname);
|
||||
return PD;
|
||||
}
|
||||
|
||||
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
|
||||
DeclarationNameInfo DNInfo) {
|
||||
DNInfo.printName(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
namespace llvm {
|
||||
/// Define DenseMapInfo so that DeclarationNames can be used as keys
|
||||
/// in DenseMap and DenseSets.
|
||||
template<>
|
||||
struct DenseMapInfo<clang::DeclarationName> {
|
||||
static inline clang::DeclarationName getEmptyKey() {
|
||||
return clang::DeclarationName::getEmptyMarker();
|
||||
}
|
||||
|
||||
static inline clang::DeclarationName getTombstoneKey() {
|
||||
return clang::DeclarationName::getTombstoneMarker();
|
||||
}
|
||||
|
||||
static unsigned getHashValue(clang::DeclarationName);
|
||||
|
||||
static inline bool
|
||||
isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::DeclarationName> { static const bool value = true; };
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
@@ -1,192 +0,0 @@
|
||||
//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines interfaces for diagnostics which may or may
|
||||
// fire based on how a template is instantiated.
|
||||
//
|
||||
// At the moment, the only consumer of this interface is access
|
||||
// control.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
|
||||
#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
|
||||
|
||||
#include "clang/Basic/PartialDiagnostic.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclContextInternals.h"
|
||||
#include "clang/AST/Type.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class ASTContext;
|
||||
class CXXRecordDecl;
|
||||
class NamedDecl;
|
||||
|
||||
/// A dependently-generated diagnostic.
|
||||
class DependentDiagnostic {
|
||||
public:
|
||||
enum AccessNonce { Access = 0 };
|
||||
|
||||
static DependentDiagnostic *Create(ASTContext &Context,
|
||||
DeclContext *Parent,
|
||||
AccessNonce _,
|
||||
SourceLocation Loc,
|
||||
bool IsMemberAccess,
|
||||
AccessSpecifier AS,
|
||||
NamedDecl *TargetDecl,
|
||||
CXXRecordDecl *NamingClass,
|
||||
QualType BaseObjectType,
|
||||
const PartialDiagnostic &PDiag) {
|
||||
DependentDiagnostic *DD = Create(Context, Parent, PDiag);
|
||||
DD->AccessData.Loc = Loc.getRawEncoding();
|
||||
DD->AccessData.IsMember = IsMemberAccess;
|
||||
DD->AccessData.Access = AS;
|
||||
DD->AccessData.TargetDecl = TargetDecl;
|
||||
DD->AccessData.NamingClass = NamingClass;
|
||||
DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr();
|
||||
return DD;
|
||||
}
|
||||
|
||||
unsigned getKind() const {
|
||||
return Access;
|
||||
}
|
||||
|
||||
bool isAccessToMember() const {
|
||||
assert(getKind() == Access);
|
||||
return AccessData.IsMember;
|
||||
}
|
||||
|
||||
AccessSpecifier getAccess() const {
|
||||
assert(getKind() == Access);
|
||||
return AccessSpecifier(AccessData.Access);
|
||||
}
|
||||
|
||||
SourceLocation getAccessLoc() const {
|
||||
assert(getKind() == Access);
|
||||
return SourceLocation::getFromRawEncoding(AccessData.Loc);
|
||||
}
|
||||
|
||||
NamedDecl *getAccessTarget() const {
|
||||
assert(getKind() == Access);
|
||||
return AccessData.TargetDecl;
|
||||
}
|
||||
|
||||
NamedDecl *getAccessNamingClass() const {
|
||||
assert(getKind() == Access);
|
||||
return AccessData.NamingClass;
|
||||
}
|
||||
|
||||
QualType getAccessBaseObjectType() const {
|
||||
assert(getKind() == Access);
|
||||
return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
|
||||
}
|
||||
|
||||
const PartialDiagnostic &getDiagnostic() const {
|
||||
return Diag;
|
||||
}
|
||||
|
||||
private:
|
||||
DependentDiagnostic(const PartialDiagnostic &PDiag,
|
||||
PartialDiagnostic::Storage *Storage)
|
||||
: Diag(PDiag, Storage) {}
|
||||
|
||||
static DependentDiagnostic *Create(ASTContext &Context,
|
||||
DeclContext *Parent,
|
||||
const PartialDiagnostic &PDiag);
|
||||
|
||||
friend class DependentStoredDeclsMap;
|
||||
friend class DeclContext::ddiag_iterator;
|
||||
DependentDiagnostic *NextDiagnostic;
|
||||
|
||||
PartialDiagnostic Diag;
|
||||
|
||||
union {
|
||||
struct {
|
||||
unsigned Loc;
|
||||
unsigned Access : 2;
|
||||
unsigned IsMember : 1;
|
||||
NamedDecl *TargetDecl;
|
||||
CXXRecordDecl *NamingClass;
|
||||
void *BaseObjectType;
|
||||
} AccessData;
|
||||
};
|
||||
};
|
||||
|
||||
///
|
||||
|
||||
/// An iterator over the dependent diagnostics in a dependent context.
|
||||
class DeclContext::ddiag_iterator {
|
||||
public:
|
||||
ddiag_iterator() : Ptr(0) {}
|
||||
explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
|
||||
|
||||
typedef DependentDiagnostic *value_type;
|
||||
typedef DependentDiagnostic *reference;
|
||||
typedef DependentDiagnostic *pointer;
|
||||
typedef int difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
reference operator*() const { return Ptr; }
|
||||
|
||||
ddiag_iterator &operator++() {
|
||||
assert(Ptr && "attempt to increment past end of diag list");
|
||||
Ptr = Ptr->NextDiagnostic;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ddiag_iterator operator++(int) {
|
||||
ddiag_iterator tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(ddiag_iterator Other) const {
|
||||
return Ptr == Other.Ptr;
|
||||
}
|
||||
|
||||
bool operator!=(ddiag_iterator Other) const {
|
||||
return Ptr != Other.Ptr;
|
||||
}
|
||||
|
||||
ddiag_iterator &operator+=(difference_type N) {
|
||||
assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
|
||||
while (N--)
|
||||
++*this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ddiag_iterator operator+(difference_type N) const {
|
||||
ddiag_iterator tmp = *this;
|
||||
tmp += N;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
DependentDiagnostic *Ptr;
|
||||
};
|
||||
|
||||
inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const {
|
||||
assert(isDependentContext()
|
||||
&& "cannot iterate dependent diagnostics of non-dependent context");
|
||||
const DependentStoredDeclsMap *Map
|
||||
= static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->LookupPtr);
|
||||
|
||||
if (!Map) return ddiag_iterator();
|
||||
return ddiag_iterator(Map->FirstDiagnostic);
|
||||
}
|
||||
|
||||
inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const {
|
||||
return ddiag_iterator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user