Compare commits

..

36 Commits

Author SHA1 Message Date
Tanya Lattner
18665516ad Commit 2.7 release notes.
Update getting started guide for 2.7

llvm-svn: 102412
2010-04-27 06:53:59 +00:00
Tanya Lattner
079a588dd1 Merge 102239 from mainline to fix PR6835
-gThis line, and those below, will be ignored--

M    Makefile.rules

llvm-svn: 102310
2010-04-25 19:18:33 +00:00
Tanya Lattner
c529f00553 Merge r100936 from mainline to fix PR6760.
llvm-svn: 101137
2010-04-13 16:34:45 +00:00
Tanya Lattner
2026b3fd03 Merge r101067 from mainline.
fix PR6660/6168: emit padding as zeros instead of undef.  Because 
trailing fields may not be represented in initializer lists, they
are being handled as padding and those fields *must* be zero 
initialized.

llvm-svn: 101134
2010-04-13 16:15:50 +00:00
Tanya Lattner
3810f02f45 Merge r100559 from mainline to fix PR6696.
llvm-svn: 100851
2010-04-09 05:05:41 +00:00
Tanya Lattner
b466918a8c Merge r100516 from mainline.
Fix PR 6725. It looks like the copy constructor gets elided during inlining.
This bug only shows up with GCC 4.4.1 Release-Asserts build.

llvm-svn: 100520
2010-04-06 05:09:03 +00:00
Tanya Lattner
a52223b574 Merge 100438 from mainline.
Push const through the regex engine. Fixes some of the warnings in PR6616.

llvm-svn: 100450
2010-04-05 18:44:01 +00:00
Tanya Lattner
b76aad9fc0 Merge 98095 from mainline. Fix for PR5893.
llvm-svn: 99958
2010-03-30 23:03:45 +00:00
Tanya Lattner
e9e7d08fc6 Merge 98074 from mainline. Fix for PR5893.
llvm-svn: 99956
2010-03-30 23:03:09 +00:00
Tanya Lattner
25e67eda53 Merge 99620 from mainline.
Do not sibcall if stack needs to be dynamically aligned.

llvm-svn: 99955
2010-03-30 23:01:26 +00:00
Tanya Lattner
1df1d40e9f Merge 98455 from mainline.
llvm-svn: 99911
2010-03-30 18:53:49 +00:00
Tanya Lattner
3a2ed724e3 Merge 99762 from mainline.
llvm-svn: 99908
2010-03-30 18:36:57 +00:00
Tanya Lattner
8ab7ded56f Merge 99043 from mainline.
llvm-svn: 99907
2010-03-30 18:35:26 +00:00
Tanya Lattner
d6db52d9b1 Merge 98701 from mainline.
Fix death tests in -Assert builds.

llvm-svn: 99906
2010-03-30 18:33:25 +00:00
Tanya Lattner
2db982c41f Merge 99032 from mainline.
If call result is in ST0 and it is not being passed to the caller's
caller, then it is not safe to optimize the call into a sibcall since
the call result has to be popped off the x87 stack.

llvm-svn: 99293
2010-03-23 17:16:35 +00:00
Tanya Lattner
650437f2ef Merge 98977 from mainline.
llvm-svn: 99292
2010-03-23 17:15:19 +00:00
Tanya Lattner
3e7b991362 Merge r98845 from mainline.
llvm-svn: 99291
2010-03-23 17:11:51 +00:00
Tanya Lattner
95e705dba6 Merge 98561 from mainline.
Avoid sibcall optimization if either caller or callee is using sret semantics.

llvm-svn: 99290
2010-03-23 17:06:56 +00:00
Tanya Lattner
18d41baa16 Merge r98416 from mainline.
Fix a typo in ValueTracking that's causing instcombine to delete needed shift instructions.

llvm-svn: 99289
2010-03-23 16:58:02 +00:00
Tanya Lattner
6fa2343443 Update version number.
llvm-svn: 98997
2010-03-19 21:30:15 +00:00
Tanya Lattner
16b1f648f4 Merge r98985 from mainline.
Update copyright.

llvm-svn: 98996
2010-03-19 21:29:27 +00:00
Tanya Lattner
3c8d9e3967 Doc patch for the branch only.
llvm-svn: 98314
2010-03-12 00:16:00 +00:00
Tanya Lattner
406d24b588 Merge 97980 from mainline.
Add documentation on sibling call optimization. Rename tailcall2.ll test to sibcall.ll.

llvm-svn: 98313
2010-03-12 00:12:20 +00:00
Tanya Lattner
6fdd777171 Merge 97974 from mainline.
Iterator traits and swap.  closes PR6548 and PR6549

llvm-svn: 98312
2010-03-12 00:10:21 +00:00
Tanya Lattner
c268488db7 Merge 97965 from mainline.
Update the OCaml Kaleidoscope tutorial.

llvm-svn: 98311
2010-03-12 00:09:10 +00:00
Tanya Lattner
859d4167a0 Merge 98264 from mainline.
fix PR6433, crash on va_arg of typedef.

llvm-svn: 98310
2010-03-12 00:05:05 +00:00
Tanya Lattner
93d8c22608 Merge 98205 from mainline.
Work around a bug in the openbsd assembler on i386,
which doesn't support .quad correctly because it is
"really really old".  PR6528.

Yet another reason the mc assembler should take over ;-)

llvm-svn: 98309
2010-03-12 00:03:18 +00:00
Tanya Lattner
45400fd182 Merge 98171 from mainline.
PR6540: Set the newly introduced variables ENABLE_SHARED and
SHLIBPATH_VAR in lit.site.cfg not only in the autoconf build, but also
in a cmake one.

llvm-svn: 98308
2010-03-12 00:00:12 +00:00
Tanya Lattner
105e1edc48 Merge 98212 from mainline.
add support, testcases, and dox for the new GHC calling
convention.  Patch by David Terei!

llvm-svn: 98307
2010-03-11 23:59:04 +00:00
Tanya Lattner
48bc24b58e Merge 98203 from mainline.
fix PR6533 by updating the br(xor) code to remember the case
when it looked past a trunc.

llvm-svn: 98306
2010-03-11 23:57:44 +00:00
Tanya Lattner
122bda50ba Merge r98192 from mainline.
add DESTDIR support for clang headers, PR6556.
Patch by Matthias Klose!

llvm-svn: 98304
2010-03-11 23:49:45 +00:00
Tanya Lattner
6e1a72fe08 Merge r98193 from mainline.
add DESTDIR support for TOOLALIAS, for PR6557, patch by
Matthias Klose!

llvm-svn: 98303
2010-03-11 23:47:58 +00:00
Tanya Lattner
2e7c26b02e Merge 98042.
Don't try to fold V_SET0 and V_SETALLONES to loads in medium and
large code models.

llvm-svn: 98301
2010-03-11 23:41:22 +00:00
Tanya Lattner
acd2efdbc3 Merge 97981 from mainline.
add a codegen hack to work around an AST bug, allowing us to compile the
code in PR6537.  This should be reverted when the ast bug is fixed.

llvm-svn: 98298
2010-03-11 23:26:52 +00:00
Ted Kremenek
f498a646c7 Disable static analysis support for C++. It is still under active development, and should not
be considered generally usable for the 2.7 release.

llvm-svn: 97961
2010-03-08 19:08:23 +00:00
Tanya Lattner
e35b1819ad Create 2.7 release branch.
llvm-svn: 97937
llvm-svn: 97934
2010-03-08 05:04:39 +00:00
15871 changed files with 472599 additions and 1837187 deletions

25
clang/.gitignore vendored
View File

@@ -1,25 +0,0 @@
#==============================================================================#
# This file specifies intentionally untracked files that git should ignore.
# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html
#
# This file is intentionally different from the output of `git svn show-ignore`,
# as most of those are useless.
#==============================================================================#
#==============================================================================#
# File extensions to be ignored anywhere in the tree.
#==============================================================================#
# Temp files created by most text editors.
*~
# Merge files created by git.
*.orig
# Byte compiled python modules.
*.pyc
# vim swap files
.*.swp
#==============================================================================#
# Explicit files to ignore (only matches one).
#==============================================================================#
cscope.files
cscope.out

View File

@@ -1,184 +1,40 @@
# If we are not building as a part of LLVM, build Clang as an
# standalone project, using LLVM as an external library:
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
project(Clang)
cmake_minimum_required(VERSION 2.8)
# Clang version information
set(CLANG_PATH_TO_LLVM_SOURCE "" CACHE PATH
"Path to LLVM source code. Not necessary if using an installed LLVM.")
set(CLANG_PATH_TO_LLVM_BUILD "" CACHE PATH
"Path to the directory where LLVM was built or installed.")
if( CLANG_PATH_TO_LLVM_SOURCE )
if( NOT EXISTS "${CLANG_PATH_TO_LLVM_SOURCE}/cmake/config-ix.cmake" )
message(FATAL_ERROR "Please set CLANG_PATH_TO_LLVM_SOURCE to the root directory of LLVM source code.")
else()
get_filename_component(LLVM_MAIN_SRC_DIR ${CLANG_PATH_TO_LLVM_SOURCE}
ABSOLUTE)
list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules")
endif()
endif()
if( NOT EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
# Looking for bin/Debug/llvm-tblgen is a complete hack. How can we get
# around this?
if( NOT EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/Debug/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
message(FATAL_ERROR "Please set CLANG_PATH_TO_LLVM_BUILD to a directory containing a LLVM build.")
endif()
endif()
list(APPEND CMAKE_MODULE_PATH "${CLANG_PATH_TO_LLVM_BUILD}/share/llvm/cmake")
get_filename_component(PATH_TO_LLVM_BUILD ${CLANG_PATH_TO_LLVM_BUILD}
ABSOLUTE)
include(AddLLVM)
include(TableGen)
include("${CLANG_PATH_TO_LLVM_BUILD}/share/llvm/cmake/LLVMConfig.cmake")
include(HandleLLVMOptions)
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
set(LLVM_MAIN_INCLUDE_DIR "${LLVM_MAIN_SRC_DIR}/include")
set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR})
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories("${PATH_TO_LLVM_BUILD}/include" "${LLVM_MAIN_INCLUDE_DIR}")
link_directories("${PATH_TO_LLVM_BUILD}/lib")
if( EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}")
else()
# FIXME: This is an utter hack.
set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/Debug/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}")
endif()
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
set( CLANG_BUILT_STANDALONE 1 )
endif()
set(CLANG_RESOURCE_DIR "" CACHE STRING
"Relative directory from the Clang binary to its resource files.")
set(C_INCLUDE_DIRS "" CACHE STRING
"Colon separated list of directories clang will search for headers.")
set(CLANG_VENDOR "" CACHE STRING
"Vendor-specific text for showing with version information.")
if( CLANG_VENDOR )
add_definitions( -DCLANG_VENDOR="${CLANG_VENDOR} " )
endif()
# Make sure that CMake reconfigures when the version changes.
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/VER
${CMAKE_CURRENT_BINARY_DIR}/VER)
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})
# Compute the Clang version from the contents of VER
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/VER CLANG_VERSION_DATA)
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
${CLANG_VERSION_DATA})
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 (LLVM_COMPILER_IS_GCC_COMPATIBLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -Wcast-qual -fno-strict-aliasing -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings")
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 ()
configure_file(
${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake
${CLANG_BINARY_DIR}/include/clang/Config/config.h)
include(LLVMParseArguments)
function(clang_tablegen)
# Syntax:
# clang_tablegen output-file [tablegen-arg ...] SOURCE source-file
# [[TARGET cmake-target-name] [DEPENDS extra-dependency ...]]
#
# Generates a custom command for invoking tblgen as
#
# tblgen source-file -o=output-file tablegen-arg ...
#
# and, if cmake-target-name is provided, creates a custom target for
# executing the custom command depending on output-file. It is
# possible to list more files to depend after DEPENDS.
parse_arguments( CTG "SOURCE;TARGET;DEPENDS" "" ${ARGN} )
if( NOT CTG_SOURCE )
message(FATAL_ERROR "SOURCE source-file required by clang_tablegen")
endif()
set( LLVM_TARGET_DEFINITIONS ${CTG_SOURCE} )
tablegen( CLANG ${CTG_DEFAULT_ARGS} )
list( GET CTG_DEFAULT_ARGS 0 output_file )
if( CTG_TARGET )
add_custom_target( ${CTG_TARGET} DEPENDS ${output_file} ${CTG_DEPENDS} )
set_target_properties( ${CTG_TARGET} PROPERTIES FOLDER "Clang tablegenning")
endif()
endfunction(clang_tablegen)
macro(add_clang_library name)
llvm_process_sources(srcs ${ARGN})
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/StaticAnalyzer${dir}/*.h
../../../include/clang/StaticAnalyzer${dir}/*.td
../../../include/clang/StaticAnalyzer${dir}/*.def
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)
if (SHARED_LIBRARY)
set(libkind SHARED)
else()
set(libkind)
@@ -187,12 +43,18 @@ macro(add_clang_library name)
if( LLVM_COMMON_DEPENDS )
add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} )
endif( LLVM_COMMON_DEPENDS )
target_link_libraries( ${name} ${LLVM_USED_LIBS} )
llvm_config( ${name} ${LLVM_LINK_COMPONENTS} )
target_link_libraries( ${name} ${LLVM_COMMON_LIBS} )
link_system_libs( ${name} )
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)
@@ -205,17 +67,20 @@ macro(add_clang_library name)
install(TARGETS ${name}
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
set_target_properties(${name} PROPERTIES FOLDER "Clang libraries")
endmacro(add_clang_library)
macro(add_clang_executable name)
add_llvm_executable( ${name} ${ARGN} )
set_target_properties(${name} PROPERTIES FOLDER "Clang executables")
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(BEFORE
${CMAKE_CURRENT_BINARY_DIR}/include
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include
)
install(DIRECTORY include/
@@ -223,28 +88,11 @@ install(DIRECTORY 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 -DHAVE_CLANG_CONFIG_H )
# Clang version information
set(CLANG_EXECUTABLE_VERSION
"${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING
"Version number that will be placed into the clang executable, in the form XX.YY")
set(LIBCLANG_LIBRARY_VERSION
"${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING
"Version number that will be placed into the libclang library , in the form XX.YY")
mark_as_advanced(CLANG_EXECUTABLE_VERSION LIBCLANG_LIBRARY_VERSION)
add_subdirectory(utils/TableGen)
add_definitions( -D_GNU_SOURCE )
option(CLANG_BUILD_EXAMPLES "Build CLANG example programs." OFF)
if(CLANG_BUILD_EXAMPLES)
@@ -254,25 +102,7 @@ endif ()
add_subdirectory(include)
add_subdirectory(lib)
add_subdirectory(tools)
add_subdirectory(runtime)
# TODO: docs.
add_subdirectory(test)
if( LLVM_INCLUDE_TESTS )
if( NOT CLANG_BUILT_STANDALONE )
add_subdirectory(unittests)
endif()
endif()
# Workaround for MSVS10 to avoid the Dialog Hell
# FIXME: This could be removed with future version of CMake.
if( CLANG_BUILT_STANDALONE AND MSVC_VERSION EQUAL 1600 )
set(CLANG_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/Clang.sln")
if( EXISTS "${CLANG_SLN_FILENAME}" )
file(APPEND "${CLANG_SLN_FILENAME}" "\n# This should be regenerated!\n")
endif()
endif()
set(BUG_REPORT_URL "http://llvm.org/bugs/" CACHE STRING
"Default URL where bug reports are to be submitted.")

View File

@@ -1,27 +0,0 @@
#define EXPAND_2_CASES(i, x, y) CASE(i, x, y); CASE(i + 1, x, y);
#define EXPAND_4_CASES(i, x, y) EXPAND_2_CASES(i, x, y) EXPAND_2_CASES(i + 2, x, y)
#define EXPAND_8_CASES(i, x, y) EXPAND_4_CASES(i, x, y) EXPAND_4_CASES(i + 4, x, y)
#define EXPAND_16_CASES(i, x, y) EXPAND_8_CASES(i, x, y) EXPAND_8_CASES(i + 8, x, y)
#define EXPAND_32_CASES(i, x, y) EXPAND_16_CASES(i, x, y) EXPAND_16_CASES(i + 16, x, y)
#define EXPAND_64_CASES(i, x, y) EXPAND_32_CASES(i, x, y) EXPAND_32_CASES(i + 32, x, y)
#define EXPAND_128_CASES(i, x, y) EXPAND_64_CASES(i, x, y) EXPAND_64_CASES(i + 64, x, y)
#define EXPAND_256_CASES(i, x, y) EXPAND_128_CASES(i, x, y) EXPAND_128_CASES(i + 128, x, y)
#define EXPAND_512_CASES(i, x, y) EXPAND_256_CASES(i, x, y) EXPAND_256_CASES(i + 256, x, y)
#define EXPAND_1024_CASES(i, x, y) EXPAND_512_CASES(i, x, y) EXPAND_512_CASES(i + 512, x, y)
#define EXPAND_2048_CASES(i, x, y) EXPAND_1024_CASES(i, x, y) EXPAND_1024_CASES(i + 1024, x, y)
#define EXPAND_4096_CASES(i, x, y) EXPAND_2048_CASES(i, x, y) EXPAND_2048_CASES(i + 2048, x, y)
// This has a *monstrous* single fan-out in the CFG, across 8000 blocks inside
// the while loop.
unsigned cfg_big_switch(int x) {
unsigned y = 0;
while (x > 0) {
switch(x) {
#define CASE(i, x, y) \
case i: { int case_var = 3*x + i; y += case_var - 1; break; }
EXPAND_4096_CASES(0, x, y);
}
--x;
}
return y;
}

View File

@@ -1,20 +0,0 @@
#define EXPAND_2_BRANCHES(i, x, y) BRANCH(i, x, y); BRANCH(i + 1, x, y);
#define EXPAND_4_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i + 2, x, y)
#define EXPAND_8_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i + 4, x, y)
#define EXPAND_16_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i + 8, x, y)
#define EXPAND_32_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i + 16, x, y)
#define EXPAND_64_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i + 32, x, y)
#define EXPAND_128_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i + 64, x, y)
#define EXPAND_256_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i + 128, x, y)
#define EXPAND_512_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i + 256, x, y)
#define EXPAND_1024_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i + 512, x, y)
#define EXPAND_2048_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i + 1024, x, y)
#define EXPAND_4096_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i + 2048, x, y)
unsigned cfg_long_chain_single_exit(unsigned x) {
unsigned y = 0;
#define BRANCH(i, x, y) if ((x % 13171) < i) { int var = x / 13171; y ^= var; }
EXPAND_4096_BRANCHES(1, x, y);
#undef BRANCH
return y;
}

View File

@@ -1,20 +0,0 @@
#define EXPAND_2_BRANCHES(i, x, y) BRANCH(i, x, y); BRANCH(i + 1, x, y);
#define EXPAND_4_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i + 2, x, y)
#define EXPAND_8_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i + 4, x, y)
#define EXPAND_16_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i + 8, x, y)
#define EXPAND_32_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i + 16, x, y)
#define EXPAND_64_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i + 32, x, y)
#define EXPAND_128_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i + 64, x, y)
#define EXPAND_256_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i + 128, x, y)
#define EXPAND_512_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i + 256, x, y)
#define EXPAND_1024_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i + 512, x, y)
#define EXPAND_2048_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i + 1024, x, y)
#define EXPAND_4096_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i + 2048, x, y)
unsigned cfg_long_chain_multiple_exit(unsigned x) {
unsigned y = 0;
#define BRANCH(i, x, y) if (((x % 13171) + ++y) < i) { int var = x / 13171 + y; return var; }
EXPAND_4096_BRANCHES(1, x, y);
#undef BRANCH
return 42;
}

View File

@@ -1,21 +0,0 @@
#define EXPAND_2_BRANCHES(i, x, y) BRANCH(i, x, y); BRANCH(i + 1, x, y);
#define EXPAND_4_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i + 2, x, y)
#define EXPAND_8_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i + 4, x, y)
#define EXPAND_16_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i + 8, x, y)
#define EXPAND_32_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i + 16, x, y)
#define EXPAND_64_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i + 32, x, y)
#define EXPAND_128_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i + 64, x, y)
#define EXPAND_256_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i + 128, x, y)
#define EXPAND_512_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i + 256, x, y)
#define EXPAND_1024_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i + 512, x, y)
#define EXPAND_2048_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i + 1024, x, y)
#define EXPAND_4096_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i + 2048, x, y)
unsigned cfg_long_chain_many_preds(unsigned x) {
unsigned y = 0;
#define BRANCH(i, x, y) if ((x % 13171) < i) { int var = x / 13171; y ^= var; } else
EXPAND_4096_BRANCHES(1, x, y);
#undef BRANCH
int var = x / 13171; y^= var;
return y;
}

View File

@@ -1,36 +0,0 @@
#define EXPAND_2_INNER_CASES(i, x, y) INNER_CASE(i, x, y); INNER_CASE(i + 1, x, y);
#define EXPAND_4_INNER_CASES(i, x, y) EXPAND_2_INNER_CASES(i, x, y) EXPAND_2_INNER_CASES(i + 2, x, y)
#define EXPAND_8_INNER_CASES(i, x, y) EXPAND_4_INNER_CASES(i, x, y) EXPAND_4_INNER_CASES(i + 4, x, y)
#define EXPAND_16_INNER_CASES(i, x, y) EXPAND_8_INNER_CASES(i, x, y) EXPAND_8_INNER_CASES(i + 8, x, y)
#define EXPAND_32_INNER_CASES(i, x, y) EXPAND_16_INNER_CASES(i, x, y) EXPAND_16_INNER_CASES(i + 16, x, y)
#define EXPAND_64_INNER_CASES(i, x, y) EXPAND_32_INNER_CASES(i, x, y) EXPAND_32_INNER_CASES(i + 32, x, y)
#define EXPAND_2_OUTER_CASES(i, x, y) OUTER_CASE(i, x, y); OUTER_CASE(i + 1, x, y);
#define EXPAND_4_OUTER_CASES(i, x, y) EXPAND_2_OUTER_CASES(i, x, y) EXPAND_2_OUTER_CASES(i + 2, x, y)
#define EXPAND_8_OUTER_CASES(i, x, y) EXPAND_4_OUTER_CASES(i, x, y) EXPAND_4_OUTER_CASES(i + 4, x, y)
#define EXPAND_16_OUTER_CASES(i, x, y) EXPAND_8_OUTER_CASES(i, x, y) EXPAND_8_OUTER_CASES(i + 8, x, y)
#define EXPAND_32_OUTER_CASES(i, x, y) EXPAND_16_OUTER_CASES(i, x, y) EXPAND_16_OUTER_CASES(i + 16, x, y)
#define EXPAND_64_OUTER_CASES(i, x, y) EXPAND_32_OUTER_CASES(i, x, y) EXPAND_32_OUTER_CASES(i + 32, x, y)
// Rather than a single monstrous fan-out, this fans out in smaller increments,
// but to a similar size.
unsigned cfg_nested_switch(int x) {
unsigned y = 0;
while (x > 0) {
switch (x) {
#define INNER_CASE(i, x, y) \
case i: { int case_var = 3*x + i; y += case_var - 1; break; }
#define OUTER_CASE(i, x, y) \
case i: { \
int case_var = y >> 8; \
switch (case_var) { \
EXPAND_64_INNER_CASES(0, x, y); \
} \
break; \
}
EXPAND_64_OUTER_CASES(0, x, y);
}
--x;
}
return y;
}

View File

@@ -1,59 +0,0 @@
// Hammer the CFG with large numbers of overlapping variable scopes, which
// implicit destructors triggered at each edge.
#define EXPAND_BASIC_STRUCT(i) struct X##i { X##i(int); ~X##i(); };
#define EXPAND_NORET_STRUCT(i) struct X##i { X##i(int); ~X##i() __attribute__((noreturn)); };
EXPAND_BASIC_STRUCT(0000); EXPAND_NORET_STRUCT(0001);
EXPAND_BASIC_STRUCT(0010); EXPAND_BASIC_STRUCT(0011);
EXPAND_BASIC_STRUCT(0100); EXPAND_NORET_STRUCT(0101);
EXPAND_NORET_STRUCT(0110); EXPAND_BASIC_STRUCT(0111);
EXPAND_BASIC_STRUCT(1000); EXPAND_NORET_STRUCT(1001);
EXPAND_BASIC_STRUCT(1010); EXPAND_BASIC_STRUCT(1011);
EXPAND_NORET_STRUCT(1100); EXPAND_NORET_STRUCT(1101);
EXPAND_BASIC_STRUCT(1110); EXPAND_BASIC_STRUCT(1111);
#define EXPAND_2_VARS(c, i, x) const X##i var_##c##_##i##0(x), &var_##c##_##i##1 = X##i(x)
#define EXPAND_4_VARS(c, i, x) EXPAND_2_VARS(c, i##0, x); EXPAND_2_VARS(c, i##1, x)
#define EXPAND_8_VARS(c, i, x) EXPAND_4_VARS(c, i##0, x); EXPAND_4_VARS(c, i##1, x)
#define EXPAND_16_VARS(c, i, x) EXPAND_8_VARS(c, i##0, x); EXPAND_8_VARS(c, i##1, x)
#define EXPAND_32_VARS(c, x) EXPAND_16_VARS(c, 0, x); EXPAND_16_VARS(c, 1, x)
#define EXPAND_2_INNER_CASES(i, x, y) INNER_CASE(i, x, y); INNER_CASE(i + 1, x, y);
#define EXPAND_4_INNER_CASES(i, x, y) EXPAND_2_INNER_CASES(i, x, y) EXPAND_2_INNER_CASES(i + 2, x, y)
#define EXPAND_8_INNER_CASES(i, x, y) EXPAND_4_INNER_CASES(i, x, y) EXPAND_4_INNER_CASES(i + 4, x, y)
#define EXPAND_16_INNER_CASES(i, x, y) EXPAND_8_INNER_CASES(i, x, y) EXPAND_8_INNER_CASES(i + 8, x, y)
#define EXPAND_32_INNER_CASES(i, x, y) EXPAND_16_INNER_CASES(i, x, y) EXPAND_16_INNER_CASES(i + 16, x, y)
#define EXPAND_2_OUTER_CASES(i, x, y) OUTER_CASE(i, x, y); OUTER_CASE(i + 1, x, y);
#define EXPAND_4_OUTER_CASES(i, x, y) EXPAND_2_OUTER_CASES(i, x, y) EXPAND_2_OUTER_CASES(i + 2, x, y)
#define EXPAND_8_OUTER_CASES(i, x, y) EXPAND_4_OUTER_CASES(i, x, y) EXPAND_4_OUTER_CASES(i + 4, x, y)
#define EXPAND_16_OUTER_CASES(i, x, y) EXPAND_8_OUTER_CASES(i, x, y) EXPAND_8_OUTER_CASES(i + 8, x, y)
#define EXPAND_32_OUTER_CASES(i, x, y) EXPAND_16_OUTER_CASES(i, x, y) EXPAND_16_OUTER_CASES(i + 16, x, y)
unsigned cfg_nested_vars(int x) {
int y = 0;
while (x > 0) {
EXPAND_32_VARS(a, x);
switch (x) {
#define INNER_CASE(i, x, y) \
case i: { \
int case_var = 3*x + i; \
EXPAND_32_VARS(c, case_var); \
y += case_var - 1; \
break; \
}
#define OUTER_CASE(i, x, y) \
case i: { \
int case_var = y >> 8; \
EXPAND_32_VARS(b, y); \
switch (case_var) { \
EXPAND_32_INNER_CASES(0, x, y); \
} \
break; \
}
EXPAND_32_OUTER_CASES(0, x, y);
}
--x;
}
return y;
}

View File

@@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
Copyright (c) 2007-2011 University of Illinois at Urbana-Champaign.
Copyright (c) 2007-2010 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:

View File

@@ -1,92 +1,24 @@
##===- 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 := utils/TableGen include lib tools runtime docs unittests
LEVEL = ../..
DIRS := include lib tools 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
ifneq ($(ENABLE_DOCS),1)
DIRS := $(filter-out docs, $(DIRS))
endif
# 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
ifdef CLANG_REPOSITORY_STRING
CPP.Flags += -DCLANG_REPOSITORY_STRING='"$(CLANG_REPOSITORY_STRING)"'
endif
# Disable -fstrict-aliasing. Darwin disables it by default (and LLVM doesn't
# work with it enabled with GCC), Clang/llvm-gcc 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
# Set up Clang's tblgen.
ifndef CLANG_TBLGEN
ifeq ($(LLVM_CROSS_COMPILING),1)
CLANG_TBLGEN := $(BuildLLVMToolDir)/clang-tblgen$(BUILD_EXEEXT)
else
CLANG_TBLGEN := $(LLVMToolDir)/clang-tblgen$(EXEEXT)
endif
endif
ClangTableGen = $(CLANG_TBLGEN) $(TableGen.Flags)
###
# Clang Top Level specific stuff.
ifeq ($(IS_TOP_LEVEL),1)
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
$(RecursiveTargets)::
$(Verb) for dir in test unittests; do \
if [ -f $(PROJ_SRC_DIR)/$${dir}/Makefile ] && [ ! -f $${dir}/Makefile ]; then \
$(MKDIR) $${dir}; \
$(CP) $(PROJ_SRC_DIR)/$${dir}/Makefile $${dir}/Makefile; \
fi \
done
$(Verb) if [ ! -f test/Makefile ]; then \
$(MKDIR) test; \
$(CP) $(PROJ_SRC_DIR)/test/Makefile test/Makefile; \
fi
endif
test::
@ $(MAKE) -C test
@ $(MAKE) -C test
report::
@ $(MAKE) -C test report
@@ -94,11 +26,8 @@ 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/`
$(Verb) etags `find . -type f -name \*.h | grep -v /lib/Headers | grep -v /test/` `find . -type f -name \*.cpp | grep -v /lib/Headers | grep -v /test/`
cscope.files:
find tools lib include -name '*.cpp' \
@@ -108,4 +37,29 @@ cscope.files:
.PHONY: test report clean cscope.files
install-local::
$(Echo) Installing include files
$(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir)
$(Verb) if test -d "$(PROJ_SRC_ROOT)/tools/clang/include" ; then \
cd $(PROJ_SRC_ROOT)/tools/clang/include && \
for hdr in `find . -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" ; then \
cd $(PROJ_OBJ_ROOT)/tools/clang/include && \
for hdr in `find . -type f '!' '(' -name 'Makefile' ')' -print \
| grep -v CVS | grep -v .tmp | grep -v .dir` ; do \
$(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
done ; \
fi
endif

View File

@@ -13,7 +13,8 @@ This is similar to -Eonly.
//===---------------------------------------------------------------------===//
Creating and using a PTH file for performance measurement (use a release build).
Creating and using a PTH file for performance measurement (use a release-asserts
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
@@ -83,21 +84,3 @@ enum VerifyConstraintResult {
};
//===---------------------------------------------------------------------===//
Blocks should not capture variables that are only used in dead code.
The rule that we came up with is that blocks are required to capture
variables if they're referenced in evaluated code, even if that code
doesn't actually rely on the value of the captured variable.
For example, this requires a capture:
(void) var;
But this does not:
if (false) puts(var);
Summary of <rdar://problem/9851835>: if we implement this, we should
warn about non-POD variables that are referenced but not captured, but
only if the non-reachability is not due to macro or template
metaprogramming.
//===---------------------------------------------------------------------===//

View File

@@ -4,7 +4,7 @@
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.
compiler intrastructure 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

75
clang/TODO.txt Normal file
View File

@@ -0,0 +1,75 @@
//===---------------------------------------------------------------------===//
// 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
clang/VER Normal file
View File

@@ -0,0 +1 @@
1.1

View File

@@ -2,9 +2,10 @@
// Clang Python Bindings
//===----------------------------------------------------------------------===//
This directory implements Python bindings for Clang.
This directory implements Python bindings for Clang. Currently, only bindings
for the CIndex C API exist.
You may need to alter LD_LIBRARY_PATH so that the Clang library can be
You may need to alter LD_LIBRARY_PATH so that the CIndex library can be
found. The unit tests are designed to be run with 'nosetests'. For example:
--
$ env PYTHONPATH=$(echo ~/llvm/tools/clang/bindings/python/) \

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
from clang.cindex import Index, CursorKind, TypeKind
from clang.cindex import Index, CursorKind
kInput = """\
// FIXME: Find nicer way to drop builtins and other cruft.
@@ -47,17 +47,13 @@ def test_get_children():
assert len(s0_nodes) == 2
assert s0_nodes[0].kind == CursorKind.FIELD_DECL
assert s0_nodes[0].spelling == 'a'
assert s0_nodes[0].type.kind == TypeKind.INT
assert s0_nodes[1].kind == CursorKind.FIELD_DECL
assert s0_nodes[1].spelling == 'b'
assert s0_nodes[1].type.kind == TypeKind.INT
assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
assert tu_nodes[1].spelling == 's1'
assert tu_nodes[1].displayname == '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].displayname == 'f0(int, int)'
assert tu_nodes[2].is_definition() == True

View File

@@ -18,14 +18,10 @@ def test_kind_groups():
for k in CursorKind.get_all_kinds():
group = [n for n in ('is_declaration', 'is_reference', 'is_expression',
'is_statement', 'is_invalid', 'is_attribute')
'is_statement', 'is_invalid')
if getattr(k, n)()]
if k in ( CursorKind.TRANSLATION_UNIT,
CursorKind.MACRO_DEFINITION,
CursorKind.MACRO_INSTANTIATION,
CursorKind.INCLUSION_DIRECTIVE,
CursorKind.PREPROCESSING_DIRECTIVE):
if k == CursorKind.TRANSLATION_UNIT:
assert len(group) == 0
else:
assert len(group) == 1

View File

@@ -3,6 +3,8 @@ 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.
@@ -36,7 +38,7 @@ def test_diagnostic_fixit():
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 == 26
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
@@ -44,26 +46,3 @@ def test_diagnostic_fixit():
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 = '
def test_diagnostic_range():
index = Index.create()
tu = tu_from_source("""void f() { int i = "a" + 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 == 16
assert tu.diagnostics[0].spelling.startswith('incompatible pointer to')
assert len(tu.diagnostics[0].fixits) == 0
assert len(tu.diagnostics[0].ranges) == 1
assert tu.diagnostics[0].ranges[0].start.line == 1
assert tu.diagnostics[0].ranges[0].start.column == 20
assert tu.diagnostics[0].ranges[0].end.line == 1
assert tu.diagnostics[0].ranges[0].end.column == 27
try:
tu.diagnostics[0].ranges[1].start.line
except IndexError:
assert True
else:
assert False

View File

@@ -1,50 +0,0 @@
from clang.cindex import Index
baseInput="int one;\nint two;\n"
def assert_location(loc, line, column, offset):
assert loc.line == line
assert loc.column == column
assert loc.offset == offset
def test_location():
index = Index.create()
tu = index.parse('t.c', unsaved_files = [('t.c',baseInput)])
for n in tu.cursor.get_children():
if n.spelling == 'one':
assert_location(n.location,line=1,column=5,offset=4)
if n.spelling == 'two':
assert_location(n.location,line=2,column=5,offset=13)
# adding a linebreak at top should keep columns same
tu = index.parse('t.c', unsaved_files = [('t.c',"\n"+baseInput)])
for n in tu.cursor.get_children():
if n.spelling == 'one':
assert_location(n.location,line=2,column=5,offset=5)
if n.spelling == 'two':
assert_location(n.location,line=3,column=5,offset=14)
# adding a space should affect column on first line only
tu = index.parse('t.c', unsaved_files = [('t.c'," "+baseInput)])
for n in tu.cursor.get_children():
if n.spelling == 'one':
assert_location(n.location,line=1,column=6,offset=5)
if n.spelling == 'two':
assert_location(n.location,line=2,column=5,offset=14)
def test_extent():
index = Index.create()
tu = index.parse('t.c', unsaved_files = [('t.c',baseInput)])
for n in tu.cursor.get_children():
if n.spelling == 'one':
assert_location(n.extent.start,line=1,column=1,offset=0)
assert_location(n.extent.end,line=1,column=8,offset=7)
assert baseInput[n.extent.start.offset:n.extent.end.offset] == "int one"
if n.spelling == 'two':
assert_location(n.extent.start,line=2,column=1,offset=9)
assert_location(n.extent.end,line=2,column=8,offset=16)
assert baseInput[n.extent.start.offset:n.extent.end.offset] == "int two"

View File

@@ -25,24 +25,16 @@ def test_parse_arguments():
assert spellings[-2] == 'hello'
assert spellings[-1] == 'hi'
def test_reparse_arguments():
path = os.path.join(kInputsDir, 'parse_arguments.c')
index = Index.create()
tu = index.parse(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi'])
tu.reparse()
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()
tu = index.parse('fake.c', ['-I./'], unsaved_files = [
# 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 "fake.h"
#include "/tmp/fake.h"
int x;
int SOME_DEFINE;
"""),
('./fake.h', """
('/tmp/fake.h', """
#define SOME_DEFINE y
""")
])
@@ -58,27 +50,24 @@ def test_unsaved_files_2():
spellings = [c.spelling for c in tu.cursor.get_children()]
assert spellings[-1] == 'x'
def normpaths_equal(path1, path2):
""" Compares two paths for equality after normalizing them with
os.path.normpath
"""
return os.path.normpath(path1) == os.path.normpath(path2)
def test_includes():
def eq(expected, actual):
if not actual.is_input_file:
return normpaths_equal(expected[0], actual.source.name) and \
normpaths_equal(expected[1], actual.include.name)
return expected[0] == actual.source.name and \
expected[1] == actual.include.name
else:
return normpaths_equal(expected[1], actual.include.name)
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 = [(src, h1), (h1, h3), (src, h2), (h2, h3)]
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])

View File

@@ -1,95 +0,0 @@
from clang.cindex import Index, CursorKind, TypeKind
kInput = """\
typedef int I;
struct teststruct {
int a;
I b;
long c;
unsigned long d;
signed long e;
const int f;
int *g;
int ***h;
};
"""
def test_a_struct():
index = Index.create()
tu = index.parse('t.c', unsaved_files = [('t.c',kInput)])
for n in tu.cursor.get_children():
if n.spelling == 'teststruct':
fields = list(n.get_children())
assert all(x.kind == CursorKind.FIELD_DECL for x in fields)
assert fields[0].spelling == 'a'
assert not fields[0].type.is_const_qualified()
assert fields[0].type.kind == TypeKind.INT
assert fields[0].type.get_canonical().kind == TypeKind.INT
assert fields[1].spelling == 'b'
assert not fields[1].type.is_const_qualified()
assert fields[1].type.kind == TypeKind.TYPEDEF
assert fields[1].type.get_canonical().kind == TypeKind.INT
assert fields[1].type.get_declaration().spelling == 'I'
assert fields[2].spelling == 'c'
assert not fields[2].type.is_const_qualified()
assert fields[2].type.kind == TypeKind.LONG
assert fields[2].type.get_canonical().kind == TypeKind.LONG
assert fields[3].spelling == 'd'
assert not fields[3].type.is_const_qualified()
assert fields[3].type.kind == TypeKind.ULONG
assert fields[3].type.get_canonical().kind == TypeKind.ULONG
assert fields[4].spelling == 'e'
assert not fields[4].type.is_const_qualified()
assert fields[4].type.kind == TypeKind.LONG
assert fields[4].type.get_canonical().kind == TypeKind.LONG
assert fields[5].spelling == 'f'
assert fields[5].type.is_const_qualified()
assert fields[5].type.kind == TypeKind.INT
assert fields[5].type.get_canonical().kind == TypeKind.INT
assert fields[6].spelling == 'g'
assert not fields[6].type.is_const_qualified()
assert fields[6].type.kind == TypeKind.POINTER
assert fields[6].type.get_pointee().kind == TypeKind.INT
assert fields[7].spelling == 'h'
assert not fields[7].type.is_const_qualified()
assert fields[7].type.kind == TypeKind.POINTER
assert fields[7].type.get_pointee().kind == TypeKind.POINTER
assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER
assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT
break
else:
assert False, "Didn't find teststruct??"
constarrayInput="""
struct teststruct {
void *A[2];
};
"""
def testConstantArray():
index = Index.create()
tu = index.parse('t.c', unsaved_files = [('t.c',constarrayInput)])
for n in tu.cursor.get_children():
if n.spelling == 'teststruct':
fields = list(n.get_children())
assert fields[0].spelling == 'A'
assert fields[0].type.kind == TypeKind.CONSTANTARRAY
break
else:
assert False, "Didn't find teststruct??"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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), // IFF BLOCK_HAS_SIGNATURE
BLOCK_HAS_SIGNATURE = (1 << 30),
};
In 10.6.ABI the (1<<29) was usually set and was always ignored by the runtime - it had been 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): 10.6.ABI, no signature field available
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 signature field is not always populated.
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), 10 };
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. The call should be:
_Block_object_dispose(&_block_byref_xxx, BLOCK_FIELD_IS_BYREF);
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 *);
id 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 into const copies using the copy constructor. It is an error if a stack based C++ object is used within a block if it does not have a 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 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) {
FOO_ctor(&dst->foo, &src->foo);
}
void __block_dispose_10(struct __block_literal_10 *src) {
FOO_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. For example,
__block FOO blockStorageFoo;
requires the normal constructor for the embedded blockStorageFoo object
FOO_ctor(& _block_byref_blockStorageFoo->blockStorageFoo);
and at scope termination the destructor:
FOO_dtor(& _block_byref_blockStorageFoo->blockStorageFoo);
Note that the forwarding indirection is NOT used.
The compiler would need to generate (if used from a block literal) the following copy/dispose helpers:
void _block_byref_obj_keep(struct _block_byref_blockStorageFoo *dst, struct _block_byref_blockStorageFoo *src) {
FOO_ctor(&dst->blockStorageFoo, &src->blockStorageFoo);
}
void _block_byref_obj_dispose(struct _block_byref_blockStorageFoo *src) {
FOO_dtor(&src->blockStorageFoo);
}
for the appropriately named constructor and destructor for the class/struct FOO.
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);

View File

@@ -0,0 +1,647 @@
Block Implementation Specification
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.
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
This document describes the Apple ABI implementation specification of Blocks.
1. High Level
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);
void (*dispose_helper)(void *src);
} *descriptor;
// imported variables
};
The following flags bits are used by the compiler:
enum {
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
BLOCK_IS_GLOBAL = (1 << 28),
BLOCK_HAS_DESCRIPTOR = (1 << 29), // interim until complete world build is accomplished
};
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);

View File

@@ -151,7 +151,7 @@ For example, given class Foo with member function fighter(void):
...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;
Foo *const block_fooPtr = fooPtr;
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.

View File

@@ -88,7 +88,7 @@
<h3 id="components">Flexible</h3>
<!--=======================================================================-->
<p>The driver was designed to be flexible and easily accommodate
<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
@@ -218,7 +218,7 @@
<p>The clang driver can dump the results of this
stage using the <tt>-ccc-print-options</tt> flag (which
must precede any actual command line arguments). For
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>
@@ -405,7 +405,7 @@
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 fails).</p>
compilation files).</p>
<h4 id="int_unified_parsing">Unified Parsing &amp; Pipelining</h4>
@@ -490,7 +490,7 @@
<li>
<b>Specs</b>
<p>The clang driver has no direct correspondent for
<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

View File

@@ -25,7 +25,6 @@ td {
<li><a href="#Diagnostics">The Diagnostics Subsystem</a></li>
<li><a href="#SourceLocation">The SourceLocation and SourceManager
classes</a></li>
<li><a href="#SourceRange">SourceRange and CharSourceRange</a></li>
</ul>
</li>
<li><a href="#libdriver">The Driver Library</a>
@@ -68,12 +67,7 @@ td {
<li><a href="#Constants">Constant Folding in the Clang AST</a></li>
</ul>
</li>
<li><a href="#Howtos">Howto guides</a>
<ul>
<li><a href="#AddingAttributes">How to add an attribute</a></li>
<li><a href="#AddingExprStmt">How to add a new expression or statement</a></li>
</ul>
</li>
<li><a href="libIndex.html">The Index Library</a></li>
</ul>
@@ -124,8 +118,8 @@ classes somewhere else, or introduce some other solution.</p>
<p>The Clang Diagnostics subsystem is an important part of how the compiler
communicates with the human. Diagnostics are the warnings and errors produced
when the code is incorrect or dubious. In Clang, each diagnostic produced has
(at the minimum) a unique ID, an English translation associated with it, a <a
href="#SourceLocation">SourceLocation</a> to "put the caret", and a severity (e.g.
(at the minimum) a unique ID, a <a href="#SourceLocation">SourceLocation</a> to
"put the caret", an English translation associated with it, and a severity (e.g.
<tt>WARNING</tt> or <tt>ERROR</tt>). They can also optionally include a number
of arguments to the dianostic (which fill in "%0"'s in the string) as well as a
number of source ranges that related to the diagnostic.</p>
@@ -133,7 +127,7 @@ number of source ranges that related to the diagnostic.</p>
<p>In this section, we'll be giving examples produced by the Clang command line
driver, but diagnostics can be <a href="#DiagnosticClient">rendered in many
different ways</a> depending on how the DiagnosticClient interface is
implemented. A representative example of a diagnostic is:</p>
implemented. A representative example of a diagonstic is:</p>
<pre>
t.c:38:15: error: invalid operands to binary expression ('int *' and '_Complex float')
@@ -151,14 +145,15 @@ diagnostic :).</p>
pieces, this section describes them and talks about best practices when adding
a new diagnostic.</p>
<!-- ============================= -->
<h4>The Diagnostic*Kinds.td files</h4>
<!-- ============================= -->
<!-- ============================ -->
<h4>The DiagnosticKinds.def file</h4>
<!-- ============================ -->
<p>Diagnostics are created by adding an entry to one of the <tt>
clang/Basic/Diagnostic*Kinds.td</tt> files, depending on what library will
be using it. From this file, tblgen generates the unique ID of the diagnostic,
the severity of the diagnostic and the English translation + format string.</p>
<p>Diagnostics are created by adding an entry to the <tt><a
href="http://llvm.org/svn/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def"
>DiagnosticKinds.def</a></tt> file. This file encodes the unique ID of the
diagnostic (as an enum, the first argument), the severity of the diagnostic
(second argument) and the English translation + format string.</p>
<p>There is little sanity with the naming of the unique ID's right now. Some
start with err_, warn_, ext_ to encode the severity into the name. Since the
@@ -242,7 +237,7 @@ are some simple format strings:</p>
<ul>
<li>Keep the string short. It should ideally fit in the 80 column limit of the
<tt>DiagnosticKinds.td</tt> file. This avoids the diagnostic wrapping when
<tt>DiagnosticKinds.def</tt> file. This avoids the diagnostic wrapping when
printed, and forces you to think about the important point you are conveying
with the diagnostic.</li>
<li>Take advantage of location information. The user will be able to see the
@@ -257,7 +252,7 @@ are some simple format strings:</p>
<p>Diagnostics should never take random English strings as arguments: you
shouldn't use <tt>"you have a problem with %0"</tt> and pass in things like
<tt>"your argument"</tt> or <tt>"your return value"</tt> as arguments. Doing
this prevents <a href="#translation">translating</a> the Clang diagnostics to
this prevents <a href="translation">translating</a> the Clang diagnostics to
other languages (because they'll get random English words in their otherwise
localized diagnostic). The exceptions to this are C/C++ language keywords
(e.g. auto, const, mutable, etc) and C/C++ operators (<tt>/=</tt>). Note
@@ -372,10 +367,10 @@ of repetitive diagnostics and/or have an idea for a useful formatter, please
bring it up on the cfe-dev mailing list.</p>
<!-- ===================================================== -->
<h4 id="producingdiag">Producing the Diagnostic</h4>
<h4><a name="#producingdiag">Producing the Diagnostic</a></h4>
<!-- ===================================================== -->
<p>Now that you've created the diagnostic in the DiagnosticKinds.td file, you
<p>Now that you've created the diagnostic in the DiagnosticKinds.def file, you
need to write the code that detects the condition in question and emits the
new diagnostic. Various components of Clang (e.g. the preprocessor, Sema,
etc) provide a helper function named "Diag". It creates a diagnostic and
@@ -393,7 +388,7 @@ it.</p>
<p>This shows that use of the Diag method: they take a location (a <a
href="#SourceLocation">SourceLocation</a> object) and a diagnostic enum value
(which matches the name from DiagnosticKinds.td). If the diagnostic takes
(which matches the name from DiagnosticKinds.def). If the diagnostic takes
arguments, they are specified with the &lt;&lt; operator: the first argument
becomes %0, the second becomes %1, etc. The diagnostic interface allows you to
specify arguments of many different types, including <tt>int</tt> and
@@ -412,7 +407,7 @@ it is rendered.
</p>
<!-- ==================================================== -->
<h4 id="fix-it-hints">Fix-It Hints</h4>
<h4 id="code-modification-hints">Code Modification Hints</h4>
<!-- ==================================================== -->
<p>In some cases, the front end emits diagnostics when it is clear
@@ -422,14 +417,14 @@ deprecated syntax that is easily rewritten into a more modern form.
Clang tries very hard to emit the diagnostic and recover gracefully
in these and other cases.</p>
<p>However, for these cases where the fix is obvious, the diagnostic
can be annotated with a hint (referred to as a "fix-it hint") that
describes how to change the code referenced by the diagnostic to fix
the problem. For example, it might add the missing semicolon at the
end of the statement or rewrite the use of a deprecated construct
into something more palatable. Here is one such example from the C++
front end, where we warn about the right-shift operator changing
meaning from C++98 to C++0x:</p>
<p>However, for these cases where the fix is obvious, the diagnostic
can be annotated with a code
modification "hint" that describes how to change the code referenced
by the diagnostic to fix the problem. For example, it might add the
missing semicolon at the end of the statement or rewrite the use of a
deprecated construct into something more palatable. Here is one such
example C++ front end, where we warn about the right-shift operator
changing meaning from C++98 to C++0x:</p>
<pre>
test.cpp:3:7: warning: use of right-shift operator ('&gt;&gt;') in template argument will require parentheses in C++0x
@@ -438,31 +433,33 @@ A&lt;100 &gt;&gt; 2&gt; *a;
( )
</pre>
<p>Here, the fix-it hint is suggesting that parentheses be added,
and showing exactly where those parentheses would be inserted into the
source code. The fix-it hints themselves describe what changes to make
to the source code in an abstract manner, which the text diagnostic
printer renders as a line of "insertions" below the caret line. <a
href="#DiagnosticClient">Other diagnostic clients</a> might choose
to render the code differently (e.g., as markup inline) or even give
the user the ability to automatically fix the problem.</p>
<p>Here, the code modification hint is suggesting that parentheses be
added, and showing exactly where those parentheses would be inserted
into the source code. The code modification hints themselves describe
what changes to make to the source code in an abstract manner, which
the text diagnostic printer renders as a line of "insertions" below
the caret line. <a href="#DiagnosticClient">Other diagnostic
clients</a> might choose to render the code differently (e.g., as
markup inline) or even give the user the ability to automatically fix
the problem.</p>
<p>All fix-it hints are described by the <code>FixItHint</code> class,
instances of which should be attached to the diagnostic using the
&lt;&lt; operator in the same way that highlighted source ranges and
arguments are passed to the diagnostic. Fix-it hints can be created
with one of three constructors:</p>
<p>All code modification hints are described by the
<code>CodeModificationHint</code> class, instances of which should be
attached to the diagnostic using the &lt;&lt; operator in the same way
that highlighted source ranges and arguments are passed to the
diagnostic. Code modification hints can be created with one of three
constructors:</p>
<dl>
<dt><code>FixItHint::CreateInsertion(Loc, Code)</code></dt>
<dt><code>CodeModificationHint::CreateInsertion(Loc, Code)</code></dt>
<dd>Specifies that the given <code>Code</code> (a string) should be inserted
before the source location <code>Loc</code>.</dd>
<dt><code>FixItHint::CreateRemoval(Range)</code></dt>
<dt><code>CodeModificationHint::CreateRemoval(Range)</code></dt>
<dd>Specifies that the code in the given source <code>Range</code>
should be removed.</dd>
<dt><code>FixItHint::CreateReplacement(Range, Code)</code></dt>
<dt><code>CodeModificationHint::CreateReplacement(Range, Code)</code></dt>
<dd>Specifies that the code in the given source <code>Range</code>
should be removed, and replaced with the given <code>Code</code> string.</dd>
</dl>
@@ -535,12 +532,12 @@ source code of the program. Important design points include:</p>
</ol>
<p>In practice, the SourceLocation works together with the SourceManager class
to encode two pieces of information about a location: its spelling location
and its instantiation location. For most tokens, these will be the same.
However, for a macro expansion (or tokens that came from a _Pragma directive)
these will describe the location of the characters corresponding to the token
and the location where the token was used (i.e. the macro instantiation point
or the location of the _Pragma itself).</p>
to encode two pieces of information about a location: it's spelling location
and it's instantiation location. For most tokens, these will be the same. However,
for a macro expansion (or tokens that came from a _Pragma directive) these will
describe the location of the characters corresponding to the token and the
location where the token was used (i.e. the macro instantiation point or the
location of the _Pragma itself).</p>
<p>The Clang front-end inherently depends on the location of a token being
tracked correctly. If it is ever incorrect, the front-end may get confused and
@@ -548,30 +545,6 @@ die. The reason for this is that the notion of the 'spelling' of a Token in
Clang depends on being able to find the original input characters for the token.
This concept maps directly to the "spelling location" for the token.</p>
<!-- ======================================================================= -->
<h3 id="SourceRange">SourceRange and CharSourceRange</h3>
<!-- ======================================================================= -->
<!-- mostly taken from
http://lists.cs.uiuc.edu/pipermail/cfe-dev/2010-August/010595.html -->
<p>Clang represents most source ranges by [first, last], where first and last
each point to the beginning of their respective tokens. For example
consider the SourceRange of the following statement:</p>
<pre>
x = foo + bar;
^first ^last
</pre>
<p>To map from this representation to a character-based
representation, the 'last' location needs to be adjusted to point to
(or past) the end of that token with either
<code>Lexer::MeasureTokenLength()</code> or
<code>Lexer::getLocForEndOfToken()</code>. For the rare cases
where character-level source ranges information is needed we use
the <code>CharSourceRange</code> class.</p>
<!-- ======================================================================= -->
<h2 id="libdriver">The Driver Library</h2>
<!-- ======================================================================= -->
@@ -734,10 +707,9 @@ above, it would be the location of the "a" identifier.</li>
last token replaced with the annotation token. In the example above, it would
be the location of the "c" identifier.</li>
<li><b>void* "AnnotationValue"</b> - This contains an opaque object
that the parser gets from Sema. The parser merely preserves the
information for Sema to later interpret based on the annotation token
kind.</li>
<li><b>void* "AnnotationValue"</b> - This contains an opaque object that the
parser gets from Sema through an Actions module, it is passed around and Sema
intepretes it, based on the type of annotation token.</li>
<li><b>TokenKind "Kind"</b> - This indicates the kind of Annotation token this
is. See below for the different valid kinds.</li>
@@ -747,29 +719,21 @@ is. See below for the different valid kinds.</li>
<ol>
<li><b>tok::annot_typename</b>: This annotation token represents a
resolved typename token that is potentially qualified. The
AnnotationValue field contains the <tt>QualType</tt> returned by
Sema::getTypeName(), possibly with source location information
attached.</li>
resolved typename token that is potentially qualified. The AnnotationValue
field contains a pointer returned by Action::getTypeName(). In the case of the
Sema actions module, this is a <tt>Decl*</tt> for the type.</li>
<li><b>tok::annot_cxxscope</b>: This annotation token represents a C++
scope specifier, such as "A::B::". This corresponds to the grammar
productions "::" and ":: [opt] nested-name-specifier". The
AnnotationValue pointer is a <tt>NestedNameSpecifier*</tt> returned by
the Sema::ActOnCXXGlobalScopeSpecifier and
Sema::ActOnCXXNestedNameSpecifier callbacks.</li>
<li><b>tok::annot_cxxscope</b>: This annotation token represents a C++ scope
specifier, such as "A::B::". This corresponds to the grammar productions "::"
and ":: [opt] nested-name-specifier". The AnnotationValue pointer is returned
by the Action::ActOnCXXGlobalScopeSpecifier and
Action::ActOnCXXNestedNameSpecifier callbacks. In the case of Sema, this is a
<tt>DeclContext*</tt>.</li>
<li><b>tok::annot_template_id</b>: This annotation token represents a
C++ template-id such as "foo&lt;int, 4&gt;", where "foo" is the name
of a template. The AnnotationValue pointer is a pointer to a malloc'd
TemplateIdAnnotation object. Depending on the context, a parsed
template-id that names a type might become a typename annotation token
(if all we care about is the named type, e.g., because it occurs in a
type specifier) or might remain a template-id token (if we want to
retain more source location information or produce a new type, e.g.,
in a declaration of a class template specialization). template-id
annotation tokens that refer to a type can be "upgraded" to typename
annotation tokens by the parser.</li>
TemplateIdAnnotation object. Depending on the context, a parsed template-id that names a type might become a typename annotation token (if all we care about is the named type, e.g., because it occurs in a type specifier) or might remain a template-id token (if we want to retain more source location information or produce a new type, e.g., in a declaration of a class template specialization). template-id annotation tokens that refer to a type can be "upgraded" to typename annotation tokens by the parser.</li>
</ol>
@@ -819,7 +783,7 @@ code is vectorized on X86 and PowerPC hosts).</p>
within the filename.</li>
<li>When parsing a preprocessor directive (after "<tt>#</tt>") the
ParsingPreprocessorDirective mode is entered. This changes the parser to
return EOD at a newline.</li>
return EOM at a newline.</li>
<li>The Lexer uses a LangOptions object to know whether trigraphs are enabled,
whether C++ or ObjC keywords are recognized, etc.</li>
</ul>
@@ -989,12 +953,11 @@ make sense to you :).</p>
<h3 id="QualType">The QualType class</h3>
<!-- ======================================================================= -->
<p>The QualType class is designed as a trivial value class that is
small, passed by-value and is efficient to query. The idea of
QualType is that it stores the type qualifiers (const, volatile,
restrict, plus some extended qualifiers required by language
extensions) separately from the types themselves. QualType is
conceptually a pair of "Type*" and the bits for these type qualifiers.</p>
<p>The QualType class is designed as a trivial value class that is small,
passed by-value and is efficient to query. The idea of QualType is that it
stores the type qualifiers (const, volatile, restrict) separately from the types
themselves: QualType is conceptually a pair of "Type*" and bits for the type
qualifiers.</p>
<p>By storing the type qualifiers as bits in the conceptual pair, it is
extremely efficient to get the set of qualifiers on a QualType (just return the
@@ -1009,11 +972,10 @@ both point to the same heap allocated "int" type). This reduces the heap size
used to represent bits and also means we do not have to consider qualifiers when
uniquing types (<a href="#Type">Type</a> does not even contain qualifiers).</p>
<p>In practice, the two most common type qualifiers (const and
restrict) are stored in the low bits of the pointer to the Type
object, together with a flag indicating whether extended qualifiers
are present (which must be heap-allocated). This means that QualType
is exactly the same size as a pointer.</p>
<p>In practice, on hosts where it is safe, the 3 type qualifiers are stored in
the low bit of the pointer to the Type object. This means that QualType is
exactly the same size as a pointer, and this works fine on any system where
malloc'd objects are at least 8 byte aligned.</p>
<!-- ======================================================================= -->
<h3 id="DeclarationName">Declaration names</h3>
@@ -1213,8 +1175,8 @@ void g();
void g(int);
</pre>
<p>the <code>DeclContext::lookup</code> operation will return
a <code>DeclContext::lookup_result</code> that contains a range of iterators
over declarations of "g". Clients that perform semantic analysis on a
an <code>OverloadedFunctionDecl</code> that contains both
declarations of "g". Clients that perform semantic analysis on a
program that is not concerned with the actual source code will
primarily use this semantics-centric view.</p>
@@ -1396,8 +1358,8 @@ namespace N {
nodes in Snippet #1, each of which is a declaration context that
contains a single declaration of "f". However, the semantics-centric
view provided by name lookup into the namespace <code>N</code> for
"f" will return a <code>DeclContext::lookup_result</code> that contains
a range of iterators over declarations of "f".</p>
"f" will return an <code>OverloadedFunctionDecl</code> that contains
both declarations of "f".</p>
<p><code>DeclContext</code> manages multiply-defined declaration
contexts internally. The
@@ -1709,304 +1671,10 @@ interacts with constant evaluation:</p>
floating-point literal.</li>
<li><b><tt>__builtin_abs,copysign,..</tt></b>: These are constant folded as
general constant expressions.</li>
<li><b><tt>__builtin_strlen</tt></b> and <b><tt>strlen</tt></b>: These are constant folded as integer constant expressions if the argument is a string literal.</li>
</ul>
<!-- ======================================================================= -->
<h2 id="Howtos">How to change Clang</h2>
<!-- ======================================================================= -->
<!-- ======================================================================= -->
<h3 id="AddingAttributes">How to add an attribute</h3>
<!-- ======================================================================= -->
<p>To add an attribute, you'll have to add it to the list of attributes, add it
to the parsing phase, and look for it in the AST scan.
<a href="http://llvm.org/viewvc/llvm-project?view=rev&revision=124217">r124217</a>
has a good example of adding a warning attribute.</p>
<p>(Beware that this hasn't been reviewed/fixed by the people who designed the
attributes system yet.)</p>
<h4><a
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?view=markup">include/clang/Basic/Attr.td</a></h4>
<p>Each attribute gets a <tt>def</tt> inheriting from <tt>Attr</tt> or one of
its subclasses. <tt>InheritableAttr</tt> means that the attribute also applies
to subsequent declarations of the same name.</p>
<p><tt>Spellings</tt> lists the strings that can appear in
<tt>__attribute__((here))</tt> or <tt>[[here]]</tt>. All such strings
will be synonymous. If you want to allow the <tt>[[]]</tt> C++0x
syntax, you have to define a list of <tt>Namespaces</tt>, which will
let users write <tt>[[namespace:spelling]]</tt>. Using the empty
string for a namespace will allow users to write just the spelling
with no "<tt>:</tt>".</p>
<p><tt>Subjects</tt> restricts what kinds of AST node to which this attribute
can appertain (roughly, attach).</p>
<p><tt>Args</tt> names the arguments the attribute takes, in order. If
<tt>Args</tt> is <tt>[StringArgument&lt;"Arg1">, IntArgument&lt;"Arg2">]</tt>
then <tt>__attribute__((myattribute("Hello", 3)))</tt> will be a valid use.</p>
<h4>Boilerplate</h4>
<p>Add an element to the <tt>AttributeList::Kind</tt> enum in <a
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?view=markup">include/clang/Sema/AttributeList.h</a>
named <tt>AT_lower_with_underscores</tt>. That is, a CamelCased
<tt>AttributeName</tt> in <tt>Attr.td</tt> name should become
<tt>AT_attribute_name</tt>.</p>
<p>Add a case to the <tt>StringSwitch</tt> in <tt>AttributeList::getKind()</tt>
in <a
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?view=markup">lib/Sema/AttributeList.cpp</a>
for each spelling of your attribute. Less common attributes should come toward
the end of that list.</p>
<p>Write a new <tt>HandleYourAttr()</tt> function in <a
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?view=markup">lib/Sema/SemaDeclAttr.cpp</a>,
and add a case to the switch in <tt>ProcessNonInheritableDeclAttr()</tt> or
<tt>ProcessInheritableDeclAttr()</tt> forwarding to it.</p>
<p>If your attribute causes extra warnings to fire, define a <tt>DiagGroup</tt>
in <a
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?view=markup">include/clang/Basic/DiagnosticGroups.td</a>
named after the attribute's <tt>Spelling</tt> with "_"s replaced by "-"s. If
you're only defining one diagnostic, you can skip <tt>DiagnosticGroups.td</tt>
and use <tt>InGroup&lt;DiagGroup&lt;"your-attribute">></tt> directly in <a
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?view=markup">DiagnosticSemaKinds.td</a></p>
<h4>The meat of your attribute</h4>
<p>Find an appropriate place in Clang to do whatever your attribute needs to do.
Check for the attribute's presence using <tt>Decl::getAttr&lt;YourAttr>()</tt>.</p>
<p>Update the <a href="LanguageExtensions.html">Clang Language Extensions</a>
document to describe your new attribute.</p>
<!-- ======================================================================= -->
<h3 id="AddingExprStmt">How to add an expression or statement</h3>
<!-- ======================================================================= -->
<p>Expressions and statements are one of the most fundamental constructs within a
compiler, because they interact with many different parts of the AST,
semantic analysis, and IR generation. Therefore, adding a new
expression or statement kind into Clang requires some care. The following list
details the various places in Clang where an expression or statement needs to be
introduced, along with patterns to follow to ensure that the new
expression or statement works well across all of the C languages. We
focus on expressions, but statements are similar.</p>
<ol>
<li>Introduce parsing actions into the parser. Recursive-descent
parsing is mostly self-explanatory, but there are a few things that
are worth keeping in mind:
<ul>
<li>Keep as much source location information as possible! You'll
want it later to produce great diagnostics and support Clang's
various features that map between source code and the AST.</li>
<li>Write tests for all of the "bad" parsing cases, to make sure
your recovery is good. If you have matched delimiters (e.g.,
parentheses, square brackets, etc.), use
<tt>Parser::BalancedDelimiterTracker</tt> to give nice diagnostics when
things go wrong.</li>
</ul>
</li>
<li>Introduce semantic analysis actions into <tt>Sema</tt>. Semantic
analysis should always involve two functions: an <tt>ActOnXXX</tt>
function that will be called directly from the parser, and a
<tt>BuildXXX</tt> function that performs the actual semantic
analysis and will (eventually!) build the AST node. It's fairly
common for the <tt>ActOnCXX</tt> function to do very little (often
just some minor translation from the parser's representation to
<tt>Sema</tt>'s representation of the same thing), but the separation
is still important: C++ template instantiation, for example,
should always call the <tt>BuildXXX</tt> variant. Several notes on
semantic analysis before we get into construction of the AST:
<ul>
<li>Your expression probably involves some types and some
subexpressions. Make sure to fully check that those types, and the
types of those subexpressions, meet your expectations. Add
implicit conversions where necessary to make sure that all of the
types line up exactly the way you want them. Write extensive tests
to check that you're getting good diagnostics for mistakes and
that you can use various forms of subexpressions with your
expression.</li>
<li>When type-checking a type or subexpression, make sure to first
check whether the type is "dependent"
(<tt>Type::isDependentType()</tt>) or whether a subexpression is
type-dependent (<tt>Expr::isTypeDependent()</tt>). If any of these
return true, then you're inside a template and you can't do much
type-checking now. That's normal, and your AST node (when you get
there) will have to deal with this case. At this point, you can
write tests that use your expression within templates, but don't
try to instantiate the templates.</li>
<li>For each subexpression, be sure to call
<tt>Sema::CheckPlaceholderExpr()</tt> to deal with "weird"
expressions that don't behave well as subexpressions. Then,
determine whether you need to perform
lvalue-to-rvalue conversions
(<tt>Sema::DefaultLvalueConversion</tt>e) or
the usual unary conversions
(<tt>Sema::UsualUnaryConversions</tt>), for places where the
subexpression is producing a value you intend to use.</li>
<li>Your <tt>BuildXXX</tt> function will probably just return
<tt>ExprError()</tt> at this point, since you don't have an AST.
That's perfectly fine, and shouldn't impact your testing.</li>
</ul>
</li>
<li>Introduce an AST node for your new expression. This starts with
declaring the node in <tt>include/Basic/StmtNodes.td</tt> and
creating a new class for your expression in the appropriate
<tt>include/AST/Expr*.h</tt> header. It's best to look at the class
for a similar expression to get ideas, and there are some specific
things to watch for:
<ul>
<li>If you need to allocate memory, use the <tt>ASTContext</tt>
allocator to allocate memory. Never use raw <tt>malloc</tt> or
<tt>new</tt>, and never hold any resources in an AST node, because
the destructor of an AST node is never called.</li>
<li>Make sure that <tt>getSourceRange()</tt> covers the exact
source range of your expression. This is needed for diagnostics
and for IDE support.</li>
<li>Make sure that <tt>children()</tt> visits all of the
subexpressions. This is important for a number of features (e.g., IDE
support, C++ variadic templates). If you have sub-types, you'll
also need to visit those sub-types in the
<tt>RecursiveASTVisitor</tt>.</li>
<li>Add printing support (<tt>StmtPrinter.cpp</tt>) and dumping
support (<tt>StmtDumper.cpp</tt>) for your expression.</li>
<li>Add profiling support (<tt>StmtProfile.cpp</tt>) for your AST
node, noting the distinguishing (non-source location)
characteristics of an instance of your expression. Omitting this
step will lead to hard-to-diagnose failures regarding matching of
template declarations.</li>
</ul>
</li>
<li>Teach semantic analysis to build your AST node! At this point,
you can wire up your <tt>Sema::BuildXXX</tt> function to actually
create your AST. A few things to check at this point:
<ul>
<li>If your expression can construct a new C++ class or return a
new Objective-C object, be sure to update and then call
<tt>Sema::MaybeBindToTemporary</tt> for your just-created AST node
to be sure that the object gets properly destructed. An easy way
to test this is to return a C++ class with a private destructor:
semantic analysis should flag an error here with the attempt to
call the destructor.</li>
<li>Inspect the generated AST by printing it using <tt>clang -cc1
-ast-print</tt>, to make sure you're capturing all of the
important information about how the AST was written.</li>
<li>Inspect the generated AST under <tt>clang -cc1 -ast-dump</tt>
to verify that all of the types in the generated AST line up the
way you want them. Remember that clients of the AST should never
have to "think" to understand what's going on. For example, all
implicit conversions should show up explicitly in the AST.</li>
<li>Write tests that use your expression as a subexpression of
other, well-known expressions. Can you call a function using your
expression as an argument? Can you use the ternary operator?</li>
</ul>
</li>
<li>Teach code generation to create IR to your AST node. This step
is the first (and only) that requires knowledge of LLVM IR. There
are several things to keep in mind:
<ul>
<li>Code generation is separated into scalar/aggregate/complex and
lvalue/rvalue paths, depending on what kind of result your
expression produces. On occasion, this requires some careful
factoring of code to avoid duplication.</li>
<li><tt>CodeGenFunction</tt> contains functions
<tt>ConvertType</tt> and <tt>ConvertTypeForMem</tt> that convert
Clang's types (<tt>clang::Type*</tt> or <tt>clang::QualType</tt>)
to LLVM types.
Use the former for values, and the later for memory locations:
test with the C++ "bool" type to check this. If you find
that you are having to use LLVM bitcasts to make
the subexpressions of your expression have the type that your
expression expects, STOP! Go fix semantic analysis and the AST so
that you don't need these bitcasts.</li>
<li>The <tt>CodeGenFunction</tt> class has a number of helper
functions to make certain operations easy, such as generating code
to produce an lvalue or an rvalue, or to initialize a memory
location with a given value. Prefer to use these functions rather
than directly writing loads and stores, because these functions
take care of some of the tricky details for you (e.g., for
exceptions).</li>
<li>If your expression requires some special behavior in the event
of an exception, look at the <tt>push*Cleanup</tt> functions in
<tt>CodeGenFunction</tt> to introduce a cleanup. You shouldn't
have to deal with exception-handling directly.</li>
<li>Testing is extremely important in IR generation. Use <tt>clang
-cc1 -emit-llvm</tt> and <a
href="http://llvm.org/cmds/FileCheck.html">FileCheck</a> to verify
that you're generating the right IR.</li>
</ul>
</li>
<li>Teach template instantiation how to cope with your AST
node, which requires some fairly simple code:
<ul>
<li>Make sure that your expression's constructor properly
computes the flags for type dependence (i.e., the type your
expression produces can change from one instantiation to the
next), value dependence (i.e., the constant value your expression
produces can change from one instantiation to the next),
instantiation dependence (i.e., a template parameter occurs
anywhere in your expression), and whether your expression contains
a parameter pack (for variadic templates). Often, computing these
flags just means combining the results from the various types and
subexpressions.</li>
<li>Add <tt>TransformXXX</tt> and <tt>RebuildXXX</tt> functions to
the
<tt>TreeTransform</tt> class template in <tt>Sema</tt>.
<tt>TransformXXX</tt> should (recursively) transform all of the
subexpressions and types
within your expression, using <tt>getDerived().TransformYYY</tt>.
If all of the subexpressions and types transform without error, it
will then call the <tt>RebuildXXX</tt> function, which will in
turn call <tt>getSema().BuildXXX</tt> to perform semantic analysis
and build your expression.</li>
<li>To test template instantiation, take those tests you wrote to
make sure that you were type checking with type-dependent
expressions and dependent types (from step #2) and instantiate
those templates with various types, some of which type-check and
some that don't, and test the error messages in each case.</li>
</ul>
</li>
<li>There are some "extras" that make other features work better.
It's worth handling these extras to give your expression complete
integration into Clang:
<ul>
<li>Add code completion support for your expression in
<tt>SemaCodeComplete.cpp</tt>.</li>
<li>If your expression has types in it, or has any "interesting"
features other than subexpressions, extend libclang's
<tt>CursorVisitor</tt> to provide proper visitation for your
expression, enabling various IDE features such as syntax
highlighting, cross-referencing, and so on. The
<tt>c-index-test</tt> helper program can be used to test these
features.</li>
</ul>
</li>
</ol>
</div>
</body>

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
#
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ..
LEVEL := ../../..
DIRS := tools
ifdef BUILD_FOR_WEBSITE
@@ -16,13 +16,13 @@ DOXYGEN = doxygen
$(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in
cat $< | sed \
-e 's/@abs_srcdir@/./g' \
-e 's/@abs_top_srcdir@/../g' \
-e 's/@DOT@/dot/g' \
-e 's/@PACKAGE_VERSION@/mainline/' \
-e 's/@abs_builddir@/./g' > $@
-e 's/@abs_top_builddir@/../g' > $@
endif
include $(CLANG_LEVEL)/Makefile
include $(LEVEL)/Makefile.common
HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) \
$(wildcard $(PROJ_SRC_DIR)/*.css)
@@ -59,7 +59,7 @@ $(PROJ_OBJ_DIR)/html.tar.gz: $(HTML)
$(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/html.tar
$(Verb) cd $(PROJ_SRC_DIR) && \
$(TAR) cf $(PROJ_OBJ_DIR)/html.tar *.html
$(Verb) $(GZIPBIN) $(PROJ_OBJ_DIR)/html.tar
$(Verb) $(GZIP) $(PROJ_OBJ_DIR)/html.tar
install-doxygen: doxygen
$(Echo) Installing doxygen documentation
@@ -82,7 +82,7 @@ $(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) $(GZIPBIN) $(PROJ_OBJ_DIR)/doxygen.tar
$(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

View File

@@ -144,15 +144,6 @@ 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">
@@ -218,27 +209,6 @@ 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
@@ -391,23 +361,23 @@ 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, in reverse order, prior to the expression
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(5)</code></td></tr>
<tr><td><code>IntegerLiteral(4)</code></td></tr>
<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 syntax tree node,
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

View File

@@ -32,20 +32,16 @@ td {
</li>
<li><a href="#general_features">Language and Target-Independent Features</a>
<ul>
<li><a href="#diagnostics">Controlling Errors and Warnings</a>
<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="#diagnostics_enable_everything">Enabling All Warnings</a></li>
<li><a href="#analyzer_diagnositics">Controlling Static Analyzer Diagnostics</a></li>
</ul>
</li>
<li><a href="#precompiledheaders">Precompiled Headers</a></li>
<li><a href="#codegen">Controlling Code Generation</a></li>
</ul>
</ul>
</li>
<li><a href="#c">C Language Features</a>
<ul>
@@ -56,6 +52,16 @@ td {
<li><a href="#c_ms">Microsoft extensions</a></li>
</ul>
</li>
<li><a href="#objc">Objective-C Language Features</a>
<ul>
<li><a href="#objc_incompatibilities">Intentional Incompatibilities with
GCC</a></li>
</ul>
</li>
<li><a href="#cxx">C++ Language Features</a>
</li>
<li><a href="#objcxx">Objective C++ Language Features</a>
</li>
<li><a href="#target_features">Target-Specific Features and Limitations</a>
<ul>
<li><a href="#target_arch">CPU Architectures Features and Limitations</a>
@@ -69,8 +75,8 @@ td {
<ul>
<li><a href="#target_os_darwin">Darwin (Mac OS/X)</a></li>
<li>Linux, etc.</li>
<li><a href="#target_os_win32">Windows</a></li>
</ul>
</li>
</ul>
</li>
@@ -183,12 +189,6 @@ introduces the language selection and other high level options like -c, -g, etc.
<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>
<!-- ================================================= -->
@@ -207,7 +207,7 @@ diagnostics that it generates.</p>
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:
print something like:</p>
<pre>
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
@@ -225,7 +225,7 @@ column number.</p>
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:
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]
@@ -242,7 +242,7 @@ when this is enabled, Clang will print something like:
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:
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]
@@ -250,65 +250,22 @@ when this is enabled, Clang will print something like:
^
//
</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>
<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>
<p>When this is disabled, Clang will just print:</p>
<pre>
test.c:2:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
#endif bad
^
//
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
</pre>
</dd>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<dt id="opt_fdiagnostics-format"><b>-fdiagnostics-format=clang/msvc/vi</b>:
Changes diagnostic output format to better match IDEs and command line tools.</dt>
<dd>This option controls the output format of the filename, line number, and column printed in diagnostic messages. The options, and their affect on formatting a simple conversion diagnostic, follow:
<dl>
<dt><b>clang</b> (default)</dt>
<dd>
<pre>t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int'</pre>
</dd>
<dt><b>msvc</b></dt>
<dd>
<pre>t.c(3,11) : warning: conversion specifies type 'char *' but the argument has type 'int'</pre>
</dd>
<dt><b>vi</b></dt>
<dd>
<pre>t.c +3:11: warning: conversion specifies type 'char *' but the argument has type 'int'</pre>
</dd>
</dl>
</dd>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<dt id="opt_fdiagnostics-show-name"><b>-f[no-]diagnostics-show-name</b>:
Enable the display of the diagnostic name.</dt>
<dd>This option, which defaults to off, controls whether or not
Clang prints the associated name.</dd>
<br>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<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:
a warning diagnostic. For example, in this output:</p>
<pre>
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
@@ -323,37 +280,13 @@ 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>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:
For example, in this output:</p>
<pre>
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
@@ -376,7 +309,7 @@ Print machine parsable information about source ranges.</dt>
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:
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')
@@ -387,25 +320,6 @@ exprs.c:47:15:{47:8-47:14}{47:17-47:24}: error: invalid operands to binary expre
<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 &quot;Gamma&quot;. 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
&quot;\\&quot;), tabs (as &quot;\t&quot;), newlines (as &quot;\n&quot;), double
quotes(as &quot;\&quot;&quot;) and non-printable characters (as octal
&quot;\xxx&quot;).</p>
</dd>
</dl>
@@ -426,7 +340,7 @@ quotes(as &quot;\&quot;&quot;) and non-printable characters (as octal
<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:
the end of preprocessor directives. For example:</p>
<pre>
test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
@@ -441,66 +355,6 @@ by commenting them out.</p>
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:
<pre>
template&lt;typename T> struct set{};
template&lt;typename T> struct trait { typedef const T& type; };
struct Value {
template&lt;typename T> void set(typename trait&lt;T>::type value) {}
};
void foo() {
Value v;
v.set&lt;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:
<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>
<!-- ======================================================================= -->
@@ -522,6 +376,7 @@ 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
@@ -529,15 +384,9 @@ it:</p>
<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 whether to print the diagnostic name [<a
href="#opt_fdiagnostics-show-name">-fdiagnostics-show-name</a>].</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>
@@ -547,41 +396,25 @@ it:</p>
<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>
</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>
</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>
<h4 id="diagnostics_commandline">Controlling Diagnostics via Command Line Flags</h4>
<p>-W flags, -pedantic, etc</p>
@@ -600,7 +433,7 @@ example code will tell Clang or GCC to ignore the -Wall warnings:</p>
#pragma GCC diagnostic ignored "-Wall"
</pre>
<p>In addition to all of the functionality provided by GCC's pragma, Clang
<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>
@@ -627,52 +460,6 @@ 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="diagnostics_enable_everything">Enabling All Warnings</h4>
<p>In addition to the traditional <tt>-W</tt> flags, one can enable <b>all</b>
warnings by passing <tt>-Weverything</tt>.
This works as expected with <tt>-Werror</tt>,
and also includes the warnings from <tt>-pedantic</tt>.</p>
<p>Note that when combined with <tt>-w</tt> (which disables all warnings), that
flag wins.</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 been 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 of which can already be done using <a
href="analyzer_annotations">annotations</a>).</li>
</ul>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<h3 id="precompiledheaders">Precompiled Headers</h3>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
@@ -687,7 +474,7 @@ 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
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>
@@ -783,16 +570,15 @@ likely to affect PCH files that reference a large number of headers.</p>
<p>Clang provides a number of ways to control code generation. The options are listed below.</p>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<dl>
<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 a check fails,
adds runtime checks for undefined runtime behavior. If the check fails,
<tt>__builtin_trap()</tt> is used to indicate failure.
The checks are:
<ul>
<li>Subscripting where the static type of one operand is a variable
<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
@@ -801,28 +587,15 @@ The checks are:
<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.
</ul>
</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 does not
operator will always return a pointer that do not
alias any other pointer when the function returns.</dd>
<dt id="opt_ftrap-function"><b>-ftrap-function=[name]</b>: Instruct code
generator to emit a function call to the specified function name for
<tt>__builtin_trap()</tt>.</dt>
<dd>LLVM code generator translates <tt>__builtin_trap()</tt> to a trap
instruction if it is supported by the target ISA. Otherwise, the builtin is
translated into a call to <tt>abort</tt>. If this option is set, then the code
generator will always lower the builtin to a call to the specified function
regardless of whether the target ISA has a trap instruction. This option is
useful for environments (e.g. deeply embedded) where a trap cannot be properly
handled, or when some custom behavior is desired.</dd>
</dl>
<!-- ======================================================================= -->
<h2 id="c">C Language Features</h2>
<!-- ======================================================================= -->
@@ -857,10 +630,6 @@ 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>
<li>Arrays that are VLA's according to the standard, but which can be constant
folded by the frontend are treated as fixed size arrays. This occurs for
things like "int X[(1, 2)];", which is technically a VLA. c* modes are
strictly compliant and treat these as VLAs.</li>
</ul>
<p>Differences between *89 and *99 modes:</p>
@@ -891,12 +660,31 @@ c94 mode (FIXME: And __STDC_VERSION__ should be defined!).</p>
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 attributes on function pointers
(<a href="http://llvm.org/bugs/show_bug.cgi?id=2461">bug 2461</a>). This is
a relatively important 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 #pragma align
(<a href="http://llvm.org/bugs/show_bug.cgi?id=3811">bug 3811</a>). This is a
relatively small feature, so it is likely to be implemented relatively
soon.</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
@@ -941,15 +729,20 @@ bug-reporting guidelines somewhere?).</p>
<ul>
<li>clang does not support the gcc extension that allows variable-length arrays
in structures. This is for a few reasons: one, it is tricky
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. Note that clang <em>does</em> support
flexible array members (arrays with a zero or unspecified size at the end of
a structure).</li>
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.</li>
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
@@ -971,13 +764,6 @@ support is incomplete; enabling Microsoft extensions will silently drop
certain constructs (including __declspec and Microsoft-style asm statements).
</p>
<ul>
<li>clang allows setting _MSC_VER with -fmsc-version=. It defaults to 1300 which
is the same as Visual C/C++ 2003. Any number is supported and can greatly affect
what Windows SDK and c++stdlib headers clang can compile. This option will be
removed when clang supports the full set of MS extensions required for these
headers.</li>
<li>clang does not support the Microsoft extension where anonymous
record members can be declared using user defined typedefs.</li>
@@ -985,7 +771,38 @@ record members can be declared using user defined typedefs.</li>
controlling record layout. GCC also contains support for this feature,
however where MSVC and GCC are incompatible clang follows the MSVC
definition.</li>
</ul>
<!-- ======================================================================= -->
<h2 id="objc">Objective-C Language Features</h2>
<!-- ======================================================================= -->
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<h3 id="objc_incompatibilities">Intentional Incompatibilities with GCC</h3>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<p>No cast of super, no lvalue casts.</p>
<!-- ======================================================================= -->
<h2 id="cxx">C++ Language Features</h2>
<!-- ======================================================================= -->
<p>At this point, Clang C++ is not production-quality and is not recommended for use beyond experimentation. However, Clang C++ support
is under active development and is progressing rapidly. Please see the <a
href="http://clang.llvm.org/cxx_status.html">C++ Status</a> page for details or
ask on the mailing list about how you can help.</p>
<p>Note that released Clang compilers will refuse to even try to use clang to compile C++ code unless you pass the <tt>-ccc-clang-cxx</tt> option to the driver. To turn on Clang's C++ support, please pass that flag. Clang compilers built from the Subversion trunk enable C++ support by default, and do not require the <tt>-ccc-clang-cxx</tt> flag.</p>
<!-- ======================================================================= -->
<h2 id="objcxx">Objective C++ Language Features</h2>
<!-- ======================================================================= -->
<p>At this point, Clang C++ support is not generally useful (and therefore,
neither is Objective-C++). Please see the <a href="#cxx">C++ section</a> for
more information.</p>
<!-- ======================================================================= -->
<h2 id="target_features">Target-Specific Features and Limitations</h2>
@@ -999,23 +816,16 @@ definition.</li>
<!-- ======================== -->
<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 many large C, C++, Objective-C, and Objective-C++ codebases.</p>
<p>On x86_64-mingw32, passing i128(by value) is incompatible to Microsoft x64
calling conversion. You might need to tweak WinX86_64ABIInfo::classify()
in lib/CodeGen/TargetInfo.cpp.</p>
<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>
<!-- ======================== -->
<p>The support for ARM (specifically ARMv6 and ARMv7) is considered stable on
Darwin (iOS): it has been tested to correctly compile many large C, C++,
Objective-C, and Objective-C++ codebases. Clang only supports a limited number
of ARM architectures. It does not yet fully support ARMv5, for example.</p>
ARM support is mostly feature-complete, but still experimental; it hasn't
undergone significant testing.
<!-- ======================== -->
<h4 id="target_arch_other">Other platforms</h4>
@@ -1024,6 +834,9 @@ 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.
@@ -1045,54 +858,6 @@ Generating assembly requires a suitable LLVM backend.
<p>No __thread support, 64-bit ObjC support requires SL tools.</p>
<!-- ======================================= -->
<h4 id="target_os_win32">Windows</h4>
<!-- ======================================= -->
<p>Experimental supports are on Cygming.</p>
<h5>Cygwin</h5>
<p>Clang works on Cygwin-1.7.</p>
<h5>MinGW32</h5>
<p>Clang works on some mingw32 distributions.
Clang assumes directories as below;</p>
<ul>
<li><tt>C:/mingw/include</tt></li>
<li><tt>C:/mingw/lib</tt></li>
<li><tt>C:/mingw/lib/gcc/mingw32/4.[3-5].0/include/c++</tt></li>
</ul>
<p>On MSYS, a few tests might fail. It is due to <a href="http://llvm.org/bugs/show_bug.cgi?id=8520">Bug 8520</a> and is fixed in <a href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20110314/118106.html">LLVM's r127724</a>.</p>
<h5>MinGW-w64</h5>
<p>For 32-bit (i686-w64-mingw32), and 64-bit (x86_64-w64-mingw32), Clang assumes as below;<p>
<ul>
<li><tt>GCC versions 4.5.0 to 4.5.3, 4.6.0 to 4.6.2, or 4.7.0 (for the C++ header search path)</tt></li>
<li><tt>some_directory/bin/gcc.exe</tt></li>
<li><tt>some_directory/bin/clang.exe</tt></li>
<li><tt>some_directory/bin/clang++.exe</tt></li>
<li><tt>some_directory/bin/../include/c++/GCC_version</tt></li>
<li><tt>some_directory/bin/../include/c++/GCC_version/x86_64-w64-mingw32</tt></li>
<li><tt>some_directory/bin/../include/c++/GCC_version/i686-w64-mingw32</tt></li>
<li><tt>some_directory/bin/../include/c++/GCC_version/backward</tt></li>
<li><tt>some_directory/bin/../x86_64-w64-mingw32/include</tt></li>
<li><tt>some_directory/bin/../i686-w64-mingw32/include</tt></li>
<li><tt>some_directory/bin/../include</tt></li>
</ul>
<p>This directory layout is standard for any toolchain you will find on the official <a href="mingw-w64.sourceforge.net">MinGW-w64 website</a>.
<p>Clang expects the GCC executable &quot;gcc.exe&quot; compiled for i686-w64-mingw32 (or x86_64-w64-mingw32) to be present on PATH.</p>
<p><a href="http://llvm.org/bugs/show_bug.cgi?id=9072">Some tests might fail</a>
on x86_64-w64-mingw32.</p>
</div>
</body>
</html>

1230
clang/docs/doxygen.cfg Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@ PROJECT_NUMBER = @PACKAGE_VERSION@
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = @abs_builddir@/doxygen
OUTPUT_DIRECTORY = @abs_top_builddir@/docs/doxygen
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@@ -39,7 +39,7 @@ OUTPUT_DIRECTORY = @abs_builddir@/doxygen
# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS = YES
CREATE_SUBDIRS = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
@@ -450,9 +450,9 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = @abs_srcdir@/../include \
@abs_srcdir@/../lib \
@abs_srcdir@/doxygen.intro
INPUT = @abs_top_srcdir@/include \
@abs_top_srcdir@/lib \
@abs_top_srcdir@/docs/doxygen.intro
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@@ -493,7 +493,7 @@ EXCLUDE_PATTERNS =
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = @abs_srcdir@/../examples
EXAMPLE_PATH = @abs_top_srcdir@/examples
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@@ -513,7 +513,7 @@ EXAMPLE_RECURSIVE = YES
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH = @abs_srcdir@/img
IMAGE_PATH = @abs_top_srcdir@/docs/img
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -636,13 +636,13 @@ HTML_FILE_EXTENSION = .html
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER = @abs_srcdir@/doxygen.header
HTML_HEADER = @abs_top_srcdir@/docs/doxygen.header
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER = @abs_srcdir@/doxygen.footer
HTML_FOOTER = @abs_top_srcdir@/docs/doxygen.footer
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
@@ -651,7 +651,7 @@ HTML_FOOTER = @abs_srcdir@/doxygen.footer
# the style sheet file to the HTML output directory, so don't put your own
# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET = @abs_srcdir@/doxygen.css
HTML_STYLESHEET = @abs_top_srcdir@/docs/doxygen.css
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to

View File

@@ -370,39 +370,9 @@ H2 {
H3 {
font-size: 100%;
}
H2, H3 {
border-bottom: 2px solid;
margin-top: 2em;
}
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 }
div.memitem {
border: 1px solid #999999;
margin-top: 1.0em;
margin-bottom: 1.0em;
-webkit-border-radius: 0.5em;
-webkit-box-shadow: 3px 3px 6px #777777;
-moz-border-radius: 0.5em;
-moz-box-shadow: black 3px 3px 3px;
}
div.memproto {
background-color: #E3E4E5;
padding: 0.25em 0.5em;
-webkit-border-top-left-radius: 0.5em;
-webkit-border-top-right-radius: 0.5em;
-moz-border-radius-topleft: 0.5em;
-moz-border-radius-topright: 0.5em;
}
div.memdoc {
padding-left: 1em;
padding-right: 1em;
}

4
clang/docs/index.html Normal file
View File

@@ -0,0 +1,4 @@
<title>'clang' C frontend documentation</title>
None yet, sorry :(

267
clang/docs/libIndex.html Normal file
View File

@@ -0,0 +1,267 @@
<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] &lt;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] &lt;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] &lt;t1.c:4:19, t1.c:4:19>
> [Decl: Function bar_func | Stmt: DeclRefExpr global_var] &lt;t2.c:6:3, t2.c:6:3>
> [Decl: Function bar_func | Stmt: DeclRefExpr global_var] &lt;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] &lt;t2.c:3:5, t2.c:3:18>
</pre>
</p>
</div>
</body>
</html>

View File

@@ -37,11 +37,10 @@ clean:
else
# Otherwise, if not in BUILD_FOR_WEBSITE mode, use the project info.
CLANG_LEVEL := ../..
include $(CLANG_LEVEL)/Makefile
LEVEL := ../../../..
include $(LEVEL)/Makefile.common
CLANG_VERSION := $(word 3,$(shell grep "CLANG_VERSION " \
$(PROJ_OBJ_DIR)/$(CLANG_LEVEL)/include/clang/Basic/Version.inc))
CLANG_VERSION := $(shell cat $(PROJ_SRC_DIR)/../../VER)
SRC_DOC_DIR=$(PROJ_SRC_DIR)/
DST_HTML_DIR=$(PROJ_OBJ_DIR)/

View File

@@ -2,24 +2,23 @@
=head1 NAME
clang - the Clang C, C++, and Objective-C compiler
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<-Oz>|B<-O3>|B<-O4>]
[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>
B<-stdlib=>I<library>
I<input-filenames>
=head1 DESCRIPTION
B<clang> is a C, C++, and Objective-C compiler which encompasses preprocessing,
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
@@ -38,8 +37,7 @@ the other tools.
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), ".ii" (for C++), ".mi" (for
Objective-C) , or ".mii" (for Objective-C++) file.
this stage is typically called a ".i" (for C) or ".mi" (for Objective-C) file.
=item B<Parsing and Semantic Analysis>
@@ -52,13 +50,10 @@ 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-specific 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.
IR") and ultimately to machine code (depending on the optimization level). 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.
=item B<Assembler>
@@ -80,7 +75,7 @@ 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
through code analysis. This tool uses many parts of Clang and is built into the
though code analysis. This tool uses many parts of Clang and is built into the
same driver.
@@ -132,11 +127,6 @@ Treat subsequent input files as having type I<language>.
Specify the language standard to compile for.
=item B<-stdlib>=I<language>
Specify the C++ standard library to use; supported options are libstdc++ and
libc++.
=item B<-ansi>
Same as B<-std=c89>.
@@ -175,14 +165,6 @@ Enable support for Pascal-style strings with "\pfoo".
Enable support for Microsoft extensions.
=item B<-fmsc-version=>
Set _MSC_VER. Defaults to 1300 on Windows. Not set otherwise.
=item B<-fborland-extensions>
Enable support for Borland extensions.
=item B<-fwritable-strings>
Make all string literals default to writable. This disables uniquing of
@@ -196,6 +178,7 @@ Allow loose type checking rules for implicit vector conversions.
Enable the "Blocks" language feature.
=item B<-fobjc-gc-only>
Indicate that Objective-C code should be compiled in GC-only mode, which only
@@ -206,22 +189,6 @@ works when Objective-C Garbage Collection is enabled.
Indicate that Objective-C code should be compiled in hybrid-GC mode, which works
with both GC and non-GC mode.
=item B<-fobjc-abi-version>=I<version>
Select the Objective-C ABI version to use. Available versions are 1 (legacy
"fragile" ABI), 2 (non-fragile ABI 1), and 3 (non-fragile ABI 2).
=item B<-fobjc-nonfragile-abi-version>=I<version>
Select the Objective-C non-fragile ABI version to use by default. This will only
be used as the Objective-C ABI when the non-fragile ABI is enabled (either via
-fobjc-nonfragile-abi, or because it is the platform default).
=item B<-fobjc-nonfragile-abi>
Enable use of the Objective-C non-fragile ABI. On platforms for which this is
the default ABI, it can be disabled with B<-fno-objc-nonfragile-abi>.
=back
@@ -263,13 +230,12 @@ may not exist on earlier ones.
=over
=item B<-O0> B<-O1> B<-O2> B<-Os> B<-Oz> B<-O3> B<-O4>
=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<-Oz> is like B<-Os>
(and thus B<-O2>), but reduces code size further. B<-O3> is like B<-O2>,
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
@@ -357,6 +323,10 @@ Pass I<arg> to the static analyzer.
Pass I<arg> to the assembler.
=item B<-Xclang> I<arg>
Pass I<arg> to the clang compiler.
=item B<-Xlinker> I<arg>
Pass I<arg> to the linker.
@@ -365,7 +335,7 @@ Pass I<arg> to the linker.
Pass I<arg> to the preprocessor.
=item B<-o> I<file>
=item B<-o> I<file>
Write output to I<file>.
@@ -389,12 +359,6 @@ Print the paths used for finding libraries and programs.
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.
@@ -418,7 +382,6 @@ Show commands to run and use verbose output.
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>
@@ -459,13 +422,7 @@ Add the specified directory to the search path for framework include files.
=item B<-nostdinc>
Do not search the standard system directories or compiler builtin directories
for include files.
=item B<-nostdlibinc>
Do not search the standard system directories for include files, but do search
compiler builting include directories.
Do not search the standard system directories for include files.
=item B<-nobuiltininc>
@@ -545,6 +502,7 @@ targets.
=head1 BUGS
Clang currently does not have C++ support, and this manual page is incomplete.
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.

View File

@@ -1,2 +1,4 @@
add_subdirectory(clang-interpreter)
add_subdirectory(PrintFunctionNames)
add_subdirectory(wpa)

View File

@@ -7,8 +7,8 @@
#
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ..
LEVEL = ../../..
PARALLEL_DIRS := clang-interpreter PrintFunctionNames
PARALLEL_DIRS := clang-interpreter PrintFunctionNames wpa
include $(CLANG_LEVEL)/Makefile
include $(LEVEL)/Makefile.common

View File

@@ -1,15 +1,26 @@
set(MODULE TRUE)
set(SHARED_LIBRARY TRUE)
set( LLVM_USED_LIBS
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
clangIndex
clangFrontend
clangDriver
clangSema
clangAnalysis
clangAST
)
clangParse
clangLex
clangBasic)
set( LLVM_LINK_COMPONENTS support mc)
set( LLVM_LINK_COMPONENTS
bitreader
mc
core
)
add_clang_library(PrintFunctionNames PrintFunctionNames.cpp)
set_target_properties(PrintFunctionNames
PROPERTIES
LINKER_LANGUAGE CXX
PREFIX "")
LINKER_LANGUAGE CXX)

View File

@@ -7,22 +7,21 @@
#
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ../..
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
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
LINK_LIBS_IN_SHARED = 0
# Include this here so we can get the configuration of the targets that have
# been configured for construction. We have to do this early so we can set up
# LINK_COMPONENTS before including Makefile.rules
include $(LEVEL)/Makefile.config
LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
include $(CLANG_LEVEL)/Makefile
LINK_COMPONENTS := bitreader mc core
USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
ifeq ($(OS),Darwin)
LDFLAGS=-Wl,-undefined,dynamic_lookup
endif
include $(LEVEL)/Makefile.common

View File

@@ -15,7 +15,6 @@
#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;
@@ -30,40 +29,16 @@ public:
llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
}
}
};
};
class PrintFunctionNamesAction : public PluginASTAction {
class PrintFunctionNamesAction : public ASTFrontendAction {
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") {
DiagnosticsEngine &D = CI.getDiagnostics();
unsigned DiagID = D.getCustomDiagID(
DiagnosticsEngine::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>
FrontendPluginRegistry::Add<PrintFunctionNamesAction>
X("print-fns", "print function names");

View File

@@ -1 +0,0 @@
_ZN4llvm8Registry*

View File

@@ -1,12 +1,10 @@
This is a simple example demonstrating how to use clang's facility for
providing AST consumers using a plugin.
Build the plugin by running `make` in this directory.
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:
--
Linux:
$ clang -cc1 -load ../../Debug+Asserts/lib/libPrintFunctionNames.so -plugin print-fns some-input-file.c
Mac:
$ clang -cc1 -load ../../Debug+Asserts/lib/libPrintFunctionNames.dylib -plugin print-fns some-input-file.c
$ clang -cc1 -load path/to/PrintFunctionNames.so -plugin print-fns some-input-file.c
--

View File

@@ -1,14 +0,0 @@
set(MODULE TRUE)
set( LLVM_USED_LIBS
clangStaticAnalyzerCore
)
set( LLVM_LINK_COMPONENTS support mc)
add_clang_library(SampleAnalyzerPlugin SampleAnalyzerPlugin)
set_target_properties(SampleAnalyzerPlugin
PROPERTIES
LINKER_LANGUAGE CXX
PREFIX "")

View File

@@ -1,52 +0,0 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
using namespace clang;
using namespace ento;
namespace {
class MainCallChecker : public Checker < check::PreStmt<CallExpr> > {
mutable llvm::OwningPtr<BugType> BT;
public:
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
};
} // end anonymous namespace
void MainCallChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee();
const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
if (!FD)
return;
// Get the name of the callee.
IdentifierInfo *II = FD->getIdentifier();
if (!II) // if no identifier, not a simple C function
return;
if (II->isStr("main")) {
ExplodedNode *N = C.generateSink();
if (!N)
return;
if (!BT)
BT.reset(new BugType("call to main", "example analyzer plugin"));
BugReport *report = new BugReport(*BT, BT->getName(), N);
report->addRange(Callee->getSourceRange());
C.EmitReport(report);
}
}
// Register plugin!
extern "C"
void clang_registerCheckers (CheckerRegistry &registry) {
registry.addChecker<MainCallChecker>("example.MainCallChecker", "Disallows calls to functions called main");
}
extern "C"
const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING;

View File

@@ -1,20 +0,0 @@
##===- examples/analyzer-plugin/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 = SampleAnalyzerPlugin
LINK_LIBS_IN_SHARED = 0
SHARED_LIBRARY = 1
include $(CLANG_LEVEL)/Makefile
ifeq ($(OS),Darwin)
LDFLAGS=-Wl,-undefined,dynamic_lookup
endif

View File

@@ -1,13 +1,11 @@
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
clangFrontend
clangSerialization
clangDriver
clangCodeGen
clangSema
clangStaticAnalyzerFrontend
clangStaticAnalyzerCheckers
clangStaticAnalyzerCore
clangIndex
clangChecker
clangAnalysis
clangRewrite
clangAST
@@ -20,10 +18,8 @@ set(LLVM_LINK_COMPONENTS
jit
interpreter
nativecodegen
asmparser
bitreader
bitwriter
codegen
ipo
selectiondag
)

View File

@@ -7,19 +7,24 @@
#
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ../..
LEVEL = ../../../..
TOOLNAME = clang-interpreter
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
NO_INSTALL = 1
# No plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \
selectiondag asmparser instrumentation
USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a clangCodeGen.a \
clangParse.a clangSema.a clangStaticAnalyzerFrontend.a \
clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \
clangAnalysis.a clangRewrite.a clangAST.a clangLex.a clangBasic.a
# Include this here so we can get the configuration of the targets that have
# been configured for construction. We have to do this early so we can set up
# LINK_COMPONENTS before including Makefile.rules
include $(LEVEL)/Makefile.config
include $(CLANG_LEVEL)/Makefile
LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \
selectiondag
USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangSema.a \
clangChecker.a clangAnalysis.a clangRewrite.a clangAST.a \
clangParse.a clangLex.a clangBasic.a
include $(LLVM_SRC_ROOT)/Makefile.rules

View File

@@ -7,36 +7,31 @@
//
//===----------------------------------------------------------------------===//
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/CodeGenAction.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/JIT.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
#include "llvm/Target/TargetSelect.h"
using namespace clang;
using namespace clang::driver;
// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// GetMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement GetMainExecutable
// without being given the address of a function in the main executable).
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.
@@ -44,7 +39,7 @@ llvm::sys::Path GetExecutablePath(const char *Argv0) {
return llvm::sys::Path::GetMainExecutable(Argv0, MainAddr);
}
static int Execute(llvm::Module *Mod, char * const *envp) {
int Execute(llvm::Module *Mod, char * const *envp) {
llvm::InitializeNativeTarget();
std::string Error;
@@ -71,12 +66,11 @@ static int Execute(llvm::Module *Mod, char * const *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());
TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
DiagnosticsEngine Diags(DiagID, DiagClient);
Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
Diagnostic Diags(&DiagClient);
Driver TheDriver(Path.getBasename(), Path.getDirname(),
llvm::sys::getHostTriple(),
"a.out", /*IsProduction=*/false, Diags);
TheDriver.setTitle("clang interpreter");
@@ -85,7 +79,8 @@ int main(int argc, const char **argv, char * const *envp) {
// (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));
llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(Args.size(),
Args.data()));
if (!C)
return 0;
@@ -94,7 +89,7 @@ int main(int argc, const char **argv, char * const *envp) {
// 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())) {
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);
@@ -111,10 +106,8 @@ int main(int argc, const char **argv, char * const *envp) {
// 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(),
CompilerInvocation::CreateFromArgs(*CI, (const char**) CCArgs.data(),
(const char**) CCArgs.data()+CCArgs.size(),
Diags);
// Show the invocation, with -v.
@@ -128,10 +121,11 @@ int main(int argc, const char **argv, char * const *envp) {
// 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()));
Clang.createDiagnostics(int(CCArgs.size()), (char**) CCArgs.data());
if (!Clang.hasDiagnostics())
return 1;

View File

@@ -1,14 +1,11 @@
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
clangIndex
clangFrontend
clangDriver
clangSema
clangAnalysis
clangSerialization
clangStaticAnalyzerFrontend
clangStaticAnalyzerCheckers
clangStaticAnalyzerCore
clangRewrite
clangAST
clangParse
clangLex

View File

@@ -7,20 +7,22 @@
#
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ../..
LEVEL = ../../../..
TOOLNAME = clang-wpa
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
NO_INSTALL = 1
# No plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
LINK_COMPONENTS := asmparser bitreader mc core
USEDLIBS = clangStaticAnalyzerFrontend.a \
clangStaticAnalyzerCheckers.a \
clangStaticAnalyzerCore.a \
clangIndex.a clangFrontend.a clangDriver.a \
clangParse.a clangSema.a clangAnalysis.a clangSerialization.a \
clangAST.a clangLex.a clangBasic.a
# Include this here so we can get the configuration of the targets that have
# been configured for construction. We have to do this early so we can set up
# LINK_COMPONENTS before including Makefile.rules
include $(LEVEL)/Makefile.config
include $(CLANG_LEVEL)/Makefile
LINK_COMPONENTS := bitreader mc core
USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(LLVM_SRC_ROOT)/Makefile.rules

View File

@@ -14,22 +14,9 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/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 "clang/Basic/TargetInfo.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -38,144 +25,32 @@ 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");
FileManager FileMgr;
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);
llvm::OwningPtr<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,
FileSystemOptions(),
false, 0, 0, true));
llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, *Diags));
if (!AST)
return 1;
ASTUnits.push_back(AST.take());
}
if (ViewCallGraph) {
llvm::OwningPtr<CallGraph> CG;
CG.reset(new CallGraph(Prog));
llvm::OwningPtr<CallGraph> CG;
CG.reset(new CallGraph());
for (unsigned i = 0, e = ASTUnits.size(); i != e; ++i)
CG->addTU(ASTUnits[i]->getASTContext());
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();
AnalyzerOptions Opts;
// Hard code options and checkers for now.
Opts.MaxNodes = 300000;
Opts.MaxLoop = 3;
Opts.InlineCall = true;
Opts.CFGAddImplicitDtors = true;
Opts.EagerlyTrimEGraph = true;
Opts.CheckersControlList.push_back(std::make_pair("core", true));
if (PP.getTargetInfo().getTriple().getOS() != llvm::Triple::Win32)
Opts.CheckersControlList.push_back(std::make_pair("unix", true));
if (PP.getTargetInfo().getTriple().getVendor() == llvm::Triple::Apple)
Opts.CheckersControlList.push_back(std::make_pair("macosx", true));
// Checks to perform for Objective-C/Objective-C++.
if (PP.getLangOptions().ObjC1)
Opts.CheckersControlList.push_back(std::make_pair("cocoa", true));
llvm::OwningPtr<ento::CheckerManager> checkerMgr;
checkerMgr.reset(ento::registerCheckers(Opts, PP.getLangOptions(),
PP.getDiagnostics()));
using namespace clang::ento;
AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(),
PP.getLangOptions(), /* PathDiagnostic */ 0,
CreateRegionStoreManager,
CreateRangeConstraintManager, checkerMgr.get(), &Idxer,
Opts.MaxNodes, Opts.MaxLoop,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.PurgeDead, Opts.EagerlyAssume,
Opts.TrimGraph, Opts.InlineCall,
Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
Opts.CFGAddInitializers,
Opts.EagerlyTrimEGraph);
TransferFuncs* TF = MakeCFRefCountTF(AMgr.getASTContext(), /*GC*/false,
AMgr.getLangOptions());
ExprEngine Eng(AMgr, TF);
Eng.ExecuteWorkList(AMgr.getStackFrame(FD, TU), AMgr.getMaxNodes());
return 0;
CG->ViewCallGraph();
}

View File

@@ -1,4 +1,4 @@
CLANG_LEVEL := ..
DIRS := clang clang-c
LEVEL = ../../..
DIRS := clang
include $(CLANG_LEVEL)/Makefile
include $(LEVEL)/Makefile.common

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -1,112 +0,0 @@
//===-- ARCMT.h - ARC Migration Rewriter ------------------------*- 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_ARCMIGRATE_ARCMT_H
#define LLVM_CLANG_ARCMIGRATE_ARCMT_H
#include "clang/ARCMigrate/FileRemapper.h"
#include "clang/Frontend/CompilerInvocation.h"
namespace clang {
class ASTContext;
class DiagnosticConsumer;
namespace arcmt {
class MigrationPass;
/// \brief Creates an AST with the provided CompilerInvocation but with these
/// changes:
/// -if a PCH/PTH is set, the original header is used instead
/// -Automatic Reference Counting mode is enabled
///
/// It then checks the AST and produces errors/warning for ARC migration issues
/// that the user needs to handle manually.
///
/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
/// even if the migrator can fix them, but the function will still return false
/// if all ARC errors can be fixed.
///
/// \param plistOut if non-empty, it is the file path to store the plist with
/// the pre-migration ARC diagnostics.
///
/// \returns false if no error is produced, true otherwise.
bool checkForManualIssues(CompilerInvocation &CI,
StringRef Filename, InputKind Kind,
DiagnosticConsumer *DiagClient,
bool emitPremigrationARCErrors = false,
StringRef plistOut = StringRef());
/// \brief Works similar to checkForManualIssues but instead of checking, it
/// applies automatic modifications to source files to conform to ARC.
///
/// \returns false if no error is produced, true otherwise.
bool applyTransformations(CompilerInvocation &origCI,
StringRef Filename, InputKind Kind,
DiagnosticConsumer *DiagClient);
/// \brief Applies automatic modifications and produces temporary files
/// and metadata into the \arg outputDir path.
///
/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
/// even if the migrator can fix them, but the function will still return false
/// if all ARC errors can be fixed.
///
/// \param plistOut if non-empty, it is the file path to store the plist with
/// the pre-migration ARC diagnostics.
///
/// \returns false if no error is produced, true otherwise.
bool migrateWithTemporaryFiles(CompilerInvocation &origCI,
StringRef Filename, InputKind Kind,
DiagnosticConsumer *DiagClient,
StringRef outputDir,
bool emitPremigrationARCErrors,
StringRef plistOut);
/// \brief Get the set of file remappings from the \arg outputDir path that
/// migrateWithTemporaryFiles produced.
///
/// \returns false if no error is produced, true otherwise.
bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap,
StringRef outputDir,
DiagnosticConsumer *DiagClient);
typedef void (*TransformFn)(MigrationPass &pass);
std::vector<TransformFn> getAllTransformations();
class MigrationProcess {
CompilerInvocation OrigCI;
DiagnosticConsumer *DiagClient;
FileRemapper Remapper;
public:
MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient,
StringRef outputDir = StringRef());
class RewriteListener {
public:
virtual ~RewriteListener();
virtual void start(ASTContext &Ctx) { }
virtual void finish() { }
virtual void insert(SourceLocation loc, StringRef text) { }
virtual void remove(CharSourceRange range) { }
};
bool applyTransform(TransformFn trans, RewriteListener *listener = 0);
FileRemapper &getRemapper() { return Remapper; }
};
} // end namespace arcmt
} // end namespace clang
#endif

View File

@@ -1,51 +0,0 @@
//===--- ARCMTActions.h - ARC Migrate Tool Frontend Actions -----*- 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_ARCMIGRATE_ARCMT_ACTION_H
#define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H
#include "clang/Frontend/FrontendAction.h"
#include "llvm/ADT/OwningPtr.h"
namespace clang {
namespace arcmt {
class CheckAction : public WrapperFrontendAction {
protected:
virtual bool BeginInvocation(CompilerInstance &CI);
public:
CheckAction(FrontendAction *WrappedAction);
};
class ModifyAction : public WrapperFrontendAction {
protected:
virtual bool BeginInvocation(CompilerInstance &CI);
public:
ModifyAction(FrontendAction *WrappedAction);
};
class MigrateAction : public WrapperFrontendAction {
std::string MigrateDir;
std::string PlistOut;
bool EmitPremigrationARCErros;
protected:
virtual bool BeginInvocation(CompilerInstance &CI);
public:
MigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
StringRef plistOut,
bool emitPremigrationARCErrors);
};
}
}
#endif

View File

@@ -1,77 +0,0 @@
//===-- FileRemapper.h - File Remapping Helper ------------------*- 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_ARCMIGRATE_FILEREMAPPER_H
#define LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
class MemoryBuffer;
}
namespace clang {
class FileManager;
class FileEntry;
class DiagnosticsEngine;
class CompilerInvocation;
namespace arcmt {
class FileRemapper {
// FIXME: Reuse the same FileManager for multiple ASTContexts.
llvm::OwningPtr<FileManager> FileMgr;
typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target;
typedef llvm::DenseMap<const FileEntry *, Target> MappingsTy;
MappingsTy FromToMappings;
llvm::DenseMap<const FileEntry *, const FileEntry *> ToFromMappings;
public:
FileRemapper();
~FileRemapper();
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
bool ignoreIfFilesChanged);
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag);
bool overwriteOriginal(DiagnosticsEngine &Diag,
StringRef outputDir = StringRef());
void remap(StringRef filePath, llvm::MemoryBuffer *memBuf);
void remap(StringRef filePath, StringRef newPath);
void applyMappings(CompilerInvocation &CI) const;
void transferMappingsAndClear(CompilerInvocation &CI);
void clear(StringRef outputDir = StringRef());
private:
void remap(const FileEntry *file, llvm::MemoryBuffer *memBuf);
void remap(const FileEntry *file, const FileEntry *newfile);
const FileEntry *getOriginalFile(StringRef filePath);
void resetTarget(Target &targ);
bool report(const Twine &err, DiagnosticsEngine &Diag);
std::string getRemapInfoFile(StringRef outputDir);
};
} // end namespace arcmt
} // end namespace clang
#endif

View File

@@ -14,13 +14,11 @@
#ifndef LLVM_CLANG_AST_APVALUE_H
#define LLVM_CLANG_AST_APVALUE_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/APFloat.h"
namespace clang {
class CharUnits;
class DiagnosticBuilder;
class Expr;
/// APValue - This class implements a discriminated union of [uninitialized]
@@ -87,10 +85,10 @@ public:
APValue(const APValue &RHS) : Kind(Uninitialized) {
*this = RHS;
}
APValue(const Expr* B, const CharUnits &O) : Kind(Uninitialized) {
APValue(Expr* B, const CharUnits &O) : Kind(Uninitialized) {
MakeLValue(); setLValue(B, O);
}
APValue(const Expr* B);
APValue(Expr* B);
~APValue() {
MakeUninit();
@@ -105,7 +103,7 @@ public:
bool isLValue() const { return Kind == LValue; }
bool isVector() const { return Kind == Vector; }
void print(raw_ostream &OS) const;
void print(llvm::raw_ostream &OS) const;
void dump() const;
APSInt &getInt() {
@@ -124,17 +122,13 @@ public:
return const_cast<APValue*>(this)->getFloat();
}
APValue &getVectorElt(unsigned i) {
APValue &getVectorElt(unsigned i) const {
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;
return ((Vec*)(void *)Data)->NumElts;
}
APSInt &getComplexIntReal() {
@@ -169,7 +163,7 @@ public:
return const_cast<APValue*>(this)->getComplexFloatImag();
}
const Expr* getLValueBase() const;
Expr* getLValueBase() const;
CharUnits getLValueOffset() const;
void setInt(const APSInt &I) {
@@ -201,7 +195,7 @@ public:
((ComplexAPFloat*)(char*)Data)->Real = R;
((ComplexAPFloat*)(char*)Data)->Imag = I;
}
void setLValue(const Expr *B, const CharUnits &O);
void setLValue(Expr *B, const CharUnits &O);
const APValue &operator=(const APValue &RHS);
@@ -235,15 +229,11 @@ private:
void MakeLValue();
};
inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) {
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
V.print(OS);
return OS;
}
// Writes a concise representation of V to DB, in a single << operation.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const APValue &V);
} // end namespace clang.
#endif

View File

@@ -16,13 +16,10 @@
namespace clang {
class ASTContext;
class CXXRecordDecl;
class DeclGroupRef;
class HandleTagDeclDefinition;
class ASTMutationListener;
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
class TagDecl;
class HandleTagDeclDefinition;
class SemaConsumer; // layering violation required for safe SemaConsumer
class VarDecl;
/// ASTConsumer - This is an abstract interface that should be implemented by
@@ -50,11 +47,6 @@ public:
/// 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) {}
@@ -76,26 +68,6 @@ public:
/// 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 getting modified after
/// their initial creation, it should return a pointer to
/// an ASTMutationListener here.
virtual ASTMutationListener *GetASTMutationListener() { return 0; }
/// \brief If the consumer is interested in entities being deserialized from
/// AST files, it should return a pointer to a ASTDeserializationListener here
virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; }
/// PrintStats - If desired, print any statistics.
virtual void PrintStats() {}

File diff suppressed because it is too large Load Diff

View File

@@ -15,8 +15,7 @@
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.inc"
#undef DIAG
@@ -24,27 +23,25 @@ namespace clang {
};
} // end namespace diag
/// \brief DiagnosticsEngine argument formatting function for diagnostics that
/// \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 DiagnosticsEngine::SetArgToStringFn(), where the cookie is an \c
/// ASTContext pointer.
void FormatASTNodeDiagnosticArgument(
DiagnosticsEngine::ArgumentKind Kind,
intptr_t Val,
const char *Modifier,
unsigned ModLen,
const char *Argument,
unsigned ArgLen,
const DiagnosticsEngine::ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
SmallVectorImpl<char> &Output,
void *Cookie,
SmallVectorImpl<intptr_t> &QualTypeVals);
/// \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

View File

@@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclarationName.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@@ -25,7 +25,7 @@ namespace clang {
class ASTContext;
class Decl;
class DeclContext;
class DiagnosticsEngine;
class Diagnostic;
class Expr;
class FileManager;
class IdentifierInfo;
@@ -45,13 +45,13 @@ namespace clang {
/// \brief The file managers we're importing to and from.
FileManager &ToFileManager, &FromFileManager;
/// \brief Whether to perform a minimal import.
bool Minimal;
/// \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<const Type *, const Type *> ImportedTypes;
llvm::DenseMap<Type *, Type *> ImportedTypes;
/// \brief Mapping from the already-imported declarations in the "from"
/// context to the corresponding declarations in the "to" context.
@@ -63,40 +63,23 @@ namespace clang {
/// \brief Mapping from the already-imported FileIDs in the "from" source
/// manager to the corresponding FileIDs in the "to" source manager.
llvm::DenseMap<FileID, FileID> ImportedFileIDs;
llvm::DenseMap<unsigned, FileID> ImportedFileIDs;
/// \brief Imported, anonymous tag declarations that are missing their
/// corresponding typedefs.
SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
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:
/// \brief Create a new AST importer.
///
/// \param ToContext The context we'll be importing into.
///
/// \param ToFileManager The file manager we'll be importing into.
///
/// \param FromContext The context we'll be importing from.
///
/// \param FromFileManager The file manager we'll be importing into.
///
/// \param MinimalImport If true, the importer will attempt to import
/// as little as it can, e.g., by importing declarations as forward
/// declarations that can be completed at a later point.
ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport);
ASTImporter(Diagnostic &Diags,
ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager);
virtual ~ASTImporter();
/// \brief Whether the importer will perform a minimal import, creating
/// to-be-completed forward declarations when possible.
bool isMinimalImport() const { return Minimal; }
/// \brief Import the given type from the "from" context into the "to"
/// context.
///
@@ -145,17 +128,6 @@ namespace clang {
/// \returns the equivalent nested-name-specifier in the "to"
/// context, or NULL if an error occurred.
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
/// \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.
NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS);
/// \brief Import the goven template name from the "from" context into the
/// "to" context.
TemplateName Import(TemplateName From);
/// \brief Import the given source location from the "from" context into
/// the "to" context.
@@ -182,7 +154,7 @@ namespace clang {
/// into the "to" context.
///
/// \returns the equivalent identifier in the "to" context.
IdentifierInfo *Import(const IdentifierInfo *FromId);
IdentifierInfo *Import(IdentifierInfo *FromId);
/// \brief Import the given Objective-C selector from the "from"
/// context into the "to" context.
@@ -197,12 +169,6 @@ namespace clang {
/// context.
FileID Import(FileID);
/// \brief Import the definition of the given declaration, including all of
/// the declarations it contains.
///
/// This routine is intended to be used
void ImportDefinition(Decl *From);
/// \brief Cope with a name conflict when importing a declaration into the
/// given context.
///
@@ -246,6 +212,9 @@ namespace clang {
/// \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);
@@ -259,13 +228,12 @@ namespace clang {
/// \brief Note that we have imported the "from" declaration by mapping it
/// to the (potentially-newly-created) "to" declaration.
///
/// Subclasses can override this function to observe all of the \c From ->
/// \c To declaration mappings as they are imported.
virtual Decl *Imported(Decl *From, Decl *To);
/// \returns \p To
Decl *Imported(Decl *From, Decl *To);
/// \brief Determine whether the given types are structurally
/// equivalent.
bool IsStructurallyEquivalent(QualType From, QualType To);
bool IsStructurallyEquivalent(QualType From, QualType To);
};
}

View File

@@ -1,67 +0,0 @@
//===--- ASTMutationListener.h - AST Mutation Interface --------*- 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 ASTMutationListener interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
namespace clang {
class Decl;
class DeclContext;
class TagDecl;
class CXXRecordDecl;
class ClassTemplateDecl;
class ClassTemplateSpecializationDecl;
class FunctionDecl;
class FunctionTemplateDecl;
class ObjCCategoryDecl;
class ObjCInterfaceDecl;
/// \brief An abstract interface that should be implemented by listeners
/// that want to be notified when an AST entity gets modified after its
/// initial creation.
class ASTMutationListener {
public:
virtual ~ASTMutationListener();
/// \brief A new TagDecl definition was completed.
virtual void CompletedTagDefinition(const TagDecl *D) { }
/// \brief A new declaration with name has been added to a DeclContext.
virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {}
/// \brief An implicit member was added after the definition was completed.
virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {}
/// \brief A template specialization (or partial one) was added to the
/// template declaration.
virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
const ClassTemplateSpecializationDecl *D) {}
/// \brief A template specialization (or partial one) was added to the
/// template declaration.
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) {}
/// \brief An implicit member got a definition.
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
/// \brief A static data member was implicitly instantiated.
virtual void StaticDataMemberInstantiated(const VarDecl *D) {}
/// \brief A new objc category class was added for an interface.
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {}
};
} // end namespace clang
#endif

View File

@@ -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

View File

@@ -14,91 +14,144 @@
#ifndef LLVM_CLANG_AST_ATTR_H
#define LLVM_CLANG_AST_ATTR_H
#include "clang/Basic/LLVM.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.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, const clang::ASTContext &C,
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, const 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, const clang::ASTContext &C, size_t)
throw ();
void operator delete[](void *Ptr, const clang::ASTContext &C, size_t)
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
throw ();
namespace clang {
/// Attr - This represents one attribute.
class Attr {
private:
SourceRange Range;
unsigned AttrKind : 16;
public:
enum Kind {
Alias,
Aligned,
AlwaysInline,
AnalyzerNoReturn, // Clang-specific.
Annotate,
AsmLabel, // Represent GCC asm label extension.
BaseCheck,
Blocks,
CDecl,
Cleanup,
Const,
Constructor,
Deprecated,
Destructor,
FastCall,
Final,
Format,
FormatArg,
GNUInline,
Hiding,
IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro.
IBActionKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro.
Malloc,
NoDebug,
NoInline,
NonNull,
NoReturn,
NoThrow,
ObjCException,
ObjCNSObject,
Override,
CFReturnsRetained, // Clang/Checker-specific.
CFReturnsNotRetained, // Clang/Checker-specific.
NSReturnsRetained, // Clang/Checker-specific.
NSReturnsNotRetained, // Clang/Checker-specific.
Overloadable, // Clang-specific
Packed,
PragmaPack,
Pure,
Regparm,
ReqdWorkGroupSize, // OpenCL-specific
Section,
Sentinel,
StdCall,
TransparentUnion,
Unavailable,
Unused,
Used,
Visibility,
WarnUnusedResult,
Weak,
WeakImport,
WeakRef,
protected:
FIRST_TARGET_ATTRIBUTE,
DLLExport,
DLLImport,
MSP430Interrupt,
X86ForceAlignArgPointer
};
private:
Attr *Next;
Kind AttrKind;
bool Inherited : 1;
virtual ~Attr();
protected:
void* operator new(size_t bytes) throw() {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
assert(0 && "Attrs cannot be allocated with regular 'new'.");
return 0;
}
void operator delete(void* data) throw() {
llvm_unreachable("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);
assert(0 && "Attrs cannot be released with regular 'delete'.");
}
protected:
Attr(attr::Kind AK, SourceRange R)
: Range(R), AttrKind(AK), Inherited(false) {}
Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
virtual ~Attr() {
assert(Next == 0 && "Destroy didn't work");
}
public:
virtual void Destroy(ASTContext &C);
attr::Kind getKind() const {
return static_cast<attr::Kind>(AttrKind);
/// \brief Whether this attribute should be merged to new
/// declarations.
virtual bool isMerged() const { return true; }
Kind getKind() const { return AttrKind; }
Attr *getNext() { return Next; }
const Attr *getNext() const { return Next; }
void setNext(Attr *next) { Next = next; }
template<typename T> const T *getNext() const {
for (const Attr *attr = getNext(); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
}
SourceLocation getLocation() const { return Range.getBegin(); }
SourceRange getRange() const { return Range; }
void setRange(SourceRange R) { Range = R; }
bool isInherited() const { return Inherited; }
void setInherited(bool value) { Inherited = value; }
void addAttr(Attr *attr) {
assert((attr != 0) && "addAttr(): attr is null");
// FIXME: This doesn't preserve the order in any way.
attr->Next = Next;
Next = attr;
}
// Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0;
@@ -106,142 +159,428 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *) { return true; }
};
class InheritableAttr : public Attr {
class AttrWithString : public Attr {
private:
const char *Str;
unsigned StrLen;
protected:
InheritableAttr(attr::Kind AK, SourceRange R)
: Attr(AK, R) {}
AttrWithString(Attr::Kind AK, ASTContext &C, llvm::StringRef s);
llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); }
void ReplaceString(ASTContext &C, llvm::StringRef newS);
public:
void setInherited(bool I) { Inherited = I; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() <= attr::LAST_INHERITABLE;
}
static bool classof(const InheritableAttr *) { return true; }
virtual void Destroy(ASTContext &C);
};
class InheritableParamAttr : public InheritableAttr {
protected:
InheritableParamAttr(attr::Kind AK, SourceRange R)
: InheritableAttr(AK, R) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() <= attr::LAST_INHERITABLE_PARAM;
}
static bool classof(const InheritableParamAttr *) { return true; }
};
#include "clang/AST/Attrs.inc"
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
typedef SmallVector<Attr*, 2> AttrVec;
typedef SmallVector<const Attr*, 2> ConstAttrVec;
/// DestroyAttrs - Destroy the contents of an AttrVec.
inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
#define DEF_SIMPLE_ATTR(ATTR) \
class ATTR##Attr : public Attr { \
public: \
ATTR##Attr() : Attr(ATTR) {} \
virtual Attr *clone(ASTContext &C) const; \
static bool classof(const Attr *A) { return A->getKind() == ATTR; } \
static bool classof(const ATTR##Attr *A) { return true; } \
}
/// 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;
DEF_SIMPLE_ATTR(Packed);
void AdvanceToNext() const {
while (!isa<SpecificAttr>(*Current))
++Current;
}
void AdvanceToNext(AttrVec::const_iterator I) const {
while (Current != I && !isa<SpecificAttr>(*Current))
++Current;
}
class PragmaPackAttr : public Attr {
unsigned Alignment;
public:
typedef SpecificAttr* value_type;
typedef SpecificAttr* reference;
typedef SpecificAttr* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
PragmaPackAttr(unsigned alignment) : Attr(PragmaPack), Alignment(alignment) {}
specific_attr_iterator() : Current() { }
explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
/// getAlignment - The specified alignment in bits.
unsigned getAlignment() const { return Alignment; }
reference operator*() const {
AdvanceToNext();
return cast<SpecificAttr>(*Current);
}
pointer operator->() const {
AdvanceToNext();
return cast<SpecificAttr>(*Current);
}
virtual Attr* clone(ASTContext &C) const;
specific_attr_iterator& operator++() {
++Current;
return *this;
}
specific_attr_iterator operator++(int) {
specific_attr_iterator Tmp(*this);
++(*this);
return Tmp;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == PragmaPack;
}
static bool classof(const PragmaPackAttr *A) { return true; }
};
friend bool operator==(specific_attr_iterator Left,
specific_attr_iterator Right) {
if (Left.Current < Right.Current)
Left.AdvanceToNext(Right.Current);
class AlignedAttr : public Attr {
unsigned Alignment;
public:
AlignedAttr(unsigned alignment)
: Attr(Aligned), Alignment(alignment) {}
/// getAlignment - The specified alignment in bits.
unsigned getAlignment() const { return Alignment; }
/// getMaxAlignment - Get the maximum alignment of attributes on this list.
unsigned getMaxAlignment() const {
const AlignedAttr *Next = getNext<AlignedAttr>();
if (Next)
return std::max(Next->getMaxAlignment(), Alignment);
else
Right.AdvanceToNext(Left.Current);
return Left.Current == Right.Current;
return Alignment;
}
friend bool operator!=(specific_attr_iterator Left,
specific_attr_iterator Right) {
return !(Left == Right);
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == Aligned;
}
static bool classof(const AlignedAttr *A) { return true; }
};
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());
}
class AnnotateAttr : public AttrWithString {
public:
AnnotateAttr(ASTContext &C, llvm::StringRef ann)
: AttrWithString(Annotate, C, ann) {}
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;
}
llvm::StringRef getAnnotation() const { return getString(); }
/// 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;
}
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == Annotate;
}
static bool classof(const AnnotateAttr *A) { return true; }
};
class AsmLabelAttr : public AttrWithString {
public:
AsmLabelAttr(ASTContext &C, llvm::StringRef L)
: AttrWithString(AsmLabel, C, L) {}
llvm::StringRef getLabel() const { return getString(); }
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == AsmLabel;
}
static bool classof(const AsmLabelAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(AlwaysInline);
class AliasAttr : public AttrWithString {
public:
AliasAttr(ASTContext &C, llvm::StringRef aliasee)
: AttrWithString(Alias, C, aliasee) {}
llvm::StringRef getAliasee() const { return getString(); }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Alias; }
static bool classof(const AliasAttr *A) { return true; }
};
class ConstructorAttr : public Attr {
int priority;
public:
ConstructorAttr(int p) : Attr(Constructor), priority(p) {}
int getPriority() const { return priority; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Constructor; }
static bool classof(const ConstructorAttr *A) { return true; }
};
class DestructorAttr : public Attr {
int priority;
public:
DestructorAttr(int p) : Attr(Destructor), priority(p) {}
int getPriority() const { return priority; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Destructor; }
static bool classof(const DestructorAttr *A) { return true; }
};
class IBOutletAttr : public Attr {
public:
IBOutletAttr() : Attr(IBOutletKind) {}
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == IBOutletKind;
}
static bool classof(const IBOutletAttr *A) { return true; }
};
class IBActionAttr : public Attr {
public:
IBActionAttr() : Attr(IBActionKind) {}
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == IBActionKind;
}
static bool classof(const IBActionAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(AnalyzerNoReturn);
DEF_SIMPLE_ATTR(Deprecated);
DEF_SIMPLE_ATTR(Final);
DEF_SIMPLE_ATTR(GNUInline);
DEF_SIMPLE_ATTR(Malloc);
DEF_SIMPLE_ATTR(NoReturn);
class SectionAttr : public AttrWithString {
public:
SectionAttr(ASTContext &C, llvm::StringRef N)
: AttrWithString(Section, C, N) {}
llvm::StringRef getName() const { return getString(); }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == Section;
}
static bool classof(const SectionAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(Unavailable);
DEF_SIMPLE_ATTR(Unused);
DEF_SIMPLE_ATTR(Used);
DEF_SIMPLE_ATTR(Weak);
DEF_SIMPLE_ATTR(WeakImport);
DEF_SIMPLE_ATTR(WeakRef);
DEF_SIMPLE_ATTR(NoThrow);
DEF_SIMPLE_ATTR(Const);
DEF_SIMPLE_ATTR(Pure);
class NonNullAttr : public Attr {
unsigned* ArgNums;
unsigned Size;
public:
NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0);
virtual void Destroy(ASTContext &C);
typedef const unsigned *iterator;
iterator begin() const { return ArgNums; }
iterator end() const { return ArgNums + Size; }
unsigned size() const { return Size; }
bool isNonNull(unsigned arg) const {
return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
}
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) { return A->getKind() == NonNull; }
static bool classof(const NonNullAttr *A) { return true; }
};
class FormatAttr : public AttrWithString {
int formatIdx, firstArg;
public:
FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first)
: AttrWithString(Format, C, type), formatIdx(idx), firstArg(first) {}
llvm::StringRef getType() const { return getString(); }
void setType(ASTContext &C, llvm::StringRef type);
int getFormatIdx() const { return formatIdx; }
int getFirstArg() const { return firstArg; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Format; }
static bool classof(const FormatAttr *A) { return true; }
};
class FormatArgAttr : public Attr {
int formatIdx;
public:
FormatArgAttr(int idx) : Attr(FormatArg), formatIdx(idx) {}
int getFormatIdx() const { return formatIdx; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == FormatArg; }
static bool classof(const FormatArgAttr *A) { return true; }
};
class SentinelAttr : public Attr {
int sentinel, NullPos;
public:
SentinelAttr(int sentinel_val, int nullPos) : Attr(Sentinel),
sentinel(sentinel_val), NullPos(nullPos) {}
int getSentinel() const { return sentinel; }
int getNullPos() const { return NullPos; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Sentinel; }
static bool classof(const SentinelAttr *A) { return true; }
};
class VisibilityAttr : public Attr {
public:
/// @brief An enumeration for the kinds of visibility of symbols.
enum VisibilityTypes {
DefaultVisibility = 0,
HiddenVisibility,
ProtectedVisibility
};
private:
VisibilityTypes VisibilityType;
public:
VisibilityAttr(VisibilityTypes v) : Attr(Visibility),
VisibilityType(v) {}
VisibilityTypes getVisibility() const { return VisibilityType; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Visibility; }
static bool classof(const VisibilityAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(FastCall);
DEF_SIMPLE_ATTR(StdCall);
DEF_SIMPLE_ATTR(CDecl);
DEF_SIMPLE_ATTR(TransparentUnion);
DEF_SIMPLE_ATTR(ObjCNSObject);
DEF_SIMPLE_ATTR(ObjCException);
class OverloadableAttr : public Attr {
public:
OverloadableAttr() : Attr(Overloadable) { }
virtual bool isMerged() const { return false; }
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) { return A->getKind() == Overloadable; }
static bool classof(const OverloadableAttr *) { return true; }
};
class BlocksAttr : public Attr {
public:
enum BlocksAttrTypes {
ByRef = 0
};
private:
BlocksAttrTypes BlocksAttrType;
public:
BlocksAttr(BlocksAttrTypes t) : Attr(Blocks), BlocksAttrType(t) {}
BlocksAttrTypes getType() const { return BlocksAttrType; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Blocks; }
static bool classof(const BlocksAttr *A) { return true; }
};
class FunctionDecl;
class CleanupAttr : public Attr {
FunctionDecl *FD;
public:
CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {}
const FunctionDecl *getFunctionDecl() const { return FD; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Cleanup; }
static bool classof(const CleanupAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(NoDebug);
DEF_SIMPLE_ATTR(WarnUnusedResult);
DEF_SIMPLE_ATTR(NoInline);
class RegparmAttr : public Attr {
unsigned NumParams;
public:
RegparmAttr(unsigned np) : Attr(Regparm), NumParams(np) {}
unsigned getNumParams() const { return NumParams; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Regparm; }
static bool classof(const RegparmAttr *A) { return true; }
};
class ReqdWorkGroupSizeAttr : public Attr {
unsigned X, Y, Z;
public:
ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z)
: Attr(ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {}
unsigned getXDim() const { return X; }
unsigned getYDim() const { return Y; }
unsigned getZDim() const { return Z; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == ReqdWorkGroupSize;
}
static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
};
// Checker-specific attributes.
DEF_SIMPLE_ATTR(CFReturnsNotRetained);
DEF_SIMPLE_ATTR(CFReturnsRetained);
DEF_SIMPLE_ATTR(NSReturnsNotRetained);
DEF_SIMPLE_ATTR(NSReturnsRetained);
// C++0x member checking attributes.
DEF_SIMPLE_ATTR(BaseCheck);
DEF_SIMPLE_ATTR(Hiding);
DEF_SIMPLE_ATTR(Override);
// Target-specific attributes
DEF_SIMPLE_ATTR(DLLImport);
DEF_SIMPLE_ATTR(DLLExport);
class MSP430InterruptAttr : public Attr {
unsigned Number;
public:
MSP430InterruptAttr(unsigned n) : Attr(MSP430Interrupt), Number(n) {}
unsigned getNumber() const { return Number; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == MSP430Interrupt; }
static bool classof(const MSP430InterruptAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(X86ForceAlignArgPointer);
#undef DEF_SIMPLE_ATTR
} // end namespace clang

View File

@@ -1,87 +0,0 @@
//===--- BaseSubobject.h - BaseSubobject class ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides a definition of the BaseSubobject class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_BASESUBOBJECT_H
#define LLVM_CLANG_AST_BASESUBOBJECT_H
#include "clang/AST/CharUnits.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/type_traits.h"
namespace clang {
class CXXRecordDecl;
// BaseSubobject - Uniquely identifies a direct or indirect base class.
// Stores both the base class decl and the offset from the most derived class to
// the base class. Used for vtable and VTT generation.
class BaseSubobject {
/// Base - The base class declaration.
const CXXRecordDecl *Base;
/// BaseOffset - The offset from the most derived class to the base class.
CharUnits BaseOffset;
public:
BaseSubobject() { }
BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
: Base(Base), BaseOffset(BaseOffset) { }
/// getBase - Returns the base class declaration.
const CXXRecordDecl *getBase() const { return Base; }
/// getBaseOffset - Returns the base class offset.
CharUnits getBaseOffset() const { return BaseOffset; }
friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) {
return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset;
}
};
} // end namespace clang
namespace llvm {
template<> struct DenseMapInfo<clang::BaseSubobject> {
static clang::BaseSubobject getEmptyKey() {
return clang::BaseSubobject(
DenseMapInfo<const clang::CXXRecordDecl *>::getEmptyKey(),
clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getEmptyKey()));
}
static clang::BaseSubobject getTombstoneKey() {
return clang::BaseSubobject(
DenseMapInfo<const clang::CXXRecordDecl *>::getTombstoneKey(),
clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getTombstoneKey()));
}
static unsigned getHashValue(const clang::BaseSubobject &Base) {
return
DenseMapInfo<const clang::CXXRecordDecl *>::getHashValue(Base.getBase()) ^
DenseMapInfo<int64_t>::getHashValue(Base.getBaseOffset().getQuantity());
}
static bool isEqual(const clang::BaseSubobject &LHS,
const clang::BaseSubobject &RHS) {
return LHS == RHS;
}
};
// It's OK to treat BaseSubobject as a POD type.
template <> struct isPodLike<clang::BaseSubobject> {
static const bool value = true;
};
}
#endif

View File

@@ -1,17 +0,0 @@
clang_tablegen(Attrs.inc -gen-clang-attr-classes
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
TARGET ClangAttrClasses)
clang_tablegen(AttrImpl.inc -gen-clang-attr-impl
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
TARGET ClangAttrImpl)
clang_tablegen(StmtNodes.inc -gen-clang-stmt-nodes
SOURCE ../Basic/StmtNodes.td
TARGET ClangStmtNodes)
clang_tablegen(DeclNodes.inc -gen-clang-decl-nodes
SOURCE ../Basic/DeclNodes.td
TARGET ClangDeclNodes)

View File

@@ -19,8 +19,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include <list>
#include <map>
@@ -66,7 +64,7 @@ struct 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 SmallVector<CXXBasePathElement, 4> {
class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
public:
CXXBasePath() : Access(AS_public) {}
@@ -80,14 +78,14 @@ public:
DeclContext::lookup_result Decls;
void clear() {
SmallVectorImpl<CXXBasePathElement>::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 hierarchy:
/// following class hierachy:
///
/// @code
/// class A { };
@@ -197,7 +195,7 @@ public:
/// \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);
bool isAmbiguous(QualType BaseType);
/// \brief Whether we are finding multiple paths to detect ambiguities.
bool isFindingAmbiguities() const { return FindAmbiguities; }
@@ -229,142 +227,7 @@ public:
/// 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, SmallVector<UniqueVirtualMethod, 4> >
Overrides;
public:
// Iterate over the set of subobjects that have overriding methods.
typedef llvm::DenseMap<unsigned, SmallVector<UniqueVirtualMethod, 4> >
::iterator iterator;
typedef llvm::DenseMap<unsigned, 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 SmallVector<UniqueVirtualMethod, 4>::iterator
overriding_iterator;
typedef 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> { };
/// \brief A set of all the primary bases for a class.
class CXXIndirectPrimaryBaseSet
: public llvm::SmallSet<const CXXRecordDecl*, 32> { };
} // end namespace clang
#endif

View File

@@ -66,16 +66,7 @@ public:
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type.
///
/// The underlying pointer must not be NULL.
const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type, or NULL.
///
const T *getTypePtrOrNull() const {
return cast_or_null<T>(Stored.getTypePtrOrNull());
}
T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
/// \brief Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
@@ -87,8 +78,6 @@ public:
return Stored.isNull();
}
SplitQualType split() const { return Stored.split(); }
/// \brief Retrieve a canonical type pointer with a different static type,
/// upcasting or downcasting as needed.
///
@@ -176,8 +165,6 @@ public:
// (dynamic) type.
static CanQual<T> CreateUnsafe(QualType Other);
void dump() const { Stored.dump(); }
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(getAsOpaquePtr());
}
@@ -227,7 +214,7 @@ protected:
public:
/// \brief Retrieve the pointer to the underlying Type
const T *getTypePtr() const { return Stored.getTypePtr(); }
T* getTypePtr() const { return Stored.getTypePtr(); }
/// \brief Implicit conversion to the underlying pointer.
///
@@ -236,7 +223,7 @@ public:
/// @code
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
/// @endcode
operator const T*() const { return this->Stored.getTypePtrOrNull(); }
operator const T*() const { return this->Stored.getTypePtr(); }
/// \brief Try to convert the given canonical type to a specific structural
/// type.
@@ -250,6 +237,7 @@ public:
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)
@@ -257,7 +245,6 @@ public:
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)
@@ -274,27 +261,18 @@ public:
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, isSignedIntegerOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl)
/// \brief Retrieve the proxy-adaptor type.
///
@@ -349,7 +327,7 @@ namespace llvm {
/// to return smart pointer (proxies?).
template<typename T>
struct simplify_type<const ::clang::CanQual<T> > {
typedef const T *SimpleType;
typedef T* SimpleType;
static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
return Val.getTypePtr();
}
@@ -584,21 +562,24 @@ struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
template<>
struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv)
};
template<>
struct CanProxyAdaptor<FunctionNoProtoType>
: public CanProxyBase<FunctionNoProtoType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv)
};
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(bool, getNoReturnAttr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)
CanQualType getArgType(unsigned i) const {
return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
@@ -632,14 +613,6 @@ struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
};
template <>
struct CanProxyAdaptor<UnaryTransformType>
: public CanProxyBase<UnaryTransformType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind)
};
template<>
struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
@@ -651,6 +624,7 @@ 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<>
@@ -665,26 +639,7 @@ struct CanProxyAdaptor<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(TemplateTypeParmDecl *, getDecl)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier)
};
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)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName)
};
template<>
@@ -724,9 +679,9 @@ inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
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!");
Result.Stored.setFromOpaqueValue(Ptr);
assert((!Result || Result.Stored.isCanonical())
&& "Type is not canonical!");
return Result;
}

View File

@@ -14,9 +14,7 @@
#ifndef LLVM_CLANG_AST_CHARUNITS_H
#define LLVM_CLANG_AST_CHARUNITS_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/System/DataTypes.h"
namespace clang {
@@ -34,7 +32,7 @@ namespace clang {
/// architectures where the two are the same size.
///
/// For portability, never assume that a target character is 8 bits wide. Use
/// CharUnit values wherever you calculate sizes, offsets, or alignments
/// CharUnit values whereever you calculate sizes, offsets, or alignments
/// in character units.
class CharUnits {
public:
@@ -70,24 +68,10 @@ namespace clang {
Quantity += Other.Quantity;
return *this;
}
CharUnits& operator++ () {
++Quantity;
return *this;
}
CharUnits operator++ (int) {
return CharUnits(Quantity++);
}
CharUnits& operator-= (const CharUnits &Other) {
Quantity -= Other.Quantity;
return *this;
}
CharUnits& operator-- () {
--Quantity;
return *this;
}
CharUnits operator-- (int) {
return CharUnits(Quantity--);
}
// Comparison operators.
bool operator== (const CharUnits &Other) const {
@@ -125,12 +109,6 @@ namespace clang {
/// isNegative - Test whether the quantity is less than zero.
bool isNegative() const { return Quantity < 0; }
/// isPowerOfTwo - Test whether the quantity is a power of two.
/// Zero is not a power of two.
bool isPowerOfTwo() const {
return (Quantity & -Quantity) == Quantity;
}
// Arithmetic operators.
CharUnits operator* (QuantityType N) const {
return CharUnits(Quantity * N);
@@ -153,24 +131,12 @@ namespace clang {
CharUnits operator- (const CharUnits &Other) const {
return CharUnits(Quantity - Other.Quantity);
}
CharUnits operator- () const {
return CharUnits(-Quantity);
}
// Conversions.
/// getQuantity - Get the raw integer representation of this quantity.
QuantityType getQuantity() const { return Quantity; }
/// RoundUpToAlignment - Returns the next integer (mod 2**64) that is
/// greater than or equal to this quantity and is a multiple of \arg
/// Align. Align must be non-zero.
CharUnits RoundUpToAlignment(const CharUnits &Align) {
return CharUnits(llvm::RoundUpToAlignment(Quantity,
Align.Quantity));
}
}; // class CharUnit
} // namespace clang
@@ -180,38 +146,4 @@ inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
return CU * Scale;
}
namespace llvm {
template<> struct DenseMapInfo<clang::CharUnits> {
static clang::CharUnits getEmptyKey() {
clang::CharUnits::QuantityType Quantity =
DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
return clang::CharUnits::fromQuantity(Quantity);
}
static clang::CharUnits getTombstoneKey() {
clang::CharUnits::QuantityType Quantity =
DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
return clang::CharUnits::fromQuantity(Quantity);
}
static unsigned getHashValue(const clang::CharUnits &CU) {
clang::CharUnits::QuantityType Quantity = CU.getQuantity();
return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
}
static bool isEqual(const clang::CharUnits &LHS,
const clang::CharUnits &RHS) {
return LHS == RHS;
}
};
template <> struct isPodLike<clang::CharUnits> {
static const bool value = true;
};
} // end namespace llvm
#endif // LLVM_CLANG_AST_CHARUNITS_H

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -41,9 +41,6 @@ class LinkageSpecDecl;
class BlockDecl;
class DeclarationName;
class CompoundStmt;
class StoredDeclsMap;
class DependentDiagnostic;
class ASTMutationListener;
}
namespace llvm {
@@ -62,15 +59,6 @@ public:
namespace clang {
/// \brief Captures the result of checking the availability of a
/// declaration.
enum AvailabilityResult {
AR_Available = 0,
AR_NotYetIntroduced,
AR_Deprecated,
AR_Unavailable
};
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
///
@@ -78,98 +66,39 @@ class Decl {
public:
/// \brief Lists the kind of concrete classes of Decl.
enum Kind {
#define DECL(DERIVED, BASE) DERIVED,
#define ABSTRACT_DECL(DECL)
#define DECL_RANGE(BASE, START, END) \
first##BASE = START, last##BASE = END,
#define LAST_DECL_RANGE(BASE, START, END) \
first##BASE = START, last##BASE = END
#include "clang/AST/DeclNodes.inc"
#define DECL(Derived, Base) Derived,
#define DECL_RANGE(CommonBase, Start, End) \
CommonBase##First = Start, CommonBase##Last = End,
#define LAST_DECL_RANGE(CommonBase, Start, End) \
CommonBase##First = Start, CommonBase##Last = End
#include "clang/AST/DeclNodes.def"
};
/// \brief A placeholder type used to construct an empty shell of a
/// decl-derived type that will be filled in later (e.g., by some
/// deserialization method).
struct EmptyShell { };
/// IdentifierNamespace - The different namespaces in which
/// declarations may appear. According to C99 6.2.3, there are
/// four namespaces, labels, tags, members and ordinary
/// identifiers. C++ describes lookup completely differently:
/// certain lookups merely "ignore" certain kinds of declarations,
/// usually based on whether the declaration is of a type, etc.
///
/// These are meant as bitmasks, so that searches in
/// C++ can look into the "tag" namespace during ordinary lookup.
///
/// Decl currently provides 15 bits of IDNS bits.
/// IdentifierNamespace - According to C99 6.2.3, there are four
/// namespaces, labels, tags, members and ordinary
/// identifiers. These are meant as bitmasks, so that searches in
/// C++ can look into the "tag" namespace during ordinary lookup. We
/// use additional namespaces for Objective-C entities. We also put
/// C++ friend declarations (of previously-undeclared entities) in
/// shadow namespaces, and 'using' declarations (as opposed to their
/// implicit shadow declarations) can be found in their own
/// namespace.
enum IdentifierNamespace {
/// Labels, declared with 'x:' and referenced with 'goto x'.
IDNS_Label = 0x0001,
/// Tags, declared with 'struct foo;' and referenced with
/// 'struct foo'. All tags are also types. This is what
/// elaborated-type-specifiers look for in C.
IDNS_Tag = 0x0002,
/// Types, declared with 'struct foo', typedefs, etc.
/// This is what elaborated-type-specifiers look for in C++,
/// but note that it's ill-formed to find a non-tag.
IDNS_Type = 0x0004,
/// Members, declared with object declarations within tag
/// definitions. In C, these can only be found by "qualified"
/// lookup in member expressions. In C++, they're found by
/// normal lookup.
IDNS_Member = 0x0008,
/// Namespaces, declared with 'namespace foo {}'.
/// Lookup for nested-name-specifiers find these.
IDNS_Namespace = 0x0010,
/// Ordinary names. In C, everything that's not a label, tag,
/// or member ends up here.
IDNS_Ordinary = 0x0020,
/// Objective C @protocol.
IDNS_ObjCProtocol = 0x0040,
/// This declaration is a friend function. A friend function
/// declaration is always in this namespace but may also be in
/// IDNS_Ordinary if it was previously declared.
IDNS_OrdinaryFriend = 0x0080,
/// This declaration is a friend class. A friend class
/// declaration is always in this namespace but may also be in
/// IDNS_Tag|IDNS_Type if it was previously declared.
IDNS_TagFriend = 0x0100,
/// This declaration is a using declaration. A using declaration
/// *introduces* a number of other declarations into the current
/// scope, and those declarations use the IDNS of their targets,
/// but the actual using declarations go in this namespace.
IDNS_Using = 0x0200,
/// This declaration is a C++ operator declared in a non-class
/// context. All such operators are also in IDNS_Ordinary.
/// C++ lexical operator lookup looks for these.
IDNS_NonMemberOperator = 0x0400
IDNS_Label = 0x1,
IDNS_Tag = 0x2,
IDNS_Member = 0x4,
IDNS_Ordinary = 0x8,
IDNS_ObjCProtocol = 0x10,
IDNS_ObjCImplementation = 0x20,
IDNS_ObjCCategoryName = 0x40,
IDNS_OrdinaryFriend = 0x80,
IDNS_TagFriend = 0x100,
IDNS_Using = 0x200
};
/// ObjCDeclQualifier - 'Qualifiers' written next to the return and
/// parameter types in method declarations. Other than remembering
/// them and mangling them into the method's signature string, these
/// are ignored by the compiler; they are consumed by certain
/// remote-messaging frameworks.
///
/// in, inout, and out are mutually exclusive and apply only to
/// method parameters. bycopy and byref are mutually exclusive and
/// apply only to method parameters (?). oneway applies only to
/// results. All of these expect their corresponding parameter to
/// have a particular type. None of this is currently enforced by
/// clang.
///
/// This should be kept in sync with ObjCDeclSpec::ObjCDeclQualifier.
/// ObjCDeclQualifier - Qualifier used on types in method declarations
/// for remote messaging. They are meant for the arguments though and
/// applied to the Decls (ObjCMethodDecl and ParmVarDecl).
enum ObjCDeclQualifier {
OBJC_TQ_None = 0x0,
OBJC_TQ_In = 0x1,
@@ -218,90 +147,55 @@ private:
return DeclCtx.get<DeclContext*>();
}
/// Loc - The location of this decl.
/// Loc - The location that this decl.
SourceLocation Loc;
/// DeclKind - This indicates which class this is.
unsigned DeclKind : 8;
Kind DeclKind : 8;
/// InvalidDecl - This indicates a semantic error occurred.
unsigned InvalidDecl : 1;
unsigned int InvalidDecl : 1;
/// HasAttrs - This indicates whether the decl has attributes or not.
unsigned HasAttrs : 1;
unsigned int HasAttrs : 1;
/// Implicit - Whether this declaration was implicitly generated by
/// the implementation rather than explicitly written by the user.
unsigned Implicit : 1;
bool Implicit : 1;
/// \brief Whether this declaration was "used", meaning that a definition is
/// required.
unsigned Used : 1;
bool Used : 1;
/// \brief Whether this declaration was "referenced".
/// The difference with 'Used' is whether the reference appears in a
/// evaluated context or not, e.g. functions used in uninstantiated templates
/// are regarded as "referenced" but not "used".
unsigned Referenced : 1;
protected:
/// Access - Used by C++ decls for the access specifier.
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
friend class CXXClassMemberWrapper;
/// \brief Whether this declaration was loaded from an AST file.
unsigned FromASTFile : 1;
/// ChangedAfterLoad - if this declaration has changed since being loaded
unsigned ChangedAfterLoad : 1;
/// \brief Whether this declaration is private to the module in which it was
/// defined.
unsigned ModulePrivate : 1;
// PCHLevel - the "level" of precompiled header/AST file from which this
// declaration was built.
unsigned PCHLevel : 2;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 12;
/// \brief Whether the \c CachedLinkage field is active.
///
/// This field is only valid for NamedDecls subclasses.
mutable unsigned HasCachedLinkage : 1;
/// \brief If \c HasCachedLinkage, the linkage of this declaration.
///
/// This field is only valid for NamedDecls subclasses.
mutable unsigned CachedLinkage : 2;
friend class ASTDeclWriter;
friend class ASTDeclReader;
unsigned IdentifierNamespace : 16;
private:
#ifndef NDEBUG
void CheckAccessDeclContext() const;
#else
void CheckAccessDeclContext() const { }
#endif
protected:
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), ChangedAfterLoad(false),
ModulePrivate(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
HasCachedLinkage(0)
{
if (Decl::CollectingStats()) add(DK);
}
Decl(Kind DK, EmptyShell Empty)
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), ChangedAfterLoad(false),
ModulePrivate(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
HasCachedLinkage(0)
{
if (Decl::CollectingStats()) add(DK);
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
virtual ~Decl();
@@ -318,7 +212,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
Kind getKind() const { return static_cast<Kind>(DeclKind); }
Kind getKind() const { return DeclKind; }
const char *getDeclKindName() const;
Decl *getNextDeclInContext() { return NextDeclInContext; }
@@ -333,13 +227,6 @@ public:
return const_cast<Decl*>(this)->getDeclContext();
}
/// Finds the innermost non-closure context of this declaration.
/// That is, walk out the DeclContext chain, skipping any blocks.
DeclContext *getNonClosureContext();
const DeclContext *getNonClosureContext() const {
return const_cast<Decl*>(this)->getNonClosureContext();
}
TranslationUnitDecl *getTranslationUnitDecl();
const TranslationUnitDecl *getTranslationUnitDecl() const {
return const_cast<Decl*>(this)->getTranslationUnitDecl();
@@ -351,82 +238,32 @@ public:
void setAccess(AccessSpecifier AS) {
Access = AS;
#ifndef NDEBUG
CheckAccessDeclContext();
#endif
}
AccessSpecifier getAccess() const {
#ifndef NDEBUG
CheckAccessDeclContext();
#endif
return AccessSpecifier(Access);
}
bool hasAttrs() const { return HasAttrs; }
void setAttrs(const AttrVec& Attrs);
AttrVec &getAttrs() {
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
void addAttr(Attr *attr);
const Attr *getAttrs() const {
if (!HasAttrs) return 0; // common case, no attributes.
return getAttrsImpl(); // Uncommon case, out of line hash lookup.
}
const AttrVec &getAttrs() const;
void swapAttrs(Decl *D);
void dropAttrs();
void invalidateAttrs();
void addAttr(Attr *A) {
if (hasAttrs())
getAttrs().push_back(A);
else
setAttrs(AttrVec(1, A));
template<typename T> const T *getAttr() const {
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
}
typedef AttrVec::const_iterator attr_iterator;
// FIXME: Do not rely on iterators having comparable singular values.
// Note that this should error out if they do not.
attr_iterator attr_begin() const {
return hasAttrs() ? getAttrs().begin() : 0;
}
attr_iterator attr_end() const {
return hasAttrs() ? getAttrs().end() : 0;
}
template <typename T>
void dropAttr() {
if (!HasAttrs) return;
AttrVec &Attrs = getAttrs();
for (unsigned i = 0, e = Attrs.size(); i != e; /* in loop */) {
if (isa<T>(Attrs[i])) {
Attrs.erase(Attrs.begin() + i);
--e;
}
else
++i;
}
if (Attrs.empty())
HasAttrs = false;
}
template <typename T>
specific_attr_iterator<T> specific_attr_begin() const {
return specific_attr_iterator<T>(attr_begin());
}
template <typename T>
specific_attr_iterator<T> specific_attr_end() const {
return specific_attr_iterator<T>(attr_end());
}
template<typename T> T *getAttr() const {
return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
}
template<typename T> bool hasAttr() const {
return hasAttrs() && hasSpecificAttr<T>(getAttrs());
}
/// getMaxAlignment - return the maximum alignment specified by attributes
/// on this decl, 0 if there are none.
unsigned getMaxAlignment() const {
return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0;
return getAttr<T>() != 0;
}
/// setInvalidDecl - Indicates the Decl had a semantic error. This
@@ -442,82 +279,30 @@ public:
/// \brief Whether this declaration was used, meaning that a definition
/// is required.
///
/// \param CheckUsedAttr When true, also consider the "used" attribute
/// (in addition to the "used" bit set by \c setUsed()) when determining
/// whether the function is used.
bool isUsed(bool CheckUsedAttr = true) const;
bool isUsed() const;
void setUsed(bool U = true) { Used = U; }
/// \brief Whether this declaration was referenced.
bool isReferenced() const;
void setReferenced(bool R = true) { Referenced = R; }
/// \brief Determine the availability of the given declaration.
/// \brief Retrieve the level of precompiled header from which this
/// declaration was generated.
///
/// This routine will determine the most restrictive availability of
/// the given declaration (e.g., preferring 'unavailable' to
/// 'deprecated').
///
/// \param Message If non-NULL and the result is not \c
/// AR_Available, will be set to a (possibly empty) message
/// describing why the declaration has not been introduced, is
/// deprecated, or is unavailable.
AvailabilityResult getAvailability(std::string *Message = 0) const;
/// The PCH level of a declaration describes where the declaration originated
/// from. A PCH level of 0 indicates that the declaration was not from a
/// precompiled header. A PCH level of 1 indicates that the declaration was
/// from a top-level precompiled header; 2 indicates that the declaration
/// comes from a precompiled header on which the top-level precompiled header
/// depends, and so on.
unsigned getPCHLevel() const { return PCHLevel; }
/// \brief Determine whether this declaration is marked 'deprecated'.
///
/// \param Message If non-NULL and the declaration is deprecated,
/// this will be set to the message describing why the declaration
/// was deprecated (which may be empty).
bool isDeprecated(std::string *Message = 0) const {
return getAvailability(Message) == AR_Deprecated;
}
/// \brief Determine whether this declaration is marked 'unavailable'.
///
/// \param Message If non-NULL and the declaration is unavailable,
/// this will be set to the message describing why the declaration
/// was made unavailable (which may be empty).
bool isUnavailable(std::string *Message = 0) const {
return getAvailability(Message) == AR_Unavailable;
}
/// \brief Determine whether this is a weak-imported symbol.
///
/// Weak-imported symbols are typically marked with the
/// 'weak_import' attribute, but may also be marked with an
/// 'availability' attribute where we're targing a platform prior to
/// the introduction of this feature.
bool isWeakImported() const;
/// \brief Determines whether this symbol can be weak-imported,
/// e.g., whether it would be well-formed to add the weak_import
/// attribute.
///
/// \param IsDefinition Set to \c true to indicate that this
/// declaration cannot be weak-imported because it has a definition.
bool canBeWeakImported(bool &IsDefinition) const;
/// \brief Determine whether this declaration came from an AST file (such as
/// a precompiled header or module) rather than having been parsed.
bool isFromASTFile() const { return FromASTFile; }
/// \brief The maximum PCH level that any declaration may have.
static const unsigned MaxPCHLevel = 3;
/// \brief Query whether this declaration was changed in a significant way
/// since being loaded from an AST file.
///
/// In an epic violation of layering, what is "significant" is entirely
/// up to the serialization system, but implemented in AST and Sema.
bool isChangedSinceDeserialization() const { return ChangedAfterLoad; }
/// \brief Mark this declaration as having changed since deserialization, or
/// reset the flag.
void setChangedSinceDeserialization(bool Changed) {
ChangedAfterLoad = Changed;
/// \brief Set the PCH level of this declaration.
void setPCHLevel(unsigned Level) {
assert(Level < MaxPCHLevel && "PCH level exceeds the maximum");
PCHLevel = Level;
}
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
@@ -526,13 +311,6 @@ public:
}
static unsigned getIdentifierNamespaceForKind(Kind DK);
bool hasTagIdentifierNamespace() const {
return isTagIdentifierNamespace(getIdentifierNamespace());
}
static bool isTagIdentifierNamespace(unsigned NS) {
// TagDecls have Tag and Type set and may also have TagFriend.
return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type);
}
/// getLexicalDeclContext - The declaration context where this Decl was
/// lexically declared (LexicalDC). May be different from
@@ -563,21 +341,11 @@ public:
void setLexicalDeclContext(DeclContext *DC);
/// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
/// scoped decl is defined outside the current function or method. This is
/// roughly global variables and functions, but also handles enums (which
/// could be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const {
return getParentFunctionOrMethod() == 0;
}
/// \brief If this decl is defined inside a function/method/block it returns
/// the corresponding DeclContext, otherwise it returns null.
const DeclContext *getParentFunctionOrMethod() const;
DeclContext *getParentFunctionOrMethod() {
return const_cast<DeclContext*>(
const_cast<const Decl*>(this)->getParentFunctionOrMethod());
}
// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
// scoped decl is defined outside the current function or method. This is
// roughly global variables and functions, but also handles enums (which could
// be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const;
/// \brief Retrieves the "canonical" declaration of the given declaration.
virtual Decl *getCanonicalDecl() { return this; }
@@ -650,16 +418,15 @@ public:
/// top-level Stmt* of that body. Otherwise this method returns null.
virtual Stmt* getBody() const { return 0; }
/// \brief Returns true if this Decl represents a declaration for a body of
/// code, such as a function or method definition.
virtual bool hasBody() const { return getBody() != 0; }
/// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt.
CompoundStmt* getCompoundBody() const;
/// getBodyRBrace - Gets the right brace of the body, if a body exists.
/// This works whether the body is a CompoundStmt or a CXXTryStmt.
SourceLocation getBodyRBrace() const;
// global temp stats (until we have a per-module visitor)
static void add(Kind k);
static void addDeclKind(Kind k);
static bool CollectingStats(bool Enable = false);
static void PrintStats();
@@ -671,12 +438,6 @@ public:
/// template parameter pack.
bool isTemplateParameterPack() const;
/// \brief Whether this declaration is a parameter pack.
bool isParameterPack() const;
/// \brief returns true if this declaration is a template
bool isTemplateDecl() const;
/// \brief Whether this declaration is a function or function template.
bool isFunctionOrFunctionTemplate() const;
@@ -689,23 +450,15 @@ public:
/// same entity may not (and probably don't) share this property.
void setObjectOfFriendDecl(bool PreviouslyDeclared) {
unsigned OldNS = IdentifierNamespace;
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
"namespace includes neither ordinary nor tag");
assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
"namespace includes other than ordinary or tag");
assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary ||
OldNS == (IDNS_Tag | IDNS_Ordinary))
&& "unsupported namespace for undeclared friend");
if (!PreviouslyDeclared) IdentifierNamespace = 0;
IdentifierNamespace = 0;
if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
if (OldNS == IDNS_Tag)
IdentifierNamespace |= IDNS_TagFriend;
if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
}
if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
else
IdentifierNamespace |= IDNS_OrdinaryFriend;
if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary;
}
}
enum FriendObjectKind {
@@ -726,36 +479,26 @@ public:
FOK_Declared : FOK_Undeclared);
}
/// Specifies that this declaration is a C++ overloaded non-member.
void setNonMemberOperator() {
assert(getKind() == Function || getKind() == FunctionTemplate);
assert((IdentifierNamespace & IDNS_Ordinary) &&
"visible non-member operators should be in ordinary namespace");
IdentifierNamespace |= IDNS_NonMemberOperator;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *) { return true; }
static bool classofKind(Kind K) { return true; }
static DeclContext *castToDeclContext(const Decl *);
static Decl *castFromDeclContext(const DeclContext *);
void print(raw_ostream &Out, unsigned Indentation = 0,
bool PrintInstantiation = false) const;
void print(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0, bool PrintInstantiation = false) const;
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const;
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
static void printGroup(Decl** Begin, unsigned NumDecls,
raw_ostream &Out, const PrintingPolicy &Policy,
llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
void dump() const;
void dumpXML() const;
void dumpXML(raw_ostream &OS) const;
private:
const Attr *getAttrsImpl() const;
protected:
ASTMutationListener *getASTMutationListener() const;
};
/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
@@ -770,32 +513,9 @@ public:
SourceManager &sm, const char *Msg)
: TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
virtual void print(raw_ostream &OS) const;
virtual void print(llvm::raw_ostream &OS) const;
};
class DeclContextLookupResult
: public std::pair<NamedDecl**,NamedDecl**> {
public:
DeclContextLookupResult(NamedDecl **I, NamedDecl **E)
: std::pair<NamedDecl**,NamedDecl**>(I, E) {}
DeclContextLookupResult()
: std::pair<NamedDecl**,NamedDecl**>() {}
using std::pair<NamedDecl**,NamedDecl**>::operator=;
};
class DeclContextLookupConstResult
: public std::pair<NamedDecl*const*, NamedDecl*const*> {
public:
DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R)
: std::pair<NamedDecl*const*, NamedDecl*const*>(R) {}
DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E)
: std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {}
DeclContextLookupConstResult()
: std::pair<NamedDecl*const*, NamedDecl*const*>() {}
using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=;
};
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are (only the top classes
@@ -812,24 +532,23 @@ public:
///
class DeclContext {
/// DeclKind - This indicates which class this is.
unsigned DeclKind : 8;
Decl::Kind DeclKind : 8;
/// \brief Whether this declaration context also has some external
/// storage that contains additional declarations that are lexically
/// part of this context.
mutable unsigned ExternalLexicalStorage : 1;
mutable bool ExternalLexicalStorage : 1;
/// \brief Whether this declaration context also has some external
/// storage that contains additional declarations that are visible
/// in this context.
mutable unsigned ExternalVisibleStorage : 1;
mutable bool ExternalVisibleStorage : 1;
/// \brief Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
/// dependent context).
mutable StoredDeclsMap *LookupPtr;
/// within this context, which is a DenseMap<DeclarationName,
/// StoredDeclsList>.
mutable void* LookupPtr;
protected:
/// FirstDecl - The first declaration stored within this declaration
/// context.
mutable Decl *FirstDecl;
@@ -840,24 +559,19 @@ protected:
/// another pointer.
mutable Decl *LastDecl;
friend class ExternalASTSource;
/// \brief Build up a chain of declarations.
///
/// \returns the first/last pair of declarations.
static std::pair<Decl *, Decl *>
BuildDeclChain(const SmallVectorImpl<Decl*> &Decls, bool FieldsAlreadyLoaded);
protected:
DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
LastDecl(0) { }
void DestroyDecls(ASTContext &C);
public:
~DeclContext();
Decl::Kind getDeclKind() const {
return static_cast<Decl::Kind>(DeclKind);
return DeclKind;
}
const char *getDeclKindName() const;
@@ -895,29 +609,13 @@ public:
return cast<Decl>(this)->getASTContext();
}
bool isClosure() const {
return DeclKind == Decl::Block;
}
bool isObjCContainer() const {
switch (DeclKind) {
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCImplementation:
case Decl::ObjCInterface:
case Decl::ObjCProtocol:
return true;
}
return false;
}
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Block:
case Decl::ObjCMethod:
return true;
default:
return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction;
return DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast;
}
}
@@ -930,15 +628,13 @@ public:
}
bool isRecord() const {
return DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord;
return DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast;
}
bool isNamespace() const {
return DeclKind == Decl::Namespace;
}
bool isInlineNamespace() const;
/// \brief Determines whether this context is dependent on a
/// template parameter.
bool isDependentContext() const;
@@ -957,22 +653,19 @@ public:
/// Here, E is a transparent context, so its enumerator (Val1) will
/// appear (semantically) that it is in the same context of E.
/// Examples of transparent contexts include: enumerations (except for
/// C++0x scoped enums), and C++ linkage specifications.
/// C++0x scoped enums), C++ linkage specifications, and C++0x
/// inline namespaces.
bool isTransparentContext() const;
/// \brief Determines whether this context is, or is nested within,
/// a C++ extern "C" linkage spec.
bool isExternCContext() const;
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
bool Equals(const DeclContext *DC) const {
return DC && this->getPrimaryContext() == DC->getPrimaryContext();
bool Equals(DeclContext *DC) {
return this->getPrimaryContext() == DC->getPrimaryContext();
}
/// \brief Determine whether this declaration context encloses the
/// declaration context DC.
bool Encloses(const DeclContext *DC) const;
bool Encloses(DeclContext *DC);
/// getPrimaryContext - There may be many different
/// declarations of the same entity (including forward declarations
@@ -981,16 +674,14 @@ public:
/// "primary" DeclContext structure, which will contain the
/// information needed to perform name lookup into this context.
DeclContext *getPrimaryContext();
const DeclContext *getPrimaryContext() const {
return const_cast<DeclContext*>(this)->getPrimaryContext();
}
/// getRedeclContext - Retrieve the context in which an entity conflicts with
/// other entities of the same name, or where it is a redeclaration if the
/// two entities are compatible. This skips through transparent contexts.
DeclContext *getRedeclContext();
const DeclContext *getRedeclContext() const {
return const_cast<DeclContext *>(this)->getRedeclContext();
/// getLookupContext - Retrieve the innermost non-transparent
/// context of this context, which corresponds to the innermost
/// location from which name lookup can find the entities in this
/// context.
DeclContext *getLookupContext();
const DeclContext *getLookupContext() const {
return const_cast<DeclContext *>(this)->getLookupContext();
}
/// \brief Retrieve the nearest enclosing namespace context.
@@ -999,14 +690,6 @@ public:
return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
}
/// \brief Test if this context is part of the enclosing namespace set of
/// the context NS, as defined in C++0x [namespace.def]p9. If either context
/// isn't a namespace, this is equivalent to Equals().
///
/// The enclosing namespace set of a namespace is the namespace and, if it is
/// inline, its enclosing namespace, recursively.
bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
/// getNextContext - If this is a DeclContext that may have other
/// DeclContexts that are semantically connected but syntactically
/// different, such as C++ namespaces, this routine retrieves the
@@ -1070,12 +753,6 @@ public:
decl_iterator decls_end() const;
bool decls_empty() const;
/// noload_decls_begin/end - Iterate over the declarations stored in this
/// context that are currently loaded; don't attempt to retrieve anything
/// from an external source.
decl_iterator noload_decls_begin() const;
decl_iterator noload_decls_end() const;
/// specific_decl_iterator - Iterates over a subrange of
/// declarations stored in a DeclContext, providing only those that
/// are of type SpecificDecl (or a class derived from it). This
@@ -1251,8 +928,9 @@ public:
/// access to the results of lookup up a name within this context.
typedef NamedDecl * const * lookup_const_iterator;
typedef DeclContextLookupResult lookup_result;
typedef DeclContextLookupConstResult lookup_const_result;
typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
typedef std::pair<lookup_const_iterator, lookup_const_iterator>
lookup_const_result;
/// lookup - Find the declarations (if any) with the given Name in
/// this context. Returns a range of iterators that contains all of
@@ -1262,15 +940,6 @@ public:
lookup_result lookup(DeclarationName Name);
lookup_const_result lookup(DeclarationName Name) const;
/// \brief A simplistic name lookup mechanism that performs name lookup
/// into this declaration context without consulting the external source.
///
/// This function should almost never be used, because it subverts the
/// usual relationship between a DeclContext and the external source.
/// See the ASTImporter for the (few, but important) use cases.
void localUncachedLookup(DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl *> &Results);
/// @brief Makes a declaration visible within this context.
///
/// This routine makes the declaration D visible to name lookup
@@ -1307,15 +976,10 @@ public:
return getUsingDirectives().second;
}
// These are all defined in DependentDiagnostic.h.
class ddiag_iterator;
inline ddiag_iterator ddiag_begin() const;
inline ddiag_iterator ddiag_end() const;
// Low-level accessors
/// \brief Retrieve the internal representation of the lookup structure.
StoredDeclsMap* getLookupPtr() const { return LookupPtr; }
void* getLookupPtr() const { return LookupPtr; }
/// \brief Whether this DeclContext has external storage containing
/// additional declarations that are lexically in this context.
@@ -1337,26 +1001,17 @@ public:
ExternalVisibleStorage = ES;
}
/// \brief Determine whether the given declaration is stored in the list of
/// declarations lexically within this context.
bool isDeclInLexicalTraversal(const Decl *D) const {
return D && (D->NextDeclInContext || D == FirstDecl || D == LastDecl);
}
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
#define DECL(NAME, BASE)
#define DECL_CONTEXT(NAME) \
static bool classof(const NAME##Decl *D) { return true; }
#include "clang/AST/DeclNodes.inc"
#define DECL_CONTEXT(Name) \
static bool classof(const Name##Decl *D) { return true; }
#include "clang/AST/DeclNodes.def"
void dumpDeclContext() const;
private:
void LoadLexicalDeclsFromExternalStorage() const;
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
void LoadVisibleDeclsFromExternalStorage() const;
void buildLookup(DeclContext *DCtx);
void makeDeclVisibleInContextImpl(NamedDecl *D);
@@ -1367,6 +1022,7 @@ inline bool Decl::isTemplateParameter() const {
getKind() == TemplateTemplateParm;
}
// Specialization selected when ToTy is not a known subclass of DeclContext.
template <class ToTy,
bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>
@@ -1398,12 +1054,17 @@ struct cast_convert_decl_context<ToTy, true> {
namespace llvm {
/// isa<T>(DeclContext*)
template <typename To>
struct isa_impl<To, ::clang::DeclContext> {
template<class ToTy>
struct isa_impl_wrap<ToTy,
const ::clang::DeclContext,const ::clang::DeclContext> {
static bool doit(const ::clang::DeclContext &Val) {
return To::classofKind(Val.getDeclKind());
return ToTy::classofKind(Val.getDeclKind());
}
};
template<class ToTy>
struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext>
: public isa_impl_wrap<ToTy,
const ::clang::DeclContext,const ::clang::DeclContext> {};
/// cast<T>(DeclContext*)
template<class ToTy>

File diff suppressed because it is too large Load Diff

View File

@@ -24,59 +24,111 @@
namespace clang {
class DependentDiagnostic;
/// StoredDeclsList - This is an array of decls optimized a common case of only
/// containing one entry.
struct StoredDeclsList {
/// The kind of data encoded in this list.
enum DataKind {
/// \brief The data is a NamedDecl*.
DK_Decl = 0,
/// \brief The data is a declaration ID (an unsigned value),
/// shifted left by 2 bits.
DK_DeclID = 1,
/// \brief The data is a pointer to a vector (of type VectorTy)
/// that contains declarations.
DK_Decl_Vector = 2,
/// \brief The data is a pointer to a vector (of type VectorTy)
/// that contains declaration ID.
DK_ID_Vector = 3
};
/// DeclsTy - When in vector form, this is what the Data pointer points to.
typedef SmallVector<NamedDecl *, 4> DeclsTy;
/// VectorTy - When in vector form, this is what the Data pointer points to.
typedef llvm::SmallVector<uintptr_t, 4> VectorTy;
/// \brief The stored data, which will be either a pointer to a NamedDecl,
/// or a pointer to a vector.
llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
/// \brief The stored data, which will be either a declaration ID, a
/// pointer to a NamedDecl, or a pointer to a vector.
uintptr_t Data;
public:
StoredDeclsList() {}
StoredDeclsList() : Data(0) {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
if (DeclsTy *RHSVec = RHS.getAsVector())
Data = new DeclsTy(*RHSVec);
if (VectorTy *RHSVec = RHS.getAsVector()) {
VectorTy *New = new VectorTy(*RHSVec);
Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
}
}
~StoredDeclsList() {
// If this is a vector-form, free the vector.
if (DeclsTy *Vector = getAsVector())
if (VectorTy *Vector = getAsVector())
delete Vector;
}
StoredDeclsList &operator=(const StoredDeclsList &RHS) {
if (DeclsTy *Vector = getAsVector())
if (VectorTy *Vector = getAsVector())
delete Vector;
Data = RHS.Data;
if (DeclsTy *RHSVec = RHS.getAsVector())
Data = new DeclsTy(*RHSVec);
if (VectorTy *RHSVec = RHS.getAsVector()) {
VectorTy *New = new VectorTy(*RHSVec);
Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
}
return *this;
}
bool isNull() const { return Data.isNull(); }
bool isNull() const { return (Data & ~0x03) == 0; }
NamedDecl *getAsDecl() const {
return Data.dyn_cast<NamedDecl *>();
if ((Data & 0x03) != DK_Decl)
return 0;
return reinterpret_cast<NamedDecl *>(Data & ~0x03);
}
DeclsTy *getAsVector() const {
return Data.dyn_cast<DeclsTy *>();
VectorTy *getAsVector() const {
if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector)
return 0;
return reinterpret_cast<VectorTy *>(Data & ~0x03);
}
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!");
Data = reinterpret_cast<uintptr_t>(ND);
}
void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) {
if (Vec.size() > 1) {
VectorTy *Vector = getAsVector();
if (!Vector) {
Vector = new VectorTy;
Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector;
}
Vector->resize(Vec.size());
std::copy(Vec.begin(), Vec.end(), Vector->begin());
return;
}
if (VectorTy *Vector = getAsVector())
delete Vector;
if (Vec.empty())
Data = 0;
else
Data = (Vec[0] << 2) | DK_DeclID;
}
/// \brief Force the stored declarations list to contain actual
/// declarations.
///
/// This routine will resolve any declaration IDs for declarations
/// that may not yet have been loaded from external storage.
void materializeDecls(ASTContext &Context);
bool hasDeclarationIDs() const {
DataKind DK = (DataKind)(Data & 0x03);
return DK == DK_DeclID || DK == DK_ID_Vector;
}
void remove(NamedDecl *D) {
@@ -84,25 +136,28 @@ public:
if (NamedDecl *Singleton = getAsDecl()) {
assert(Singleton == D && "list is different singleton");
(void)Singleton;
Data = (NamedDecl *)0;
Data = 0;
return;
}
DeclsTy &Vec = *getAsVector();
DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
VectorTy &Vec = *getAsVector();
VectorTy::iterator I = std::find(Vec.begin(), Vec.end(),
reinterpret_cast<uintptr_t>(D));
assert(I != Vec.end() && "list does not contain decl");
Vec.erase(I);
assert(std::find(Vec.begin(), Vec.end(), D)
assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D))
== Vec.end() && "list still contains decl");
}
/// getLookupResult - Return an array of all the decls that this list
/// represents.
DeclContext::lookup_result getLookupResult() {
DeclContext::lookup_result getLookupResult(ASTContext &Context) {
if (isNull())
return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
DeclContext::lookup_iterator(0));
return DeclContext::lookup_result(0, 0);
if (hasDeclarationIDs())
materializeDecls(Context);
// If we have a single NamedDecl, return it.
if (getAsDecl()) {
@@ -114,15 +169,19 @@ public:
}
assert(getAsVector() && "Must have a vector at this point");
DeclsTy &Vector = *getAsVector();
VectorTy &Vector = *getAsVector();
// Otherwise, we have a range result.
return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size());
return DeclContext::lookup_result((NamedDecl **)&Vector[0],
(NamedDecl **)&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) {
bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) {
if (hasDeclarationIDs())
materializeDecls(Context);
// Most decls only have one entry in their list, special case it.
if (NamedDecl *OldD = getAsDecl()) {
if (!D->declarationReplaces(OldD))
@@ -132,12 +191,12 @@ public:
}
// Determine if this declaration is actually a redeclaration.
DeclsTy &Vec = *getAsVector();
for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
VectorTy &Vec = *getAsVector();
for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
OD != ODEnd; ++OD) {
NamedDecl *OldD = *OD;
NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD);
if (D->declarationReplaces(OldD)) {
*OD = D;
*OD = reinterpret_cast<uintptr_t>(D);
return true;
}
}
@@ -149,15 +208,17 @@ public:
/// not a redeclaration to merge it into the appropriate place in our list.
///
void AddSubsequentDecl(NamedDecl *D) {
assert(!hasDeclarationIDs() && "Must materialize before adding decls");
// 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;
VectorTy *VT = new VectorTy();
VT->push_back(reinterpret_cast<uintptr_t>(OldD));
Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector;
}
DeclsTy &Vec = *getAsVector();
VectorTy &Vec = *getAsVector();
// Using directives end up in a special entry which contains only
// other using directives, so all this logic is wasted for them.
@@ -167,56 +228,38 @@ public:
// 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);
if (D->getIdentifierNamespace() == Decl::IDNS_Tag)
Vec.push_back(reinterpret_cast<uintptr_t>(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();
VectorTy::iterator I = Vec.begin();
if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
while (I != Vec.end() &&
(*I)->getIdentifierNamespace() == Decl::IDNS_Using)
reinterpret_cast<NamedDecl *>(*I)
->getIdentifierNamespace() == Decl::IDNS_Using)
++I;
}
Vec.insert(I, D);
Vec.insert(I, reinterpret_cast<uintptr_t>(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;
} else if (reinterpret_cast<NamedDecl *>(Vec.back())
->getIdentifierNamespace() == Decl::IDNS_Tag) {
uintptr_t TagD = Vec.back();
Vec.back() = reinterpret_cast<uintptr_t>(D);
Vec.push_back(TagD);
} else
Vec.push_back(D);
Vec.push_back(reinterpret_cast<uintptr_t>(D));
}
};
class StoredDeclsMap
: public llvm::DenseMap<DeclarationName, StoredDeclsList> {
typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
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

View File

@@ -1,196 +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.
LazyDeclPtr NextFriend;
// Location of the 'friend' specifier.
SourceLocation FriendLoc;
/// True if this 'friend' declaration is unsupported. Eventually we
/// will support every possible friend declaration, but for now we
/// silently ignore some and set this flag to authorize all access.
bool UnsupportedFriend;
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(),
FriendLoc(FriendL),
UnsupportedFriend(false) {
}
explicit FriendDecl(EmptyShell Empty)
: Decl(Decl::Friend, Empty), NextFriend() { }
FriendDecl *getNextFriend() {
return cast_or_null<FriendDecl>(
NextFriend.get(getASTContext().getExternalSource()));
}
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;
}
/// Retrieves the source range for the friend declaration.
SourceRange getSourceRange() const {
/* FIXME: consider the case of templates wrt start of range. */
if (NamedDecl *ND = getFriendDecl())
return SourceRange(getFriendLoc(), ND->getLocEnd());
else if (TypeSourceInfo *TInfo = getFriendType())
return SourceRange(getFriendLoc(), TInfo->getTypeLoc().getEndLoc());
else
return SourceRange(getFriendLoc(), getLocation());
}
/// Determines if this friend kind is unsupported.
bool isUnsupportedFriend() const {
return UnsupportedFriend;
}
void setUnsupportedFriend(bool Unsupported) {
UnsupportedFriend = Unsupported;
}
// 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->getNextFriend();
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

View File

@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
#include "llvm/Support/DataTypes.h"
#include "llvm/System/DataTypes.h"
#include <cassert>
namespace clang {
@@ -34,17 +34,18 @@ private:
public:
static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
void Destroy(ASTContext& C);
unsigned size() const { return NumDecls; }
Decl*& operator[](unsigned i) {
assert (i < NumDecls && "Out-of-bounds access.");
return ((Decl**) (this+1))[i];
return *((Decl**) (this+1));
}
Decl* const& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
return ((Decl* const*) (this+1))[i];
return *((Decl* const*) (this+1));
}
};

View File

@@ -0,0 +1,165 @@
//===-- DeclNodes.def - Metadata about Decl AST nodes -----------*- 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 declaration nodes within the AST. The
// description of the declaration nodes uses six macros:
//
// DECL(Derived, Base) describes a normal declaration type Derived
// and specifies its base class. Note that Derived should not have
// the Decl suffix on it, while Base should.
//
// LAST_DECL(Derived, Base) is like DECL, but is used for the last
// declaration in the list.
//
// ABSTRACT_DECL(Derived, Base) describes an abstract class that is
// used to specify a classification of declarations. For example,
// TagDecl is an abstract class used to describe the various kinds of
// "tag" declarations (unions, structs, classes, enums).
//
// DECL_CONTEXT(Decl) specifies that Decl is a kind of declaration
// that is also a DeclContext.
//
// LAST_DECL_CONTEXT(Decl) is like DECL_CONTEXT, but is used for the
// last declaration context.
//
// DECL_RANGE(CommonBase, Start, End) specifies a range of
// declaration values that have a common (potentially indirect) base
// class.
//
// LAST_DECL_RANGE(CommonBase, Start, End) is like DECL_RANGE, but is
// used for the last declaration range.
//
// Note that, due to the use of ranges, the order of the these
// declarations is significant. A declaration should be listed under
// its base class.
// ===----------------------------------------------------------------------===//
#ifndef DECL
# define DECL(Derived, Base)
#endif
#ifndef LAST_DECL
# define LAST_DECL(Derived, Base) DECL(Derived, Base)
#endif
#ifndef ABSTRACT_DECL
# define ABSTRACT_DECL(Derived, Base)
#endif
#ifndef DECL_CONTEXT
# define DECL_CONTEXT(Decl)
#endif
#ifndef DECL_CONTEXT_BASE
# define DECL_CONTEXT_BASE(Decl) DECL_CONTEXT(Decl)
#endif
#ifndef LAST_DECL_CONTEXT
# define LAST_DECL_CONTEXT(Decl) DECL_CONTEXT(Decl)
#endif
#ifndef DECL_RANGE
# define DECL_RANGE(CommonBase, Start, End)
#endif
#ifndef LAST_DECL_RANGE
# define LAST_DECL_RANGE(CommonBase, Start, End) \
DECL_RANGE(CommonBase, Start, End)
#endif
DECL(TranslationUnit, Decl)
ABSTRACT_DECL(Named, Decl)
DECL(Namespace, NamedDecl)
DECL(UsingDirective, NamedDecl)
DECL(NamespaceAlias, NamedDecl)
ABSTRACT_DECL(Type, NamedDecl)
DECL(Typedef, TypeDecl)
DECL(UnresolvedUsingTypename, TypeDecl)
ABSTRACT_DECL(Tag, TypeDecl)
DECL(Enum, TagDecl)
DECL(Record, TagDecl)
DECL(CXXRecord, RecordDecl)
DECL(ClassTemplateSpecialization, CXXRecordDecl)
DECL(ClassTemplatePartialSpecialization,
ClassTemplateSpecializationDecl)
DECL(TemplateTypeParm, TypeDecl)
ABSTRACT_DECL(Value, NamedDecl)
DECL(EnumConstant, ValueDecl)
DECL(UnresolvedUsingValue, ValueDecl)
ABSTRACT_DECL(Declarator, ValueDecl)
DECL(Function, DeclaratorDecl)
DECL(CXXMethod, FunctionDecl)
DECL(CXXConstructor, CXXMethodDecl)
DECL(CXXDestructor, CXXMethodDecl)
DECL(CXXConversion, CXXMethodDecl)
DECL(Field, DeclaratorDecl)
DECL(ObjCIvar, FieldDecl)
DECL(ObjCAtDefsField, FieldDecl)
DECL(Var, DeclaratorDecl)
DECL(ImplicitParam, VarDecl)
DECL(ParmVar, VarDecl)
DECL(NonTypeTemplateParm, VarDecl)
DECL(Template, NamedDecl)
DECL(FunctionTemplate, TemplateDecl)
DECL(ClassTemplate, TemplateDecl)
DECL(TemplateTemplateParm, TemplateDecl)
DECL(Using, NamedDecl)
DECL(UsingShadow, NamedDecl)
DECL(ObjCMethod, NamedDecl)
DECL(ObjCContainer, NamedDecl)
DECL(ObjCCategory, ObjCContainerDecl)
DECL(ObjCProtocol, ObjCContainerDecl)
DECL(ObjCInterface, ObjCContainerDecl)
ABSTRACT_DECL(ObjCImpl, ObjCContainerDecl)
DECL(ObjCCategoryImpl, ObjCImplDecl)
DECL(ObjCImplementation, ObjCImplDecl)
DECL(ObjCProperty, NamedDecl)
DECL(ObjCCompatibleAlias, NamedDecl)
DECL(LinkageSpec, Decl)
DECL(ObjCPropertyImpl, Decl)
DECL(ObjCForwardProtocol, Decl)
DECL(ObjCClass, Decl)
DECL(FileScopeAsm, Decl)
DECL(Friend, Decl)
DECL(FriendTemplate, Decl)
DECL(StaticAssert, Decl)
LAST_DECL(Block, Decl)
// Declaration contexts. DECL_CONTEXT_BASE indicates that it has subclasses.
DECL_CONTEXT(TranslationUnit)
DECL_CONTEXT(Namespace)
DECL_CONTEXT(LinkageSpec)
DECL_CONTEXT(ObjCMethod)
DECL_CONTEXT_BASE(Tag)
DECL_CONTEXT_BASE(Function)
DECL_CONTEXT_BASE(ObjCContainer)
LAST_DECL_CONTEXT(Block)
// Declaration ranges
DECL_RANGE(Named, Namespace, ObjCCompatibleAlias)
DECL_RANGE(ObjCContainer, ObjCContainer, ObjCImplementation)
DECL_RANGE(Field, Field, ObjCAtDefsField)
DECL_RANGE(Type, Typedef, TemplateTypeParm)
DECL_RANGE(Tag, Enum, ClassTemplatePartialSpecialization)
DECL_RANGE(Record, Record, ClassTemplatePartialSpecialization)
DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm)
DECL_RANGE(Declarator, Function, NonTypeTemplateParm)
DECL_RANGE(Function, Function, CXXConversion)
DECL_RANGE(Template, Template, TemplateTemplateParm)
DECL_RANGE(ObjCImpl, ObjCCategoryImpl, ObjCImplementation)
LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm)
#undef LAST_DECL_RANGE
#undef DECL_RANGE
#undef LAST_DECL_CONTEXT
#undef DECL_CONTEXT_BASE
#undef DECL_CONTEXT
#undef ABSTRACT_DECL
#undef LAST_DECL
#undef DECL

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,6 @@
#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 {
@@ -30,19 +29,20 @@ class DeclVisitor {
public:
RetTy Visit(Decl *D) {
switch (D->getKind()) {
default: llvm_unreachable("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"
default: assert(false && "Decl that isn't part of DeclNodes.def!");
#define DECL(Derived, Base) \
case Decl::Derived: DISPATCH(Derived##Decl, Derived##Decl);
#define ABSTRACT_DECL(Derived, Base)
#include "clang/AST/DeclNodes.def"
}
}
// 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"
#define DECL(Derived, Base) \
RetTy Visit##Derived##Decl(Derived##Decl *D) { DISPATCH(Base, Base); }
#define ABSTRACT_DECL(Derived, Base) DECL(Derived, Base)
#include "clang/AST/DeclNodes.def"
RetTy VisitDecl(Decl *D) { return RetTy(); }
};

View File

@@ -30,7 +30,6 @@ namespace clang {
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
@@ -199,12 +198,9 @@ public:
/// callee in a call expression with dependent arguments.
bool isDependentName() const;
/// getNameAsString - Retrieve the human-readable string for this name.
/// getName - Retrieve the human-readable string for this name.
std::string getAsString() const;
/// printName - Print the human-readable name to a stream.
void printName(raw_ostream &OS) const;
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
/// this declaration name, or NULL if this declaration name isn't a
/// simple identifier.
@@ -315,16 +311,15 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
/// retrieved using its member functions (e.g.,
/// getCXXConstructorName).
class DeclarationNameTable {
const ASTContext &Ctx;
void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
CXXOperatorIdName *CXXOperatorNames; // Operator names
void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
void *CXXLiteralOperatorNames; // Actually a FoldingSet<...> *
DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE
DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
public:
DeclarationNameTable(const ASTContext &C);
DeclarationNameTable();
~DeclarationNameTable();
/// getIdentifier - Create a declaration name that is a simple
@@ -336,15 +331,13 @@ public:
/// getCXXConstructorName - Returns the name of a C++ constructor
/// for the given Type.
DeclarationName getCXXConstructorName(CanQualType Ty) {
return getCXXSpecialName(DeclarationName::CXXConstructorName,
Ty.getUnqualifiedType());
return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty);
}
/// getCXXDestructorName - Returns the name of a C++ destructor
/// for the given Type.
DeclarationName getCXXDestructorName(CanQualType Ty) {
return getCXXSpecialName(DeclarationName::CXXDestructorName,
Ty.getUnqualifiedType());
return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty);
}
/// getCXXConversionFunctionName - Returns the name of a C++
@@ -368,159 +361,12 @@ public:
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() { memset((void*) this, 0, sizeof(*this)); }
}; // 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();
}
/// \brief Determine whether this name involves a template parameter.
bool isInstantiationDependent() const;
/// \brief Determine whether this name contains an unexpanded
/// parameter pack.
bool containsUnexpandedParameterPack() const;
/// getAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
/// printName - Print the human-readable name to a stream.
void printName(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(),
DiagnosticsEngine::ak_declarationname);
Diagnostic::ak_declarationname);
return DB;
}
@@ -529,16 +375,10 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
DeclarationName N) {
PD.AddTaggedVal(N.getAsOpaqueInteger(),
DiagnosticsEngine::ak_declarationname);
Diagnostic::ak_declarationname);
return PD;
}
inline raw_ostream &operator<<(raw_ostream &OS,
DeclarationNameInfo DNInfo) {
DNInfo.printName(OS);
return OS;
}
} // end namespace clang
namespace llvm {

View File

@@ -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

View File

@@ -1,83 +0,0 @@
//===--- EvaluatedExprVisitor.h - Evaluated expression visitor --*- 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 EvaluatedExprVisitor class template, which visits
// the potentially-evaluated subexpressions of a potentially-evaluated
// expression.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
#define LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
namespace clang {
class ASTContext;
/// \begin Given a potentially-evaluated expression, this visitor visits all
/// of its potentially-evaluated subexpressions, recursively.
template<typename ImplClass>
class EvaluatedExprVisitor : public StmtVisitor<ImplClass> {
ASTContext &Context;
public:
explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { }
// Expressions that have no potentially-evaluated subexpressions (but may have
// other sub-expressions).
void VisitDeclRefExpr(DeclRefExpr *E) { }
void VisitOffsetOfExpr(OffsetOfExpr *E) { }
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { }
void VisitExpressionTraitExpr(ExpressionTraitExpr *E) { }
void VisitBlockExpr(BlockExpr *E) { }
void VisitCXXUuidofExpr(CXXUuidofExpr *E) { }
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { }
void VisitMemberExpr(MemberExpr *E) {
// Only the base matters.
return this->Visit(E->getBase());
}
void VisitChooseExpr(ChooseExpr *E) {
// Only the selected subexpression matters; the other one is not evaluated.
return this->Visit(E->getChosenSubExpr(Context));
}
void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
// Only the actual initializer matters; the designators are all constant
// expressions.
return this->Visit(E->getInit());
}
void VisitCXXTypeidExpr(CXXTypeidExpr *E) {
// typeid(expression) is potentially evaluated when the argument is
// a glvalue of polymorphic type. (C++ 5.2.8p2-3)
if (!E->isTypeOperand() && E->Classify(Context).isGLValue())
if (const RecordType *Record
= E->getExprOperand()->getType()->template getAs<RecordType>())
if (cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic())
return this->Visit(E->getExprOperand());
}
/// \brief The basis case walks all of the children of the statement or
/// expression, assuming they are all potentially evaluated.
void VisitStmt(Stmt *S) {
for (Stmt::child_range C = S->children(); C; ++C)
if (*C)
this->Visit(*C);
}
};
}
#endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,39 +8,37 @@
//===----------------------------------------------------------------------===//
//
// This file defines the ExternalASTSource interface, which enables
// construction of AST nodes from some external source.
// construction of AST nodes from some external source.x
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <vector>
namespace clang {
class ASTConsumer;
class CXXBaseSpecifier;
class DeclarationName;
class Decl;
class DeclContext;
class ExternalSemaSource; // layering violation required for downcasting
class NamedDecl;
class Selector;
class Stmt;
class TagDecl;
/// \brief Enumeration describing the result of loading information from
/// an external source.
enum ExternalLoadResult {
/// \brief Loading the external information has succeeded.
ELR_Success,
/// \brief Loading the external information has failed.
ELR_Failure,
/// \brief The external information has already been loaded, and therefore
/// no additional processing is required.
ELR_AlreadyLoaded
/// \brief The deserialized representation of a set of declarations
/// with the same name that are visible in a given context.
struct VisibleDeclaration {
/// \brief The name of the declarations.
DeclarationName Name;
/// \brief The ID numbers of all of the declarations with this name.
///
/// These declarations have not necessarily been de-serialized.
llvm::SmallVector<unsigned, 4> Declarations;
};
/// \brief Abstract interface for external sources of AST nodes.
///
/// External AST sources provide AST nodes constructed from some
@@ -60,167 +58,68 @@ public:
virtual ~ExternalASTSource();
/// \brief RAII class for safely pairing a StartedDeserializing call
/// with FinishedDeserializing.
class Deserializing {
ExternalASTSource *Source;
public:
explicit Deserializing(ExternalASTSource *source) : Source(source) {
assert(Source);
Source->StartedDeserializing();
}
~Deserializing() {
Source->FinishedDeserializing();
}
};
/// \brief Reads the source ranges that correspond to comments from
/// an external AST source.
///
/// \param Comments the contents of this vector will be
/// replaced with the sorted set of source ranges corresponding to
/// comments in the source code.
virtual void ReadComments(std::vector<SourceRange> &Comments) = 0;
/// \brief Resolve a type ID into a type, potentially building a new
/// type.
virtual QualType GetType(uint32_t ID) = 0;
/// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
///
/// This method only needs to be implemented if the AST source ever
/// passes back decl sets as VisibleDeclaration objects.
///
/// The default implementation of this method is a no-op.
virtual Decl *GetExternalDecl(uint32_t ID);
virtual Decl *GetDecl(uint32_t ID) = 0;
/// \brief Resolve a selector ID into a selector.
/// \brief Resolve the offset of a statement in the decl stream into a
/// statement.
///
/// This operation only needs to be implemented if the AST source
/// returns non-zero for GetNumKnownSelectors().
///
/// The default implementation of this method is a no-op.
virtual Selector GetExternalSelector(uint32_t ID);
/// This operation will read a new statement from the external
/// source each time it is called, and is meant to be used via a
/// LazyOffsetPtr.
virtual Stmt *GetDeclStmt(uint64_t Offset) = 0;
/// \brief Returns the number of selectors known to the external AST
/// source.
/// \brief Read all of the declarations lexically stored in a
/// declaration context.
///
/// The default implementation of this method is a no-op.
virtual uint32_t GetNumExternalSelectors();
/// \param DC The declaration context whose declarations will be
/// read.
///
/// \param Decls Vector that will contain the declarations loaded
/// from the external source. The caller is responsible for merging
/// these declarations with any declarations already stored in the
/// declaration context.
///
/// \returns true if there was an error while reading the
/// declarations for this declaration context.
virtual bool ReadDeclsLexicallyInContext(DeclContext *DC,
llvm::SmallVectorImpl<uint32_t> &Decls) = 0;
/// \brief Resolve the offset of a statement in the decl stream into
/// a statement.
/// \brief Read all of the declarations visible from a declaration
/// context.
///
/// This operation is meant to be used via a LazyOffsetPtr. It only
/// needs to be implemented if the AST source uses methods like
/// FunctionDecl::setLazyBody when building decls.
/// \param DC The declaration context whose visible declarations
/// will be read.
///
/// The default implementation of this method is a no-op.
virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
/// \brief Resolve the offset of a set of C++ base specifiers in the decl
/// stream into an array of specifiers.
/// \param Decls A vector of visible declaration structures,
/// providing the mapping from each name visible in the declaration
/// context to the declaration IDs of declarations with that name.
///
/// The default implementation of this method is a no-op.
virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
/// \brief Finds all declarations with the given name in the
/// given context.
///
/// Generally the final step of this method is either to call
/// SetExternalVisibleDeclsForName or to recursively call lookup on
/// the DeclContext after calling SetExternalVisibleDecls.
///
/// The default implementation of this method is a no-op.
virtual DeclContextLookupResult
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
/// \param isKindWeWant a predicate function that returns true if the passed
/// declaration kind is one we are looking for. If NULL, all declarations
/// are returned.
///
/// \return an indication of whether the load succeeded or failed.
///
/// The default implementation of this method is a no-op.
virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
SmallVectorImpl<Decl*> &Result);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
///
/// \return true if an error occurred
ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
SmallVectorImpl<Decl*> &Result) {
return FindExternalLexicalDecls(DC, 0, Result);
}
template <typename DeclTy>
ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
SmallVectorImpl<Decl*> &Result) {
return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
}
/// \brief Gives the external AST source an opportunity to complete
/// an incomplete type.
virtual void CompleteType(TagDecl *Tag) {}
/// \brief Gives the external AST source an opportunity to complete an
/// incomplete Objective-C class.
///
/// This routine will only be invoked if the "externally completed" bit is
/// set on the ObjCInterfaceDecl via the function
/// \c ObjCInterfaceDecl::setExternallyCompleted().
virtual void CompleteType(ObjCInterfaceDecl *Class) { }
/// \brief Notify ExternalASTSource that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void StartedDeserializing() { }
/// \brief Notify ExternalASTSource that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void FinishedDeserializing() { }
/// \returns true if there was an error while reading the
/// declarations for this declaration context.
virtual bool ReadDeclsVisibleInContext(DeclContext *DC,
llvm::SmallVectorImpl<VisibleDeclaration> & Decls) = 0;
/// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
/// The default implementation of this method is a no-op.
virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
/// \brief Print any statistics that have been gathered regarding
/// the external AST source.
///
/// The default implementation of this method is a no-op.
virtual void PrintStats();
//===--------------------------------------------------------------------===//
// Queries for performance analysis.
//===--------------------------------------------------------------------===//
struct MemoryBufferSizes {
size_t malloc_bytes;
size_t mmap_bytes;
MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
: malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
};
/// Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
MemoryBufferSizes getMemoryBufferSizes() const {
MemoryBufferSizes sizes(0, 0);
getMemoryBufferSizes(sizes);
return sizes;
}
virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
protected:
static DeclContextLookupResult
SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
ArrayRef<NamedDecl*> Decls);
static DeclContextLookupResult
SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name);
};
/// \brief A lazy pointer to an AST node (of base type T) that resides
@@ -229,7 +128,7 @@ protected:
/// The AST node is identified within the external AST source by a
/// 63-bit offset, and can be retrieved via an operation on the
/// external AST source itself.
template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)>
struct LazyOffsetPtr {
/// \brief Either a pointer to an AST node or the offset within the
/// external AST source where the AST node can be found.
@@ -286,190 +185,8 @@ public:
}
};
/// \brief Represents a lazily-loaded vector of data.
///
/// The lazily-loaded vector of data contains data that is partially loaded
/// from an external source and partially added by local translation. The
/// items loaded from the external source are loaded lazily, when needed for
/// iteration over the complete vector.
template<typename T, typename Source,
void (Source::*Loader)(SmallVectorImpl<T>&),
unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
class LazyVector {
SmallVector<T, LoadedStorage> Loaded;
SmallVector<T, LocalStorage> Local;
public:
// Iteration over the elements in the vector.
class iterator {
LazyVector *Self;
/// \brief Position within the vector..
///
/// In a complete iteration, the Position field walks the range [-M, N),
/// where negative values are used to indicate elements
/// loaded from the external source while non-negative values are used to
/// indicate elements added via \c push_back().
/// However, to provide iteration in source order (for, e.g., chained
/// precompiled headers), dereferencing the iterator flips the negative
/// values (corresponding to loaded entities), so that position -M
/// corresponds to element 0 in the loaded entities vector, position -M+1
/// corresponds to element 1 in the loaded entities vector, etc. This
/// gives us a reasonably efficient, source-order walk.
int Position;
friend class LazyVector;
public:
typedef T value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef int difference_type;
iterator() : Self(0), Position(0) { }
iterator(LazyVector *Self, int Position)
: Self(Self), Position(Position) { }
reference operator*() const {
if (Position < 0)
return Self->Loaded.end()[Position];
return Self->Local[Position];
}
pointer operator->() const {
if (Position < 0)
return &Self->Loaded.end()[Position];
return &Self->Local[Position];
}
reference operator[](difference_type D) {
return *(*this + D);
}
iterator &operator++() {
++Position;
return *this;
}
iterator operator++(int) {
iterator Prev(*this);
++Position;
return Prev;
}
iterator &operator--() {
--Position;
return *this;
}
iterator operator--(int) {
iterator Prev(*this);
--Position;
return Prev;
}
friend bool operator==(const iterator &X, const iterator &Y) {
return X.Position == Y.Position;
}
friend bool operator!=(const iterator &X, const iterator &Y) {
return X.Position != Y.Position;
}
friend bool operator<(const iterator &X, const iterator &Y) {
return X.Position < Y.Position;
}
friend bool operator>(const iterator &X, const iterator &Y) {
return X.Position > Y.Position;
}
friend bool operator<=(const iterator &X, const iterator &Y) {
return X.Position < Y.Position;
}
friend bool operator>=(const iterator &X, const iterator &Y) {
return X.Position > Y.Position;
}
friend iterator& operator+=(iterator &X, difference_type D) {
X.Position += D;
return X;
}
friend iterator& operator-=(iterator &X, difference_type D) {
X.Position -= D;
return X;
}
friend iterator operator+(iterator X, difference_type D) {
X.Position += D;
return X;
}
friend iterator operator+(difference_type D, iterator X) {
X.Position += D;
return X;
}
friend difference_type operator-(const iterator &X, const iterator &Y) {
return X.Position - Y.Position;
}
friend iterator operator-(iterator X, difference_type D) {
X.Position -= D;
return X;
}
};
friend class iterator;
iterator begin(Source *source, bool LocalOnly = false) {
if (LocalOnly)
return iterator(this, 0);
if (source)
(source->*Loader)(Loaded);
return iterator(this, -(int)Loaded.size());
}
iterator end() {
return iterator(this, Local.size());
}
void push_back(const T& LocalValue) {
Local.push_back(LocalValue);
}
void erase(iterator From, iterator To) {
if (From.Position < 0 && To.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position);
return;
}
if (From.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end());
From = begin(0, true);
}
Local.erase(Local.begin() + From.Position, Local.begin() + To.Position);
}
};
/// \brief A lazy pointer to a statement.
typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
LazyDeclStmtPtr;
/// \brief A lazy pointer to a declaration.
typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
LazyDeclPtr;
/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
&ExternalASTSource::GetExternalCXXBaseSpecifiers>
LazyCXXBaseSpecifiersPtr;
typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetDeclStmt> LazyDeclStmtPtr;
} // end namespace clang

View File

@@ -0,0 +1,89 @@
//===--- FullExpr.h - C++ full expression class -----------------*- 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 FullExpr interface, to be used for type safe handling
// of full expressions.
//
// Full expressions are described in C++ [intro.execution]p12.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_FULLEXPR_H
#define LLVM_CLANG_AST_FULLEXPR_H
#include "llvm/ADT/PointerUnion.h"
namespace clang {
class ASTContext;
class CXXTemporary;
class Expr;
class FullExpr {
struct ExprAndTemporaries {
Expr *SubExpr;
unsigned NumTemps;
typedef CXXTemporary** temps_iterator;
temps_iterator temps_begin() {
return reinterpret_cast<CXXTemporary **>(this + 1);
}
temps_iterator temps_end() {
return temps_begin() + NumTemps;
}
};
typedef llvm::PointerUnion<Expr *, ExprAndTemporaries *> SubExprTy;
SubExprTy SubExpr;
FullExpr() { }
public:
static FullExpr Create(ASTContext &Context, Expr *SubExpr,
CXXTemporary **Temps, unsigned NumTemps);
void Destroy(ASTContext &Context);
Expr *getExpr() {
if (Expr *E = SubExpr.dyn_cast<Expr *>())
return E;
return SubExpr.get<ExprAndTemporaries *>()->SubExpr;
}
const Expr *getExpr() const {
return const_cast<FullExpr*>(this)->getExpr();
}
typedef CXXTemporary** temps_iterator;
temps_iterator temps_begin() {
if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>())
return ET->temps_begin();
return 0;
}
temps_iterator temps_end() {
if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>())
return ET->temps_end();
return 0;
}
void *getAsOpaquePtr() const { return SubExpr.getOpaqueValue(); }
static FullExpr getFromOpaquePtr(void *Ptr) {
FullExpr E;
E.SubExpr = SubExprTy::getFromOpaqueValue(Ptr);
return E;
}
};
} // end namespace clang
#endif

View File

@@ -1,29 +0,0 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc
TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
$(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute classes with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute implementations with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang statement node tables with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $<
$(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang declaration node tables with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $<

View File

@@ -1,150 +0,0 @@
//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines the C++ name mangling interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_MANGLE_H
#define LLVM_CLANG_AST_MANGLE_H
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
class ASTContext;
class BlockDecl;
class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXMethodDecl;
class FunctionDecl;
class NamedDecl;
class ObjCMethodDecl;
class VarDecl;
struct ThisAdjustment;
struct ThunkInfo;
/// MangleBuffer - a convenient class for storing a name which is
/// either the result of a mangling or is a constant string with
/// external memory ownership.
class MangleBuffer {
public:
void setString(StringRef Ref) {
String = Ref;
}
SmallVectorImpl<char> &getBuffer() {
return Buffer;
}
StringRef getString() const {
if (!String.empty()) return String;
return Buffer.str();
}
operator StringRef() const {
return getString();
}
private:
StringRef String;
llvm::SmallString<256> Buffer;
};
/// MangleContext - Context for tracking state which persists across multiple
/// calls to the C++ name mangler.
class MangleContext {
ASTContext &Context;
DiagnosticsEngine &Diags;
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
public:
explicit MangleContext(ASTContext &Context,
DiagnosticsEngine &Diags)
: Context(Context), Diags(Diags) { }
virtual ~MangleContext() { }
ASTContext &getASTContext() const { return Context; }
DiagnosticsEngine &getDiags() const { return Diags; }
virtual void startNewFunction() { LocalBlockIds.clear(); }
unsigned getBlockId(const BlockDecl *BD, bool Local) {
llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
= Local? LocalBlockIds : GlobalBlockIds;
std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
return Result.first->second;
}
/// @name Mangler Entry Points
/// @{
virtual bool shouldMangleDeclName(const NamedDecl *D) = 0;
virtual void mangleName(const NamedDecl *D, raw_ostream &)=0;
virtual void mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
raw_ostream &) = 0;
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
raw_ostream &) = 0;
virtual void mangleReferenceTemporary(const VarDecl *D,
raw_ostream &) = 0;
virtual void mangleCXXVTable(const CXXRecordDecl *RD,
raw_ostream &) = 0;
virtual void mangleCXXVTT(const CXXRecordDecl *RD,
raw_ostream &) = 0;
virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
const CXXRecordDecl *Type,
raw_ostream &) = 0;
virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
raw_ostream &) = 0;
virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
raw_ostream &) = 0;
void mangleGlobalBlock(const BlockDecl *BD,
raw_ostream &Out);
void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
const BlockDecl *BD, raw_ostream &Out);
void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
const BlockDecl *BD, raw_ostream &Out);
void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
raw_ostream &Out);
// Do the right thing.
void mangleBlock(const BlockDecl *BD, raw_ostream &Out);
void mangleObjCMethodName(const ObjCMethodDecl *MD,
raw_ostream &);
// This is pretty lame.
virtual void mangleItaniumGuardVariable(const VarDecl *D,
raw_ostream &) {
llvm_unreachable("Target does not support mangling guard variables");
}
/// @}
};
MangleContext *createItaniumMangleContext(ASTContext &Context,
DiagnosticsEngine &Diags);
MangleContext *createMicrosoftMangleContext(ASTContext &Context,
DiagnosticsEngine &Diags);
}
#endif

View File

@@ -18,15 +18,17 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
namespace llvm {
class raw_ostream;
}
namespace clang {
class ASTContext;
class NamespaceAliasDecl;
class NamespaceDecl;
class IdentifierInfo;
struct PrintingPolicy;
class Type;
class TypeLoc;
class LangOptions;
/// \brief Represents a C++ nested name specifier, such as
@@ -39,22 +41,13 @@ class LangOptions;
/// (for dependent names), or the global specifier ('::', must be the
/// first specifier).
class NestedNameSpecifier : public llvm::FoldingSetNode {
/// \brief Enumeration describing
enum StoredSpecifierKind {
StoredIdentifier = 0,
StoredNamespaceOrAlias = 1,
StoredTypeSpec = 2,
StoredTypeSpecWithTemplate = 3
};
/// \brief The nested name specifier that precedes this nested name
/// specifier.
///
/// The pointer is the nested-name-specifier that precedes this
/// one. The integer stores one of the first four values of type
/// SpecifierKind.
llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix;
llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix;
/// \brief The last component in the nested name specifier, which
/// can be an identifier, a declaration, or a type.
@@ -70,23 +63,21 @@ public:
/// specifier.
enum SpecifierKind {
/// \brief An identifier, stored as an IdentifierInfo*.
Identifier,
/// \brief A namespace, stored as a NamespaceDecl*.
Namespace,
/// \brief A namespace alias, stored as a NamespaceAliasDecl*.
NamespaceAlias,
Identifier = 0,
/// \brief A namespace, stored as a Namespace*.
Namespace = 1,
/// \brief A type, stored as a Type*.
TypeSpec,
TypeSpec = 2,
/// \brief A type that was preceded by the 'template' keyword,
/// stored as a Type*.
TypeSpecWithTemplate,
TypeSpecWithTemplate = 3,
/// \brief The global specifier '::'. There is no stored value.
Global
Global = 4
};
private:
/// \brief Builds the global specifier.
NestedNameSpecifier() : Prefix(0, StoredIdentifier), Specifier(0) { }
NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { }
/// \brief Copy constructor used internally to clone nested name
/// specifiers.
@@ -99,7 +90,7 @@ private:
/// \brief Either find or insert the given nested name specifier
/// mockup in the given context.
static NestedNameSpecifier *FindOrInsert(const ASTContext &Context,
static NestedNameSpecifier *FindOrInsert(ASTContext &Context,
const NestedNameSpecifier &Mockup);
public:
@@ -108,24 +99,19 @@ public:
/// The prefix must be dependent, since nested name specifiers
/// referencing an identifier are only permitted when the identifier
/// cannot be resolved.
static NestedNameSpecifier *Create(const ASTContext &Context,
static NestedNameSpecifier *Create(ASTContext &Context,
NestedNameSpecifier *Prefix,
IdentifierInfo *II);
/// \brief Builds a nested name specifier that names a namespace.
static NestedNameSpecifier *Create(const ASTContext &Context,
static NestedNameSpecifier *Create(ASTContext &Context,
NestedNameSpecifier *Prefix,
NamespaceDecl *NS);
/// \brief Builds a nested name specifier that names a namespace alias.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
NamespaceAliasDecl *Alias);
/// \brief Builds a nested name specifier that names a type.
static NestedNameSpecifier *Create(const ASTContext &Context,
static NestedNameSpecifier *Create(ASTContext &Context,
NestedNameSpecifier *Prefix,
bool Template, const Type *T);
bool Template, Type *T);
/// \brief Builds a specifier that consists of just an identifier.
///
@@ -133,12 +119,11 @@ public:
/// prefix because the prefix is implied by something outside of the
/// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
/// type.
static NestedNameSpecifier *Create(const ASTContext &Context,
IdentifierInfo *II);
static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II);
/// \brief Returns the nested name specifier representing the global
/// scope.
static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
/// \brief Return the prefix of this nested name specifier.
///
@@ -150,12 +135,16 @@ public:
NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
/// \brief Determine what kind of nested name specifier is stored.
SpecifierKind getKind() const;
SpecifierKind getKind() const {
if (Specifier == 0)
return Global;
return (SpecifierKind)Prefix.getInt();
}
/// \brief Retrieve the identifier stored in this nested name
/// specifier.
IdentifierInfo *getAsIdentifier() const {
if (Prefix.getInt() == StoredIdentifier)
if (Prefix.getInt() == Identifier)
return (IdentifierInfo *)Specifier;
return 0;
@@ -163,17 +152,18 @@ public:
/// \brief Retrieve the namespace stored in this nested name
/// specifier.
NamespaceDecl *getAsNamespace() const;
NamespaceDecl *getAsNamespace() const {
if (Prefix.getInt() == Namespace)
return (NamespaceDecl *)Specifier;
/// \brief Retrieve the namespace alias stored in this nested name
/// specifier.
NamespaceAliasDecl *getAsNamespaceAlias() const;
return 0;
}
/// \brief Retrieve the type stored in this nested name specifier.
const Type *getAsType() const {
if (Prefix.getInt() == StoredTypeSpec ||
Prefix.getInt() == StoredTypeSpecWithTemplate)
return (const Type *)Specifier;
Type *getAsType() const {
if (Prefix.getInt() == TypeSpec ||
Prefix.getInt() == TypeSpecWithTemplate)
return (Type *)Specifier;
return 0;
}
@@ -182,290 +172,28 @@ public:
/// type or not.
bool isDependent() const;
/// \brief Whether this nested name specifier involves a template
/// parameter.
bool isInstantiationDependent() const;
/// \brief Whether this nested-name-specifier contains an unexpanded
/// parameter pack (for C++0x variadic templates).
bool containsUnexpandedParameterPack() const;
/// \brief Print this nested name specifier to the given output
/// stream.
void print(raw_ostream &OS, const PrintingPolicy &Policy) const;
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(Prefix.getOpaqueValue());
ID.AddPointer(Specifier);
}
void Destroy(ASTContext &Context);
/// \brief Dump the nested name specifier to standard output to aid
/// in debugging.
void dump(const LangOptions &LO);
};
/// \brief A C++ nested-name-specifier augmented with source location
/// information.
class NestedNameSpecifierLoc {
NestedNameSpecifier *Qualifier;
void *Data;
/// \brief Determines the data length for the last component in the
/// given nested-name-specifier.
static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
/// \brief Determines the data length for the entire
/// nested-name-specifier.
static unsigned getDataLength(NestedNameSpecifier *Qualifier);
public:
/// \brief Construct an empty nested-name-specifier.
NestedNameSpecifierLoc() : Qualifier(0), Data(0) { }
/// \brief Construct a nested-name-specifier with source location information
/// from
NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
: Qualifier(Qualifier), Data(Data) { }
/// \brief Evalutes true when this nested-name-specifier location is
/// non-empty.
operator bool() const { return Qualifier; }
/// \brief Retrieve the nested-name-specifier to which this instance
/// refers.
NestedNameSpecifier *getNestedNameSpecifier() const {
return Qualifier;
}
/// \brief Retrieve the opaque pointer that refers to source-location data.
void *getOpaqueData() const { return Data; }
/// \brief Retrieve the source range covering the entirety of this
/// nested-name-specifier.
///
/// For example, if this instance refers to a nested-name-specifier
/// \c ::std::vector<int>::, the returned source range would cover
/// from the initial '::' to the last '::'.
SourceRange getSourceRange() const;
/// \brief Retrieve the source range covering just the last part of
/// this nested-name-specifier, not including the prefix.
///
/// For example, if this instance refers to a nested-name-specifier
/// \c ::std::vector<int>::, the returned source range would cover
/// from "vector" to the last '::'.
SourceRange getLocalSourceRange() const;
/// \brief Retrieve the location of the beginning of this
/// nested-name-specifier.
SourceLocation getBeginLoc() const {
return getSourceRange().getBegin();
}
/// \brief Retrieve the location of the end of this
/// nested-name-specifier.
SourceLocation getEndLoc() const {
return getSourceRange().getEnd();
}
/// \brief Retrieve the location of the beginning of this
/// component of the nested-name-specifier.
SourceLocation getLocalBeginLoc() const {
return getLocalSourceRange().getBegin();
}
/// \brief Retrieve the location of the end of this component of the
/// nested-name-specifier.
SourceLocation getLocalEndLoc() const {
return getLocalSourceRange().getEnd();
}
/// \brief Return the prefix of this nested-name-specifier.
///
/// For example, if this instance refers to a nested-name-specifier
/// \c ::std::vector<int>::, the prefix is \c ::std::. Note that the
/// returned prefix may be empty, if this is the first component of
/// the nested-name-specifier.
NestedNameSpecifierLoc getPrefix() const {
if (!Qualifier)
return *this;
return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
}
/// \brief For a nested-name-specifier that refers to a type,
/// retrieve the type with source-location information.
TypeLoc getTypeLoc() const;
/// \brief Determines the data length for the entire
/// nested-name-specifier.
unsigned getDataLength() const { return getDataLength(Qualifier); }
friend bool operator==(NestedNameSpecifierLoc X,
NestedNameSpecifierLoc Y) {
return X.Qualifier == Y.Qualifier && X.Data == Y.Data;
}
friend bool operator!=(NestedNameSpecifierLoc X,
NestedNameSpecifierLoc Y) {
return !(X == Y);
}
};
/// \brief Class that aids in the construction of nested-name-specifiers along
/// with source-location information for all of the components of the
/// nested-name-specifier.
class NestedNameSpecifierLocBuilder {
/// \brief The current representation of the nested-name-specifier we're
/// building.
NestedNameSpecifier *Representation;
/// \brief Buffer used to store source-location information for the
/// nested-name-specifier.
///
/// Note that we explicitly manage the buffer (rather than using a
/// SmallVector) because \c Declarator expects it to be possible to memcpy()
/// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
char *Buffer;
/// \brief The size of the buffer used to store source-location information
/// for the nested-name-specifier.
unsigned BufferSize;
/// \brief The capacity of the buffer used to store source-location
/// information for the nested-name-specifier.
unsigned BufferCapacity;
public:
NestedNameSpecifierLocBuilder();
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
NestedNameSpecifierLocBuilder &
operator=(const NestedNameSpecifierLocBuilder &Other);
~NestedNameSpecifierLocBuilder();
/// \brief Retrieve the representation of the nested-name-specifier.
NestedNameSpecifier *getRepresentation() const { return Representation; }
/// \brief Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'type::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param TemplateKWLoc The location of the 'template' keyword, if present.
///
/// \param TL The TypeLoc that describes the type preceding the '::'.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
SourceLocation ColonColonLoc);
/// \brief Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'identifier::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param Identifier The identifier.
///
/// \param IdentifierLoc The location of the identifier.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, IdentifierInfo *Identifier,
SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
/// \brief Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param Namespace The namespace.
///
/// \param NamespaceLoc The location of the namespace name.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, NamespaceDecl *Namespace,
SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
/// \brief Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace-alias::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param Alias The namespace alias.
///
/// \param AliasLoc The location of the namespace alias
/// name.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
SourceLocation AliasLoc, SourceLocation ColonColonLoc);
/// \brief Turn this (empty) nested-name-specifier into the global
/// nested-name-specifier '::'.
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
/// \brief Make a new nested-name-specifier from incomplete source-location
/// information.
///
/// This routine should be used very, very rarely, in cases where we
/// need to synthesize a nested-name-specifier. Most code should instead use
/// \c Adopt() with a proper \c NestedNameSpecifierLoc.
void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
SourceRange R);
/// \brief Adopt an existing nested-name-specifier (with source-range
/// information).
void Adopt(NestedNameSpecifierLoc Other);
/// \brief Retrieve the source range covered by this nested-name-specifier.
SourceRange getSourceRange() const {
return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange();
}
/// \brief Retrieve a nested-name-specifier with location information,
/// copied into the given AST context.
///
/// \param Context The context into which this nested-name-specifier will be
/// copied.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
/// \brief Retrieve a nested-name-specifier with location
/// information based on the information in this builder. This loc
/// will contain references to the builder's internal data and may
/// be invalidated by any change to the builder.
NestedNameSpecifierLoc getTemporary() const {
return NestedNameSpecifierLoc(Representation, Buffer);
}
/// \brief Clear out this builder, and prepare it to build another
/// nested-name-specifier with source-location information.
void Clear() {
Representation = 0;
BufferSize = 0;
}
/// \brief Retrieve the underlying buffer.
///
/// \returns A pair containing a pointer to the buffer of source-location
/// data and the size of the source-location data that resides in that
/// buffer.
std::pair<char *, unsigned> getBuffer() const {
return std::make_pair(Buffer, BufferSize);
}
};
/// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
NestedNameSpecifier *NNS) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS),
DiagnosticsEngine::ak_nestednamespec);
Diagnostic::ak_nestednamespec);
return DB;
}

View File

@@ -1,331 +0,0 @@
//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file enumerates the different kinds of operations that can be
// performed by various expressions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H
#define LLVM_CLANG_AST_OPERATION_KINDS_H
namespace clang {
/// CastKind - The kind of operation required for a conversion.
enum CastKind {
/// CK_Dependent - A conversion which cannot yet be analyzed because
/// either the expression or target type is dependent. These are
/// created only for explicit casts; dependent ASTs aren't required
/// to even approximately type-check.
/// (T*) malloc(sizeof(T))
/// reinterpret_cast<intptr_t>(A<T>::alloc());
CK_Dependent,
/// CK_BitCast - A conversion which causes a bit pattern of one type
/// to be reinterpreted as a bit pattern of another type. Generally
/// the operands must have equivalent size and unrelated types.
///
/// The pointer conversion char* -> int* is a bitcast. A conversion
/// from any pointer type to a C pointer type is a bitcast unless
/// it's actually BaseToDerived or DerivedToBase. A conversion to a
/// block pointer or ObjC pointer type is a bitcast only if the
/// operand has the same type kind; otherwise, it's one of the
/// specialized casts below.
///
/// Vector coercions are bitcasts.
CK_BitCast,
/// CK_LValueBitCast - A conversion which reinterprets the address of
/// an l-value as an l-value of a different kind. Used for
/// reinterpret_casts of l-value expressions to reference types.
/// bool b; reinterpret_cast<char&>(b) = 'a';
CK_LValueBitCast,
/// CK_LValueToRValue - A conversion which causes the extraction of
/// an r-value from the operand gl-value. The result of an r-value
/// conversion is always unqualified.
CK_LValueToRValue,
/// CK_GetObjCProperty - A conversion which calls an Objective-C
/// property getter. The operand is an OK_ObjCProperty l-value; the
/// result will generally be an r-value, but could be an ordinary
/// gl-value if the property reference is to an implicit property
/// for a method that returns a reference type.
CK_GetObjCProperty,
/// CK_NoOp - A conversion which does not affect the type other than
/// (possibly) adding qualifiers.
/// int -> int
/// char** -> const char * const *
CK_NoOp,
/// CK_BaseToDerived - A conversion from a C++ class pointer/reference
/// to a derived class pointer/reference.
/// B *b = static_cast<B*>(a);
CK_BaseToDerived,
/// CK_DerivedToBase - A conversion from a C++ class pointer
/// to a base class pointer.
/// A *a = new B();
CK_DerivedToBase,
/// CK_UncheckedDerivedToBase - A conversion from a C++ class
/// pointer/reference to a base class that can assume that the
/// derived pointer is not null.
/// const A &a = B();
/// b->method_from_a();
CK_UncheckedDerivedToBase,
/// CK_Dynamic - A C++ dynamic_cast.
CK_Dynamic,
/// CK_ToUnion - The GCC cast-to-union extension.
/// int -> union { int x; float y; }
/// float -> union { int x; float y; }
CK_ToUnion,
/// CK_ArrayToPointerDecay - Array to pointer decay.
/// int[10] -> int*
/// char[5][6] -> char(*)[6]
CK_ArrayToPointerDecay,
/// CK_FunctionToPointerDecay - Function to pointer decay.
/// void(int) -> void(*)(int)
CK_FunctionToPointerDecay,
/// CK_NullToPointer - Null pointer constant to pointer, ObjC
/// pointer, or block pointer.
/// (void*) 0
/// void (^block)() = 0;
CK_NullToPointer,
/// CK_NullToMemberPointer - Null pointer constant to member pointer.
/// int A::*mptr = 0;
/// int (A::*fptr)(int) = nullptr;
CK_NullToMemberPointer,
/// CK_BaseToDerivedMemberPointer - Member pointer in base class to
/// member pointer in derived class.
/// int B::*mptr = &A::member;
CK_BaseToDerivedMemberPointer,
/// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
/// member pointer in base class.
/// int A::*mptr = static_cast<int A::*>(&B::member);
CK_DerivedToBaseMemberPointer,
/// CK_MemberPointerToBoolean - Member pointer to boolean. A check
/// against the null member pointer.
CK_MemberPointerToBoolean,
/// CK_UserDefinedConversion - Conversion using a user defined type
/// conversion function.
/// struct A { operator int(); }; int i = int(A());
CK_UserDefinedConversion,
/// CK_ConstructorConversion - Conversion by constructor.
/// struct A { A(int); }; A a = A(10);
CK_ConstructorConversion,
/// CK_IntegralToPointer - Integral to pointer. A special kind of
/// reinterpreting conversion. Applies to normal, ObjC, and block
/// pointers.
/// (char*) 0x1001aab0
/// reinterpret_cast<int*>(0)
CK_IntegralToPointer,
/// CK_PointerToIntegral - Pointer to integral. A special kind of
/// reinterpreting conversion. Applies to normal, ObjC, and block
/// pointers.
/// (intptr_t) "help!"
CK_PointerToIntegral,
/// CK_PointerToBoolean - Pointer to boolean conversion. A check
/// against null. Applies to normal, ObjC, and block pointers.
CK_PointerToBoolean,
/// CK_ToVoid - Cast to void, discarding the computed value.
/// (void) malloc(2048)
CK_ToVoid,
/// CK_VectorSplat - A conversion from an arithmetic type to a
/// vector of that element type. Fills all elements ("splats") with
/// the source value.
/// __attribute__((ext_vector_type(4))) int v = 5;
CK_VectorSplat,
/// CK_IntegralCast - A cast between integral types (other than to
/// boolean). Variously a bitcast, a truncation, a sign-extension,
/// or a zero-extension.
/// long l = 5;
/// (unsigned) i
CK_IntegralCast,
/// CK_IntegralToBoolean - Integral to boolean. A check against zero.
/// (bool) i
CK_IntegralToBoolean,
/// CK_IntegralToFloating - Integral to floating point.
/// float f = i;
CK_IntegralToFloating,
/// CK_FloatingToIntegral - Floating point to integral. Rounds
/// towards zero, discarding any fractional component.
/// (int) f
CK_FloatingToIntegral,
/// CK_FloatingToBoolean - Floating point to boolean.
/// (bool) f
CK_FloatingToBoolean,
/// CK_FloatingCast - Casting between floating types of different size.
/// (double) f
/// (float) ld
CK_FloatingCast,
/// CK_CPointerToObjCPointerCast - Casting a C pointer kind to an
/// Objective-C pointer.
CK_CPointerToObjCPointerCast,
/// CK_BlockPointerToObjCPointerCast - Casting a block pointer to an
/// ObjC pointer.
CK_BlockPointerToObjCPointerCast,
/// CK_AnyPointerToBlockPointerCast - Casting any non-block pointer
/// to a block pointer. Block-to-block casts are bitcasts.
CK_AnyPointerToBlockPointerCast,
/// \brief Converting between two Objective-C object types, which
/// can occur when performing reference binding to an Objective-C
/// object.
CK_ObjCObjectLValueCast,
/// \brief A conversion of a floating point real to a floating point
/// complex of the original type. Injects the value as the real
/// component with a zero imaginary component.
/// float -> _Complex float
CK_FloatingRealToComplex,
/// \brief Converts a floating point complex to floating point real
/// of the source's element type. Just discards the imaginary
/// component.
/// _Complex long double -> long double
CK_FloatingComplexToReal,
/// \brief Converts a floating point complex to bool by comparing
/// against 0+0i.
CK_FloatingComplexToBoolean,
/// \brief Converts between different floating point complex types.
/// _Complex float -> _Complex double
CK_FloatingComplexCast,
/// \brief Converts from a floating complex to an integral complex.
/// _Complex float -> _Complex int
CK_FloatingComplexToIntegralComplex,
/// \brief Converts from an integral real to an integral complex
/// whose element type matches the source. Injects the value as
/// the real component with a zero imaginary component.
/// long -> _Complex long
CK_IntegralRealToComplex,
/// \brief Converts an integral complex to an integral real of the
/// source's element type by discarding the imaginary component.
/// _Complex short -> short
CK_IntegralComplexToReal,
/// \brief Converts an integral complex to bool by comparing against
/// 0+0i.
CK_IntegralComplexToBoolean,
/// \brief Converts between different integral complex types.
/// _Complex char -> _Complex long long
/// _Complex unsigned int -> _Complex signed int
CK_IntegralComplexCast,
/// \brief Converts from an integral complex to a floating complex.
/// _Complex unsigned -> _Complex float
CK_IntegralComplexToFloatingComplex,
/// \brief [ARC] Produces a retainable object pointer so that it may
/// be consumed, e.g. by being passed to a consuming parameter.
/// Calls objc_retain.
CK_ARCProduceObject,
/// \brief [ARC] Consumes a retainable object pointer that has just
/// been produced, e.g. as the return value of a retaining call.
/// Enters a cleanup to call objc_release at some indefinite time.
CK_ARCConsumeObject,
/// \brief [ARC] Reclaim a retainable object pointer object that may
/// have been produced and autoreleased as part of a function return
/// sequence.
CK_ARCReclaimReturnedObject,
/// \brief [ARC] Causes a value of block type to be copied to the
/// heap, if it is not already there. A number of other operations
/// in ARC cause blocks to be copied; this is for cases where that
/// would not otherwise be guaranteed, such as when casting to a
/// non-block pointer type.
CK_ARCExtendBlockObject
};
#define CK_Invalid ((CastKind) -1)
enum BinaryOperatorKind {
// Operators listed in order of precedence.
// Note that additions to this should also update the StmtVisitor class.
BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators.
BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators.
BO_Add, BO_Sub, // [C99 6.5.6] Additive operators.
BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators.
BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators.
BO_EQ, BO_NE, // [C99 6.5.9] Equality operators.
BO_And, // [C99 6.5.10] Bitwise AND operator.
BO_Xor, // [C99 6.5.11] Bitwise XOR operator.
BO_Or, // [C99 6.5.12] Bitwise OR operator.
BO_LAnd, // [C99 6.5.13] Logical AND operator.
BO_LOr, // [C99 6.5.14] Logical OR operator.
BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators.
BO_DivAssign, BO_RemAssign,
BO_AddAssign, BO_SubAssign,
BO_ShlAssign, BO_ShrAssign,
BO_AndAssign, BO_XorAssign,
BO_OrAssign,
BO_Comma // [C99 6.5.17] Comma operator.
};
enum UnaryOperatorKind {
// Note that additions to this should also update the StmtVisitor class.
UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement
UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement
UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection
UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
UO_Extension // __extension__ marker.
};
/// \brief The kind of bridging performed by the Objective-C bridge cast.
enum ObjCBridgeCastKind {
/// \brief Bridging via __bridge, which does nothing but reinterpret
/// the bits.
OBC_Bridge,
/// \brief Bridging via __bridge_transfer, which transfers ownership of an
/// Objective-C pointer into ARC.
OBC_BridgeTransfer,
/// \brief Bridging via __bridge_retain, which makes an ARC object available
/// as a +1 C pointer.
OBC_BridgeRetained
};
}
#endif

View File

@@ -24,16 +24,8 @@ public:
ParentMap(Stmt* ASTRoot);
~ParentMap();
/// \brief Adds and/or updates the parent/child-relations of the complete
/// stmt tree of S. All children of S including indirect descendants are
/// visited and updated or inserted but not the parents of S.
void addStmt(Stmt* S);
Stmt *getParent(Stmt*) const;
Stmt *getParentIgnoreParens(Stmt *) const;
Stmt *getParentIgnoreParenCasts(Stmt *) const;
Stmt *getParentIgnoreParenImpCasts(Stmt *) const;
Stmt *getOuterParenParent(Stmt *) const;
const Stmt *getParent(const Stmt* S) const {
return getParent(const_cast<Stmt*>(S));
@@ -43,10 +35,6 @@ public:
return getParentIgnoreParens(const_cast<Stmt*>(S));
}
const Stmt *getParentIgnoreParenCasts(const Stmt *S) const {
return getParentIgnoreParenCasts(const_cast<Stmt*>(S));
}
bool hasParent(Stmt* S) const {
return getParent(S) != 0;
}

View File

@@ -14,8 +14,9 @@
#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
#define LLVM_CLANG_AST_PRETTY_PRINTER_H
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/LLVM.h"
namespace llvm {
class raw_ostream;
}
namespace clang {
@@ -26,7 +27,7 @@ class LangOptions;
class PrinterHelper {
public:
virtual ~PrinterHelper();
virtual bool handledStmt(Stmt* E, raw_ostream& OS) = 0;
virtual bool handledStmt(Stmt* E, llvm::raw_ostream& OS) = 0;
};
/// \brief Describes how types, statements, expressions, and
@@ -35,17 +36,14 @@ struct PrintingPolicy {
/// \brief Create a default printing policy for C.
PrintingPolicy(const LangOptions &LO)
: Indentation(2), LangOpts(LO), SuppressSpecifiers(false),
SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false),
SuppressInitializers(false),
Dump(false), ConstantArraySizeAsWritten(false),
AnonymousTagLocations(true), SuppressStrongLifetime(false),
Bool(LO.Bool) { }
SuppressTag(false), SuppressTagKind(false), SuppressScope(false),
Dump(false), ConstantArraySizeAsWritten(false) { }
/// \brief The number of spaces to use to indent each line.
unsigned Indentation : 8;
/// \brief What language we're printing.
LangOptions LangOpts;
const LangOptions &LangOpts;
/// \brief Whether we should suppress printing of the actual specifiers for
/// the given type or declaration.
@@ -63,16 +61,6 @@ struct PrintingPolicy {
/// "const int" type specifier and instead only print the "*y".
bool SuppressSpecifiers : 1;
/// \brief Whether type printing should skip printing the tag keyword.
///
/// This is used when printing the inner type of elaborated types,
/// (as the tag keyword is part of the elaborated type):
///
/// \code
/// struct Geometry::Point;
/// \endcode
bool SuppressTagKeyword : 1;
/// \brief Whether type printing should skip printing the actual tag type.
///
/// This is used when the caller needs to print a tag definition in front
@@ -83,22 +71,13 @@ struct PrintingPolicy {
/// \endcode
bool SuppressTag : 1;
/// \brief If we are printing a tag type, suppresses printing of the
/// kind of tag, e.g., "struct", "union", "enum".
bool SuppressTagKind : 1;
/// \brief Suppresses printing of scope specifiers.
bool SuppressScope : 1;
/// \brief Suppress printing of variable initializers.
///
/// This flag is used when printing the loop variable in a for-range
/// statement. For example, given:
///
/// \code
/// for (auto x : coll)
/// \endcode
///
/// SuppressInitializers will be true when printing "auto x", so that the
/// internal initializer constructed for x will not be printed.
bool SuppressInitializers : 1;
/// \brief True when we are "dumping" rather than "pretty-printing",
/// where dumping involves printing the internal details of the AST
/// and pretty-printing involves printing something similar to
@@ -122,19 +101,6 @@ struct PrintingPolicy {
/// char a[9] = "A string";
/// \endcode
bool ConstantArraySizeAsWritten : 1;
/// \brief When printing an anonymous tag name, also print the location of
/// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just
/// prints "<anonymous>" for the name.
bool AnonymousTagLocations : 1;
/// \brief When true, suppress printing of the __strong lifetime qualifier in
/// ARC.
unsigned SuppressStrongLifetime : 1;
/// \brief Whether we can use 'bool' rather than '_Bool', even if the language
/// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
unsigned Bool : 1;
};
} // end namespace clang

Some files were not shown because too many files have changed in this diff Show More