Vendor import of clang release_60 branch r321788:
https://llvm.org/svn/llvm-project/cfe/branches/release_60@321788
This commit is contained in:
parent
55e6d896ad
commit
ead8c8e4f1
File diff suppressed because it is too large
Load Diff
@ -120,6 +120,10 @@ Output path for the plist report
|
||||
|
||||
.. option:: -compatibility\_version<arg>
|
||||
|
||||
.. option:: --config <arg>
|
||||
|
||||
Specifies configuration file
|
||||
|
||||
.. option:: --constant-cfstrings
|
||||
|
||||
.. option:: -coverage, --coverage
|
||||
@ -1545,6 +1549,10 @@ Enable ARC-style weak references in Objective-C
|
||||
|
||||
OpenMP target code is compiled as relocatable using the -c flag. For OpenMP targets the code is relocatable by default.
|
||||
|
||||
.. option:: -fopenmp-simd, -fno-openmp-simd
|
||||
|
||||
Emit OpenMP code only for SIMD-based constructs.
|
||||
|
||||
.. option:: -fopenmp-use-tls
|
||||
|
||||
.. option:: -fopenmp-version=<arg>
|
||||
@ -1998,7 +2006,7 @@ Link stack frames through backchain on System Z
|
||||
|
||||
.. option:: -mconsole<arg>
|
||||
|
||||
.. option:: -mcpu=<arg>, -mv4 (equivalent to -mcpu=hexagonv4), -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62)
|
||||
.. option:: -mcpu=<arg>, -mv4 (equivalent to -mcpu=hexagonv4), -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65)
|
||||
|
||||
.. option:: -mdefault-build-attributes<arg>, -mno-default-build-attributes<arg>
|
||||
|
||||
@ -2328,6 +2336,8 @@ X86
|
||||
|
||||
.. option:: -mavx2, -mno-avx2
|
||||
|
||||
.. option:: -mavx512bitalg, -mno-avx512bitalg
|
||||
|
||||
.. option:: -mavx512bw, -mno-avx512bw
|
||||
|
||||
.. option:: -mavx512cd, -mno-avx512cd
|
||||
@ -2344,8 +2354,12 @@ X86
|
||||
|
||||
.. option:: -mavx512vbmi, -mno-avx512vbmi
|
||||
|
||||
.. option:: -mavx512vbmi2, -mno-avx512vbmi2
|
||||
|
||||
.. option:: -mavx512vl, -mno-avx512vl
|
||||
|
||||
.. option:: -mavx512vnni, -mno-avx512vnni
|
||||
|
||||
.. option:: -mavx512vpopcntdq, -mno-avx512vpopcntdq
|
||||
|
||||
.. option:: -mbmi, -mno-bmi
|
||||
@ -2370,6 +2384,8 @@ X86
|
||||
|
||||
.. option:: -mfxsr, -mno-fxsr
|
||||
|
||||
.. option:: -mgfni, -mno-gfni
|
||||
|
||||
.. option:: -mibt, -mno-ibt
|
||||
|
||||
.. option:: -mlwp, -mno-lwp
|
||||
@ -2424,6 +2440,10 @@ X86
|
||||
|
||||
.. option:: -mtbm, -mno-tbm
|
||||
|
||||
.. option:: -mvaes, -mno-vaes
|
||||
|
||||
.. option:: -mvpclmulqdq, -mno-vpclmulqdq
|
||||
|
||||
.. option:: -mx87, -m80387, -mno-x87
|
||||
|
||||
.. option:: -mxop, -mno-xop
|
||||
|
@ -168,8 +168,8 @@ Attribute Changes in Clang
|
||||
Windows Support
|
||||
---------------
|
||||
|
||||
Clang's support for building native Windows programs ...
|
||||
|
||||
- Clang now has initial, preliminary support for targeting Windows on
|
||||
ARM64.
|
||||
|
||||
C Language Changes in Clang
|
||||
---------------------------
|
||||
@ -209,7 +209,18 @@ OpenCL C Language Changes in Clang
|
||||
OpenMP Support in Clang
|
||||
----------------------------------
|
||||
|
||||
...
|
||||
- Added options `-f[no]-openmp-simd` that support code emission only foe OpenMP
|
||||
SIMD-based directives, like `#pragma omp simd`, `#pragma omp parallel for simd`
|
||||
etc. The code is emitted only for simd-based part of the combined directives
|
||||
and clauses.
|
||||
|
||||
- Added support for almost all target-based directives except for
|
||||
`#pragma omp target teams distribute parallel for [simd]`. Although, please
|
||||
note that `depend` clauses on target-based directives are not supported yet.
|
||||
Clang supports offloading to X86_64, AArch64 and PPC64[LE] devices.
|
||||
|
||||
- Added support for `reduction`-based clauses on `task`-based directives from
|
||||
upcoming OpenMP 5.0.
|
||||
|
||||
Internal API Changes
|
||||
--------------------
|
||||
|
@ -694,6 +694,79 @@ a special character, which is the convention used by GNU Make. The -MV
|
||||
option tells Clang to put double-quotes around the entire filename, which
|
||||
is the convention used by NMake and Jom.
|
||||
|
||||
Configuration files
|
||||
-------------------
|
||||
|
||||
Configuration files group command-line options and allow all of them to be
|
||||
specified just by referencing the configuration file. They may be used, for
|
||||
example, to collect options required to tune compilation for particular
|
||||
target, such as -L, -I, -l, --sysroot, codegen options, etc.
|
||||
|
||||
The command line option `--config` can be used to specify configuration
|
||||
file in a Clang invocation. For example:
|
||||
|
||||
::
|
||||
|
||||
clang --config /home/user/cfgs/testing.txt
|
||||
clang --config debug.cfg
|
||||
|
||||
If the provided argument contains a directory separator, it is considered as
|
||||
a file path, and options are read from that file. Otherwise the argument is
|
||||
treated as a file name and is searched for sequentially in the directories:
|
||||
|
||||
- user directory,
|
||||
- system directory,
|
||||
- the directory where Clang executable resides.
|
||||
|
||||
Both user and system directories for configuration files are specified during
|
||||
clang build using CMake parameters, CLANG_CONFIG_FILE_USER_DIR and
|
||||
CLANG_CONFIG_FILE_SYSTEM_DIR respectively. The first file found is used. It is
|
||||
an error if the required file cannot be found.
|
||||
|
||||
Another way to specify a configuration file is to encode it in executable name.
|
||||
For example, if the Clang executable is named `armv7l-clang` (it may be a
|
||||
symbolic link to `clang`), then Clang will search for file `armv7l.cfg` in the
|
||||
directory where Clang resides.
|
||||
|
||||
If a driver mode is specified in invocation, Clang tries to find a file specific
|
||||
for the specified mode. For example, if the executable file is named
|
||||
`x86_64-clang-cl`, Clang first looks for `x86_64-cl.cfg` and if it is not found,
|
||||
looks for `x86_64.cfg`.
|
||||
|
||||
If the command line contains options that effectively change target architecture
|
||||
(these are -m32, -EL, and some others) and the configuration file starts with an
|
||||
architecture name, Clang tries to load the configuration file for the effective
|
||||
architecture. For example, invocation:
|
||||
|
||||
::
|
||||
|
||||
x86_64-clang -m32 abc.c
|
||||
|
||||
causes Clang search for a file `i368.cfg` first, and if no such file is found,
|
||||
Clang looks for the file `x86_64.cfg`.
|
||||
|
||||
The configuration file consists of command-line options specified on one or
|
||||
more lines. Lines composed of whitespace characters only are ignored as well as
|
||||
lines in which the first non-blank character is `#`. Long options may be split
|
||||
between several lines by a trailing backslash. Here is example of a
|
||||
configuration file:
|
||||
|
||||
::
|
||||
|
||||
# Several options on line
|
||||
-c --target=x86_64-unknown-linux-gnu
|
||||
|
||||
# Long option split between lines
|
||||
-I/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../\
|
||||
include/c++/5.4.0
|
||||
|
||||
# other config files may be included
|
||||
@linux.options
|
||||
|
||||
Files included by `@file` directives in configuration files are resolved
|
||||
relative to the including file. For example, if a configuration file
|
||||
`~/.llvm/target.cfg` contains the directive `@os/linux.opts`, the file
|
||||
`linux.opts` is searched for in the directory `~/.llvm/os`.
|
||||
|
||||
Language and Target-Independent Features
|
||||
========================================
|
||||
@ -2042,6 +2115,11 @@ directives, and ``#pragma omp taskgroup`` directive.
|
||||
Use `-fopenmp` to enable OpenMP. Support for OpenMP can be disabled with
|
||||
`-fno-openmp`.
|
||||
|
||||
Use `-fopenmp-simd` to enable OpenMP simd features only, without linking
|
||||
the runtime library; for combined constructs
|
||||
(e.g. ``#pragma omp parallel for simd``) the non-simd directives and clauses
|
||||
will be ignored. This can be disabled with `-fno-openmp-simd`.
|
||||
|
||||
Controlling implementation limits
|
||||
---------------------------------
|
||||
|
||||
@ -2654,6 +2732,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
|
||||
/Gd Set __cdecl as a default calling convention
|
||||
/GF- Disable string pooling
|
||||
/GR- Disable emission of RTTI data
|
||||
/Gregcall Set __regcall as a default calling convention
|
||||
/GR Enable emission of RTTI data
|
||||
/Gr Set __fastcall as a default calling convention
|
||||
/GS- Disable buffer security check
|
||||
@ -2710,7 +2789,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
|
||||
/W2 Enable -Wall
|
||||
/W3 Enable -Wall
|
||||
/W4 Enable -Wall and -Wextra
|
||||
/Wall Enable -Wall and -Wextra
|
||||
/Wall Enable -Weverything
|
||||
/WX- Do not treat warnings as errors
|
||||
/WX Treat warnings as errors
|
||||
/w Disable all warnings
|
||||
@ -2767,6 +2846,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
|
||||
Disable specified features of coverage instrumentation for Sanitizers
|
||||
-fno-sanitize-memory-track-origins
|
||||
Disable origins tracking in MemorySanitizer
|
||||
-fno-sanitize-memory-use-after-dtor
|
||||
Disable use-after-destroy detection in MemorySanitizer
|
||||
-fno-sanitize-recover=<value>
|
||||
Disable recovery for specified sanitizers
|
||||
-fno-sanitize-stats Disable sanitizer statistics gathering.
|
||||
@ -2797,6 +2878,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
|
||||
Path to blacklist file for sanitizers
|
||||
-fsanitize-cfi-cross-dso
|
||||
Enable control flow integrity (CFI) checks for cross-DSO calls.
|
||||
-fsanitize-cfi-icall-generalize-pointers
|
||||
Generalize pointers in CFI indirect call type signature checks
|
||||
-fsanitize-coverage=<value>
|
||||
Specify the type of coverage instrumentation for Sanitizers
|
||||
-fsanitize-memory-track-origins=<value>
|
||||
@ -2820,6 +2903,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
|
||||
-fsanitize=<check> Turn on runtime checks for various forms of undefined or suspicious
|
||||
behavior. See user manual for available checks
|
||||
-fstandalone-debug Emit full debug info for all types used by the program
|
||||
-fwhole-program-vtables Enables whole-program vtable optimization. Requires -flto
|
||||
-gcodeview Generate CodeView debug information
|
||||
-gline-tables-only Emit debug line number tables only
|
||||
-miamcu Use Intel MCU ABI
|
||||
@ -2828,6 +2912,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
|
||||
-Qunused-arguments Don't emit warning for unused driver arguments
|
||||
-R<remark> Enable the specified remark
|
||||
--target=<value> Generate code for the given target
|
||||
--version Print version information
|
||||
-v Show commands to run and use verbose output
|
||||
-W<warning> Enable the specified warning
|
||||
-Xclang <arg> Pass <arg> to the clang compiler
|
||||
|
@ -193,16 +193,20 @@ class OMPExecutableDirective : public Stmt {
|
||||
bool hasAssociatedStmt() const { return NumChildren > 0; }
|
||||
|
||||
/// \brief Returns statement associated with the directive.
|
||||
Stmt *getAssociatedStmt() const {
|
||||
const Stmt *getAssociatedStmt() const {
|
||||
assert(hasAssociatedStmt() && "no associated statement.");
|
||||
return const_cast<Stmt *>(*child_begin());
|
||||
return *child_begin();
|
||||
}
|
||||
Stmt *getAssociatedStmt() {
|
||||
assert(hasAssociatedStmt() && "no associated statement.");
|
||||
return *child_begin();
|
||||
}
|
||||
|
||||
/// \brief Returns the captured statement associated with the
|
||||
/// component region within the (combined) directive.
|
||||
//
|
||||
// \param RegionKind Component region kind.
|
||||
CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
|
||||
const CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
|
||||
SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
|
||||
getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
|
||||
assert(std::any_of(
|
||||
|
@ -112,6 +112,18 @@ def err_drv_invalid_argument_to_fdebug_prefix_map : Error<
|
||||
"invalid argument '%0' to -fdebug-prefix-map">;
|
||||
def err_drv_malformed_sanitizer_blacklist : Error<
|
||||
"malformed sanitizer blacklist: '%0'">;
|
||||
def err_drv_duplicate_config : Error<
|
||||
"no more than one option '--config' is allowed">;
|
||||
def err_drv_config_file_not_exist : Error<
|
||||
"configuration file '%0' does not exist">;
|
||||
def err_drv_config_file_not_found : Error<
|
||||
"configuration file '%0' cannot be found">;
|
||||
def note_drv_config_file_searched_in : Note<
|
||||
"was searched for in the directory: %0">;
|
||||
def err_drv_cannot_read_config_file : Error<
|
||||
"cannot read configuration file '%0'">;
|
||||
def err_drv_nested_config_file: Error<
|
||||
"option '--config' is not allowed inside configuration file">;
|
||||
|
||||
def err_target_unsupported_arch
|
||||
: Error<"the target architecture '%0' is not supported by the target '%1'">;
|
||||
|
@ -435,12 +435,16 @@ def StringCompare : DiagGroup<"string-compare">;
|
||||
def StringPlusInt : DiagGroup<"string-plus-int">;
|
||||
def StringPlusChar : DiagGroup<"string-plus-char">;
|
||||
def StrncatSize : DiagGroup<"strncat-size">;
|
||||
def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">;
|
||||
def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">;
|
||||
def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">;
|
||||
def TautologicalInRangeCompare : DiagGroup<"tautological-constant-in-range-compare",
|
||||
[TautologicalTypeLimitCompare,
|
||||
TautologicalUnsignedZeroCompare,
|
||||
TautologicalUnsignedEnumZeroCompare]>;
|
||||
def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">;
|
||||
def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare",
|
||||
[TautologicalUnsignedZeroCompare,
|
||||
TautologicalUnsignedEnumZeroCompare,
|
||||
[TautologicalInRangeCompare,
|
||||
TautologicalOutOfRangeCompare]>;
|
||||
def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">;
|
||||
def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
|
||||
@ -715,6 +719,7 @@ def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
|
||||
def Move : DiagGroup<"move", [PessimizingMove, RedundantMove, SelfMove]>;
|
||||
|
||||
def Extra : DiagGroup<"extra", [
|
||||
TautologicalInRangeCompare,
|
||||
MissingFieldInitializers,
|
||||
IgnoredQualifiers,
|
||||
InitializerOverrides,
|
||||
|
@ -1589,12 +1589,20 @@ def err_non_virtual_pure : Error<
|
||||
def ext_pure_function_definition : ExtWarn<
|
||||
"function definition with pure-specifier is a Microsoft extension">,
|
||||
InGroup<MicrosoftPureDefinition>;
|
||||
def err_implicit_object_parameter_init : Error<
|
||||
"cannot initialize object parameter of type %0 with an expression "
|
||||
"of type %1">;
|
||||
def err_qualified_member_of_unrelated : Error<
|
||||
"%q0 is not a member of class %1">;
|
||||
|
||||
def err_member_function_call_bad_cvr : Error<
|
||||
"'this' argument to member function %0 has type %1, but function is not marked "
|
||||
"%select{const|restrict|const or restrict|volatile|const or volatile|"
|
||||
"volatile or restrict|const, volatile, or restrict}2">;
|
||||
def err_member_function_call_bad_ref : Error<
|
||||
"'this' argument to member function %0 is an %select{lvalue|rvalue}1, "
|
||||
"but function has %select{non-const lvalue|rvalue}2 ref-qualifier">;
|
||||
def err_member_function_call_bad_type : Error<
|
||||
"cannot initialize object parameter of type %0 with an expression "
|
||||
"of type %1">;
|
||||
|
||||
def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
|
||||
"call to pure virtual member function %0 has undefined behavior; "
|
||||
"overrides of %0 in subclasses are not available in the "
|
||||
@ -1815,10 +1823,6 @@ def warn_temporary_array_to_pointer_decay : Warning<
|
||||
def err_init_list_bad_dest_type : Error<
|
||||
"%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
|
||||
"list">;
|
||||
def err_member_function_call_bad_cvr : Error<"member function %0 not viable: "
|
||||
"'this' argument has type %1, but function is not marked "
|
||||
"%select{const|restrict|const or restrict|volatile|const or volatile|"
|
||||
"volatile or restrict|const, volatile, or restrict}2">;
|
||||
|
||||
def err_reference_bind_to_bitfield : Error<
|
||||
"%select{non-const|volatile}0 reference cannot bind to "
|
||||
@ -5942,15 +5946,15 @@ def note_typecheck_assign_const : Note<
|
||||
def warn_unsigned_always_true_comparison : Warning<
|
||||
"result of comparison of %select{%3|unsigned expression}0 %2 "
|
||||
"%select{unsigned expression|%3}0 is always %4">,
|
||||
InGroup<TautologicalUnsignedZeroCompare>;
|
||||
InGroup<TautologicalUnsignedZeroCompare>, DefaultIgnore;
|
||||
def warn_unsigned_enum_always_true_comparison : Warning<
|
||||
"result of comparison of %select{%3|unsigned enum expression}0 %2 "
|
||||
"%select{unsigned enum expression|%3}0 is always %4">,
|
||||
InGroup<TautologicalUnsignedEnumZeroCompare>;
|
||||
InGroup<TautologicalUnsignedEnumZeroCompare>, DefaultIgnore;
|
||||
def warn_tautological_constant_compare : Warning<
|
||||
"result of comparison %select{%3|%1}0 %2 "
|
||||
"%select{%1|%3}0 is always %4">,
|
||||
InGroup<TautologicalConstantCompare>;
|
||||
InGroup<TautologicalTypeLimitCompare>, DefaultIgnore;
|
||||
|
||||
def warn_mixed_sign_comparison : Warning<
|
||||
"comparison of integers of different signs: %0 and %1">,
|
||||
|
@ -194,6 +194,7 @@ LANGOPT(NativeHalfArgsAndReturns, 1, 0, "Native half args and returns")
|
||||
LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")
|
||||
LANGOPT(CUDA , 1, 0, "CUDA")
|
||||
LANGOPT(OpenMP , 32, 0, "OpenMP support and version of OpenMP (31, 40 or 45)")
|
||||
LANGOPT(OpenMPSimd , 1, 0, "Use SIMD only OpenMP support.")
|
||||
LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
|
||||
LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device")
|
||||
LANGOPT(RenderScript , 1, 0, "RenderScript")
|
||||
|
@ -35,6 +35,10 @@
|
||||
/* Directories clang will search for headers */
|
||||
#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
|
||||
|
||||
/* Directories clang will search for configuration files */
|
||||
#cmakedefine CLANG_CONFIG_FILE_SYSTEM_DIR "${CLANG_CONFIG_FILE_SYSTEM_DIR}"
|
||||
#cmakedefine CLANG_CONFIG_FILE_USER_DIR "${CLANG_CONFIG_FILE_USER_DIR}"
|
||||
|
||||
/* Default <path> to all compiler invocations for --sysroot=<path>. */
|
||||
#define DEFAULT_SYSROOT "${DEFAULT_SYSROOT}"
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "clang/Driver/Util.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
@ -26,14 +28,6 @@
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
|
||||
namespace opt {
|
||||
class Arg;
|
||||
class ArgList;
|
||||
class DerivedArgList;
|
||||
class InputArgList;
|
||||
class OptTable;
|
||||
}
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
@ -138,6 +132,12 @@ class Driver {
|
||||
/// The path to the compiler resource directory.
|
||||
std::string ResourceDir;
|
||||
|
||||
/// System directory for config files.
|
||||
std::string SystemConfigDir;
|
||||
|
||||
/// User directory for config files.
|
||||
std::string UserConfigDir;
|
||||
|
||||
/// A prefix directory used to emulate a limited subset of GCC's '-Bprefix'
|
||||
/// functionality.
|
||||
/// FIXME: This type of customization should be removed in favor of the
|
||||
@ -208,6 +208,21 @@ class Driver {
|
||||
/// Name to use when invoking gcc/g++.
|
||||
std::string CCCGenericGCCName;
|
||||
|
||||
/// Name of configuration file if used.
|
||||
std::string ConfigFile;
|
||||
|
||||
/// Allocator for string saver.
|
||||
llvm::BumpPtrAllocator Alloc;
|
||||
|
||||
/// Object that stores strings read from configuration file.
|
||||
llvm::StringSaver Saver;
|
||||
|
||||
/// Arguments originated from configuration file.
|
||||
std::unique_ptr<llvm::opt::InputArgList> CfgOptions;
|
||||
|
||||
/// Arguments originated from command line.
|
||||
std::unique_ptr<llvm::opt::InputArgList> CLOptions;
|
||||
|
||||
/// Whether to check that input files exist when constructing compilation
|
||||
/// jobs.
|
||||
unsigned CheckInputsExist : 1;
|
||||
@ -277,6 +292,8 @@ class Driver {
|
||||
/// Name to use when invoking gcc/g++.
|
||||
const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }
|
||||
|
||||
const std::string &getConfigFile() const { return ConfigFile; }
|
||||
|
||||
const llvm::opt::OptTable &getOpts() const { return *Opts; }
|
||||
|
||||
const DiagnosticsEngine &getDiags() const { return Diags; }
|
||||
@ -493,6 +510,18 @@ class Driver {
|
||||
LTOKind getLTOMode() const { return LTOMode; }
|
||||
|
||||
private:
|
||||
|
||||
/// Tries to load options from configuration file.
|
||||
///
|
||||
/// \returns true if error occurred.
|
||||
bool loadConfigFile();
|
||||
|
||||
/// Read options from the specified file.
|
||||
///
|
||||
/// \param [in] FileName File to read.
|
||||
/// \returns true, if error occurred while reading.
|
||||
bool readConfigFile(StringRef FileName);
|
||||
|
||||
/// Set the driver mode (cl, gcc, etc) from an option string of the form
|
||||
/// --driver-mode=<mode>.
|
||||
void setDriverModeFromOption(StringRef Opt);
|
||||
|
@ -519,6 +519,12 @@ def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-round
|
||||
def client__name : JoinedOrSeparate<["-"], "client_name">;
|
||||
def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>;
|
||||
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
|
||||
def config : Separate<["--"], "config">, Flags<[DriverOption]>,
|
||||
HelpText<"Specifies configuration file">;
|
||||
def config_system_dir_EQ : Joined<["--"], "config-system-dir=">, Flags<[DriverOption, HelpHidden]>,
|
||||
HelpText<"System directory for configuration files">;
|
||||
def config_user_dir_EQ : Joined<["--"], "config-user-dir=">, Flags<[DriverOption, HelpHidden]>,
|
||||
HelpText<"User directory for configuration files">;
|
||||
def coverage : Flag<["-", "--"], "coverage">, Flags<[CoreOption]>;
|
||||
def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>;
|
||||
def current__version : JoinedOrSeparate<["-"], "current_version">;
|
||||
@ -1375,6 +1381,10 @@ def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">, Grou
|
||||
HelpText<"OpenMP target code is compiled as relocatable using the -c flag. For OpenMP targets the code is relocatable by default.">;
|
||||
def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
|
||||
HelpText<"Do not compile OpenMP target code as relocatable.">;
|
||||
def fopenmp_simd : Flag<["-"], "fopenmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
|
||||
HelpText<"Emit OpenMP code only for SIMD-based constructs.">;
|
||||
def fno_openmp_simd : Flag<["-"], "fno-openmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
|
||||
HelpText<"Disable OpenMP code for SIMD-based constructs.">;
|
||||
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
|
||||
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
|
||||
def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
|
||||
|
@ -1447,7 +1447,7 @@ class Parser : public CodeCompletionHandler {
|
||||
|
||||
bool isTokIdentifier_in() const;
|
||||
|
||||
ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, Declarator::TheContext Ctx,
|
||||
ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, DeclaratorContext Ctx,
|
||||
ParsedAttributes *ParamAttrs);
|
||||
void ParseObjCMethodRequirement();
|
||||
Decl *ParseObjCMethodPrototype(
|
||||
@ -1856,7 +1856,7 @@ class Parser : public CodeCompletionHandler {
|
||||
/// A context for parsing declaration specifiers. TODO: flesh this
|
||||
/// out, there are other significant restrictions on specifiers than
|
||||
/// would be best implemented in the parser.
|
||||
enum DeclSpecContext {
|
||||
enum class DeclSpecContext {
|
||||
DSC_normal, // normal context
|
||||
DSC_class, // class context, enables 'friend'
|
||||
DSC_type_specifier, // C++ type-specifier-seq or C specifier-qualifier-list
|
||||
@ -1873,18 +1873,18 @@ class Parser : public CodeCompletionHandler {
|
||||
/// trailing-type-specifier)?
|
||||
static bool isTypeSpecifier(DeclSpecContext DSC) {
|
||||
switch (DSC) {
|
||||
case DSC_normal:
|
||||
case DSC_template_param:
|
||||
case DSC_class:
|
||||
case DSC_top_level:
|
||||
case DSC_objc_method_result:
|
||||
case DSC_condition:
|
||||
case DeclSpecContext::DSC_normal:
|
||||
case DeclSpecContext::DSC_template_param:
|
||||
case DeclSpecContext::DSC_class:
|
||||
case DeclSpecContext::DSC_top_level:
|
||||
case DeclSpecContext::DSC_objc_method_result:
|
||||
case DeclSpecContext::DSC_condition:
|
||||
return false;
|
||||
|
||||
case DSC_template_type_arg:
|
||||
case DSC_type_specifier:
|
||||
case DSC_trailing:
|
||||
case DSC_alias_declaration:
|
||||
case DeclSpecContext::DSC_template_type_arg:
|
||||
case DeclSpecContext::DSC_type_specifier:
|
||||
case DeclSpecContext::DSC_trailing:
|
||||
case DeclSpecContext::DSC_alias_declaration:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("Missing DeclSpecContext case");
|
||||
@ -1894,18 +1894,18 @@ class Parser : public CodeCompletionHandler {
|
||||
/// deduction?
|
||||
static bool isClassTemplateDeductionContext(DeclSpecContext DSC) {
|
||||
switch (DSC) {
|
||||
case DSC_normal:
|
||||
case DSC_template_param:
|
||||
case DSC_class:
|
||||
case DSC_top_level:
|
||||
case DSC_condition:
|
||||
case DSC_type_specifier:
|
||||
case DeclSpecContext::DSC_normal:
|
||||
case DeclSpecContext::DSC_template_param:
|
||||
case DeclSpecContext::DSC_class:
|
||||
case DeclSpecContext::DSC_top_level:
|
||||
case DeclSpecContext::DSC_condition:
|
||||
case DeclSpecContext::DSC_type_specifier:
|
||||
return true;
|
||||
|
||||
case DSC_objc_method_result:
|
||||
case DSC_template_type_arg:
|
||||
case DSC_trailing:
|
||||
case DSC_alias_declaration:
|
||||
case DeclSpecContext::DSC_objc_method_result:
|
||||
case DeclSpecContext::DSC_template_type_arg:
|
||||
case DeclSpecContext::DSC_trailing:
|
||||
case DeclSpecContext::DSC_alias_declaration:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("Missing DeclSpecContext case");
|
||||
@ -1920,15 +1920,16 @@ class Parser : public CodeCompletionHandler {
|
||||
bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); }
|
||||
};
|
||||
|
||||
DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
|
||||
DeclGroupPtrTy ParseDeclaration(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
ParsedAttributesWithRange &attrs);
|
||||
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
|
||||
DeclGroupPtrTy ParseSimpleDeclaration(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
ParsedAttributesWithRange &attrs,
|
||||
bool RequireSemi,
|
||||
ForRangeInit *FRI = nullptr);
|
||||
bool MightBeDeclarator(unsigned Context);
|
||||
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
|
||||
bool MightBeDeclarator(DeclaratorContext Context);
|
||||
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, DeclaratorContext Context,
|
||||
SourceLocation *DeclEnd = nullptr,
|
||||
ForRangeInit *FRI = nullptr);
|
||||
Decl *ParseDeclarationAfterDeclarator(Declarator &D,
|
||||
@ -1951,21 +1952,24 @@ class Parser : public CodeCompletionHandler {
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
AccessSpecifier AS, DeclSpecContext DSC,
|
||||
ParsedAttributesWithRange &Attrs);
|
||||
DeclSpecContext getDeclSpecContextFromDeclaratorContext(unsigned Context);
|
||||
void ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
DeclSpecContext
|
||||
getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context);
|
||||
void ParseDeclarationSpecifiers(
|
||||
DeclSpec &DS,
|
||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
||||
AccessSpecifier AS = AS_none,
|
||||
DeclSpecContext DSC = DSC_normal,
|
||||
DeclSpecContext DSC = DeclSpecContext::DSC_normal,
|
||||
LateParsedAttrList *LateAttrs = nullptr);
|
||||
bool DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
|
||||
DeclSpecContext DSContext,
|
||||
bool DiagnoseMissingSemiAfterTagDefinition(
|
||||
DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext,
|
||||
LateParsedAttrList *LateAttrs = nullptr);
|
||||
|
||||
void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none,
|
||||
DeclSpecContext DSC = DSC_normal);
|
||||
void ParseSpecifierQualifierList(
|
||||
DeclSpec &DS, AccessSpecifier AS = AS_none,
|
||||
DeclSpecContext DSC = DeclSpecContext::DSC_normal);
|
||||
|
||||
void ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
|
||||
Declarator::TheContext Context);
|
||||
DeclaratorContext Context);
|
||||
|
||||
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
@ -2161,8 +2165,8 @@ class Parser : public CodeCompletionHandler {
|
||||
|
||||
public:
|
||||
TypeResult ParseTypeName(SourceRange *Range = nullptr,
|
||||
Declarator::TheContext Context
|
||||
= Declarator::TypeNameContext,
|
||||
DeclaratorContext Context
|
||||
= DeclaratorContext::TypeNameContext,
|
||||
AccessSpecifier AS = AS_none,
|
||||
Decl **OwnedType = nullptr,
|
||||
ParsedAttributes *Attrs = nullptr);
|
||||
@ -2512,7 +2516,8 @@ class Parser : public CodeCompletionHandler {
|
||||
|
||||
void DiagnoseUnexpectedNamespace(NamedDecl *Context);
|
||||
|
||||
DeclGroupPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
|
||||
DeclGroupPtrTy ParseNamespace(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
SourceLocation InlineLoc = SourceLocation());
|
||||
void ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
|
||||
std::vector<IdentifierInfo *> &Ident,
|
||||
@ -2520,12 +2525,12 @@ class Parser : public CodeCompletionHandler {
|
||||
unsigned int index, SourceLocation &InlineLoc,
|
||||
ParsedAttributes &attrs,
|
||||
BalancedDelimiterTracker &Tracker);
|
||||
Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
|
||||
Decl *ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context);
|
||||
Decl *ParseExportDeclaration();
|
||||
DeclGroupPtrTy ParseUsingDirectiveOrDeclaration(
|
||||
unsigned Context, const ParsedTemplateInfo &TemplateInfo,
|
||||
DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
|
||||
SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs);
|
||||
Decl *ParseUsingDirective(unsigned Context,
|
||||
Decl *ParseUsingDirective(DeclaratorContext Context,
|
||||
SourceLocation UsingLoc,
|
||||
SourceLocation &DeclEnd,
|
||||
ParsedAttributes &attrs);
|
||||
@ -2544,8 +2549,8 @@ class Parser : public CodeCompletionHandler {
|
||||
}
|
||||
};
|
||||
|
||||
bool ParseUsingDeclarator(unsigned Context, UsingDeclarator &D);
|
||||
DeclGroupPtrTy ParseUsingDeclaration(unsigned Context,
|
||||
bool ParseUsingDeclarator(DeclaratorContext Context, UsingDeclarator &D);
|
||||
DeclGroupPtrTy ParseUsingDeclaration(DeclaratorContext Context,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
SourceLocation UsingLoc,
|
||||
SourceLocation &DeclEnd,
|
||||
@ -2729,16 +2734,16 @@ class Parser : public CodeCompletionHandler {
|
||||
// C++ 14: Templates [temp]
|
||||
|
||||
// C++ 14.1: Template Parameters [temp.param]
|
||||
Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
|
||||
Decl *ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
AccessSpecifier AS = AS_none,
|
||||
AttributeList *AccessAttrs = nullptr);
|
||||
Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
||||
Decl *ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
AccessSpecifier AS,
|
||||
AttributeList *AccessAttrs);
|
||||
Decl *ParseSingleDeclarationAfterTemplate(
|
||||
unsigned Context,
|
||||
DeclaratorContext Context,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
ParsingDeclRAIIObject &DiagsFromParams,
|
||||
SourceLocation &DeclEnd,
|
||||
@ -2782,7 +2787,7 @@ class Parser : public CodeCompletionHandler {
|
||||
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
|
||||
ParsedTemplateArgument ParseTemplateTemplateArgument();
|
||||
ParsedTemplateArgument ParseTemplateArgument();
|
||||
Decl *ParseExplicitInstantiation(unsigned Context,
|
||||
Decl *ParseExplicitInstantiation(DeclaratorContext Context,
|
||||
SourceLocation ExternLoc,
|
||||
SourceLocation TemplateLoc,
|
||||
SourceLocation &DeclEnd,
|
||||
|
@ -202,7 +202,7 @@ namespace clang {
|
||||
ParsingDeclRAIIObject ParsingRAII;
|
||||
|
||||
public:
|
||||
ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
|
||||
ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, DeclaratorContext C)
|
||||
: Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
|
||||
}
|
||||
|
||||
|
@ -882,15 +882,8 @@ class ObjCDeclSpec {
|
||||
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ unqualified-id that has been parsed.
|
||||
class UnqualifiedId {
|
||||
private:
|
||||
UnqualifiedId(const UnqualifiedId &Other) = delete;
|
||||
const UnqualifiedId &operator=(const UnqualifiedId &) = delete;
|
||||
|
||||
public:
|
||||
/// \brief Describes the kind of unqualified-id parsed.
|
||||
enum IdKind {
|
||||
enum class UnqualifiedIdKind {
|
||||
/// \brief An identifier.
|
||||
IK_Identifier,
|
||||
/// \brief An overloaded operator name, e.g., operator+.
|
||||
@ -911,7 +904,17 @@ class UnqualifiedId {
|
||||
IK_ImplicitSelfParam,
|
||||
/// \brief A deduction-guide name (a template-name)
|
||||
IK_DeductionGuideName
|
||||
} Kind;
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ unqualified-id that has been parsed.
|
||||
class UnqualifiedId {
|
||||
private:
|
||||
UnqualifiedId(const UnqualifiedId &Other) = delete;
|
||||
const UnqualifiedId &operator=(const UnqualifiedId &) = delete;
|
||||
|
||||
public:
|
||||
/// \brief Describes the kind of unqualified-id parsed.
|
||||
UnqualifiedIdKind Kind;
|
||||
|
||||
struct OFI {
|
||||
/// \brief The kind of overloaded operator.
|
||||
@ -967,12 +970,13 @@ class UnqualifiedId {
|
||||
/// \brief The location of the last token that describes this unqualified-id.
|
||||
SourceLocation EndLocation;
|
||||
|
||||
UnqualifiedId() : Kind(IK_Identifier), Identifier(nullptr) { }
|
||||
UnqualifiedId()
|
||||
: Kind(UnqualifiedIdKind::IK_Identifier), Identifier(nullptr) {}
|
||||
|
||||
/// \brief Clear out this unqualified-id, setting it to default (invalid)
|
||||
/// state.
|
||||
void clear() {
|
||||
Kind = IK_Identifier;
|
||||
Kind = UnqualifiedIdKind::IK_Identifier;
|
||||
Identifier = nullptr;
|
||||
StartLocation = SourceLocation();
|
||||
EndLocation = SourceLocation();
|
||||
@ -985,15 +989,15 @@ class UnqualifiedId {
|
||||
bool isInvalid() const { return !isValid(); }
|
||||
|
||||
/// \brief Determine what kind of name we have.
|
||||
IdKind getKind() const { return Kind; }
|
||||
void setKind(IdKind kind) { Kind = kind; }
|
||||
UnqualifiedIdKind getKind() const { return Kind; }
|
||||
void setKind(UnqualifiedIdKind kind) { Kind = kind; }
|
||||
|
||||
/// \brief Specify that this unqualified-id was parsed as an identifier.
|
||||
///
|
||||
/// \param Id the parsed identifier.
|
||||
/// \param IdLoc the location of the parsed identifier.
|
||||
void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
|
||||
Kind = IK_Identifier;
|
||||
Kind = UnqualifiedIdKind::IK_Identifier;
|
||||
Identifier = const_cast<IdentifierInfo *>(Id);
|
||||
StartLocation = EndLocation = IdLoc;
|
||||
}
|
||||
@ -1022,7 +1026,7 @@ class UnqualifiedId {
|
||||
void setConversionFunctionId(SourceLocation OperatorLoc,
|
||||
ParsedType Ty,
|
||||
SourceLocation EndLoc) {
|
||||
Kind = IK_ConversionFunctionId;
|
||||
Kind = UnqualifiedIdKind::IK_ConversionFunctionId;
|
||||
StartLocation = OperatorLoc;
|
||||
EndLocation = EndLoc;
|
||||
ConversionFunctionId = Ty;
|
||||
@ -1038,7 +1042,7 @@ class UnqualifiedId {
|
||||
/// \param IdLoc the location of the identifier.
|
||||
void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc,
|
||||
SourceLocation IdLoc) {
|
||||
Kind = IK_LiteralOperatorId;
|
||||
Kind = UnqualifiedIdKind::IK_LiteralOperatorId;
|
||||
Identifier = const_cast<IdentifierInfo *>(Id);
|
||||
StartLocation = OpLoc;
|
||||
EndLocation = IdLoc;
|
||||
@ -1054,7 +1058,7 @@ class UnqualifiedId {
|
||||
void setConstructorName(ParsedType ClassType,
|
||||
SourceLocation ClassNameLoc,
|
||||
SourceLocation EndLoc) {
|
||||
Kind = IK_ConstructorName;
|
||||
Kind = UnqualifiedIdKind::IK_ConstructorName;
|
||||
StartLocation = ClassNameLoc;
|
||||
EndLocation = EndLoc;
|
||||
ConstructorName = ClassType;
|
||||
@ -1077,7 +1081,7 @@ class UnqualifiedId {
|
||||
void setDestructorName(SourceLocation TildeLoc,
|
||||
ParsedType ClassType,
|
||||
SourceLocation EndLoc) {
|
||||
Kind = IK_DestructorName;
|
||||
Kind = UnqualifiedIdKind::IK_DestructorName;
|
||||
StartLocation = TildeLoc;
|
||||
EndLocation = EndLoc;
|
||||
DestructorName = ClassType;
|
||||
@ -1097,7 +1101,7 @@ class UnqualifiedId {
|
||||
/// \param TemplateLoc The location of the parsed template-name.
|
||||
void setDeductionGuideName(ParsedTemplateTy Template,
|
||||
SourceLocation TemplateLoc) {
|
||||
Kind = IK_DeductionGuideName;
|
||||
Kind = UnqualifiedIdKind::IK_DeductionGuideName;
|
||||
TemplateName = Template;
|
||||
StartLocation = EndLocation = TemplateLoc;
|
||||
}
|
||||
@ -1705,21 +1709,7 @@ enum FunctionDefinitionKind {
|
||||
FDK_Deleted
|
||||
};
|
||||
|
||||
/// \brief Information about one declarator, including the parsed type
|
||||
/// information and the identifier.
|
||||
///
|
||||
/// When the declarator is fully formed, this is turned into the appropriate
|
||||
/// Decl object.
|
||||
///
|
||||
/// Declarators come in two types: normal declarators and abstract declarators.
|
||||
/// Abstract declarators are used when parsing types, and don't have an
|
||||
/// identifier. Normal declarators do have ID's.
|
||||
///
|
||||
/// Instances of this class should be a transient object that lives on the
|
||||
/// stack, not objects that are allocated in large quantities on the heap.
|
||||
class Declarator {
|
||||
public:
|
||||
enum TheContext {
|
||||
enum class DeclaratorContext {
|
||||
FileContext, // File scope declaration.
|
||||
PrototypeContext, // Within a function prototype.
|
||||
ObjCResultContext, // An ObjC method result type.
|
||||
@ -1746,6 +1736,21 @@ class Declarator {
|
||||
AliasTemplateContext // C++11 alias-declaration template.
|
||||
};
|
||||
|
||||
|
||||
/// \brief Information about one declarator, including the parsed type
|
||||
/// information and the identifier.
|
||||
///
|
||||
/// When the declarator is fully formed, this is turned into the appropriate
|
||||
/// Decl object.
|
||||
///
|
||||
/// Declarators come in two types: normal declarators and abstract declarators.
|
||||
/// Abstract declarators are used when parsing types, and don't have an
|
||||
/// identifier. Normal declarators do have ID's.
|
||||
///
|
||||
/// Instances of this class should be a transient object that lives on the
|
||||
/// stack, not objects that are allocated in large quantities on the heap.
|
||||
class Declarator {
|
||||
|
||||
private:
|
||||
const DeclSpec &DS;
|
||||
CXXScopeSpec SS;
|
||||
@ -1753,7 +1758,7 @@ class Declarator {
|
||||
SourceRange Range;
|
||||
|
||||
/// \brief Where we are parsing this declarator.
|
||||
TheContext Context;
|
||||
DeclaratorContext Context;
|
||||
|
||||
/// The C++17 structured binding, if any. This is an alternative to a Name.
|
||||
DecompositionDeclarator BindingGroup;
|
||||
@ -1820,7 +1825,7 @@ class Declarator {
|
||||
friend struct DeclaratorChunk;
|
||||
|
||||
public:
|
||||
Declarator(const DeclSpec &ds, TheContext C)
|
||||
Declarator(const DeclSpec &ds, DeclaratorContext C)
|
||||
: DS(ds), Range(ds.getSourceRange()), Context(C),
|
||||
InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
|
||||
GroupingParens(false), FunctionDefinition(FDK_Declaration),
|
||||
@ -1858,13 +1863,13 @@ class Declarator {
|
||||
return BindingGroup;
|
||||
}
|
||||
|
||||
TheContext getContext() const { return Context; }
|
||||
DeclaratorContext getContext() const { return Context; }
|
||||
|
||||
bool isPrototypeContext() const {
|
||||
return (Context == PrototypeContext ||
|
||||
Context == ObjCParameterContext ||
|
||||
Context == ObjCResultContext ||
|
||||
Context == LambdaExprParameterContext);
|
||||
return (Context == DeclaratorContext::PrototypeContext ||
|
||||
Context == DeclaratorContext::ObjCParameterContext ||
|
||||
Context == DeclaratorContext::ObjCResultContext ||
|
||||
Context == DeclaratorContext::LambdaExprParameterContext);
|
||||
}
|
||||
|
||||
/// \brief Get the source range that spans this declarator.
|
||||
@ -1919,32 +1924,32 @@ class Declarator {
|
||||
/// parameter lists.
|
||||
bool mayOmitIdentifier() const {
|
||||
switch (Context) {
|
||||
case FileContext:
|
||||
case KNRTypeListContext:
|
||||
case MemberContext:
|
||||
case BlockContext:
|
||||
case ForContext:
|
||||
case InitStmtContext:
|
||||
case ConditionContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
return false;
|
||||
|
||||
case TypeNameContext:
|
||||
case FunctionalCastContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case PrototypeContext:
|
||||
case LambdaExprParameterContext:
|
||||
case ObjCParameterContext:
|
||||
case ObjCResultContext:
|
||||
case TemplateParamContext:
|
||||
case CXXNewContext:
|
||||
case CXXCatchContext:
|
||||
case ObjCCatchContext:
|
||||
case BlockLiteralContext:
|
||||
case LambdaExprContext:
|
||||
case ConversionIdContext:
|
||||
case TemplateTypeArgContext:
|
||||
case TrailingReturnContext:
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
@ -1955,32 +1960,32 @@ class Declarator {
|
||||
/// typenames.
|
||||
bool mayHaveIdentifier() const {
|
||||
switch (Context) {
|
||||
case FileContext:
|
||||
case KNRTypeListContext:
|
||||
case MemberContext:
|
||||
case BlockContext:
|
||||
case ForContext:
|
||||
case InitStmtContext:
|
||||
case ConditionContext:
|
||||
case PrototypeContext:
|
||||
case LambdaExprParameterContext:
|
||||
case TemplateParamContext:
|
||||
case CXXCatchContext:
|
||||
case ObjCCatchContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
return true;
|
||||
|
||||
case TypeNameContext:
|
||||
case FunctionalCastContext:
|
||||
case CXXNewContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case ObjCParameterContext:
|
||||
case ObjCResultContext:
|
||||
case BlockLiteralContext:
|
||||
case LambdaExprContext:
|
||||
case ConversionIdContext:
|
||||
case TemplateTypeArgContext:
|
||||
case TrailingReturnContext:
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
@ -1989,38 +1994,38 @@ class Declarator {
|
||||
/// Return true if the context permits a C++17 decomposition declarator.
|
||||
bool mayHaveDecompositionDeclarator() const {
|
||||
switch (Context) {
|
||||
case FileContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
// FIXME: It's not clear that the proposal meant to allow file-scope
|
||||
// structured bindings, but it does.
|
||||
case BlockContext:
|
||||
case ForContext:
|
||||
case InitStmtContext:
|
||||
case ConditionContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
return true;
|
||||
|
||||
case MemberContext:
|
||||
case PrototypeContext:
|
||||
case TemplateParamContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
// Maybe one day...
|
||||
return false;
|
||||
|
||||
// These contexts don't allow any kind of non-abstract declarator.
|
||||
case KNRTypeListContext:
|
||||
case TypeNameContext:
|
||||
case FunctionalCastContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case LambdaExprParameterContext:
|
||||
case ObjCParameterContext:
|
||||
case ObjCResultContext:
|
||||
case CXXNewContext:
|
||||
case CXXCatchContext:
|
||||
case ObjCCatchContext:
|
||||
case BlockLiteralContext:
|
||||
case LambdaExprContext:
|
||||
case ConversionIdContext:
|
||||
case TemplateTypeArgContext:
|
||||
case TrailingReturnContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
@ -2035,45 +2040,45 @@ class Declarator {
|
||||
return false;
|
||||
|
||||
if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern &&
|
||||
Context != FileContext)
|
||||
Context != DeclaratorContext::FileContext)
|
||||
return false;
|
||||
|
||||
// Special names can't have direct initializers.
|
||||
if (Name.getKind() != UnqualifiedId::IK_Identifier)
|
||||
if (Name.getKind() != UnqualifiedIdKind::IK_Identifier)
|
||||
return false;
|
||||
|
||||
switch (Context) {
|
||||
case FileContext:
|
||||
case BlockContext:
|
||||
case ForContext:
|
||||
case InitStmtContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
return true;
|
||||
|
||||
case ConditionContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
// This may not be followed by a direct initializer, but it can't be a
|
||||
// function declaration either, and we'd prefer to perform a tentative
|
||||
// parse in order to produce the right diagnostic.
|
||||
return true;
|
||||
|
||||
case KNRTypeListContext:
|
||||
case MemberContext:
|
||||
case PrototypeContext:
|
||||
case LambdaExprParameterContext:
|
||||
case ObjCParameterContext:
|
||||
case ObjCResultContext:
|
||||
case TemplateParamContext:
|
||||
case CXXCatchContext:
|
||||
case ObjCCatchContext:
|
||||
case TypeNameContext:
|
||||
case FunctionalCastContext: // FIXME
|
||||
case CXXNewContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case BlockLiteralContext:
|
||||
case LambdaExprContext:
|
||||
case ConversionIdContext:
|
||||
case TemplateTypeArgContext:
|
||||
case TrailingReturnContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
case DeclaratorContext::FunctionalCastContext: // FIXME
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
@ -2089,8 +2094,8 @@ class Declarator {
|
||||
/// special C++ name (constructor, destructor, etc.), or a structured
|
||||
/// binding (which is not exactly a name, but occupies the same position).
|
||||
bool hasName() const {
|
||||
return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier ||
|
||||
isDecompositionDeclarator();
|
||||
return Name.getKind() != UnqualifiedIdKind::IK_Identifier ||
|
||||
Name.Identifier || isDecompositionDeclarator();
|
||||
}
|
||||
|
||||
/// Return whether this declarator is a decomposition declarator.
|
||||
@ -2099,7 +2104,7 @@ class Declarator {
|
||||
}
|
||||
|
||||
IdentifierInfo *getIdentifier() const {
|
||||
if (Name.getKind() == UnqualifiedId::IK_Identifier)
|
||||
if (Name.getKind() == UnqualifiedIdKind::IK_Identifier)
|
||||
return Name.Identifier;
|
||||
|
||||
return nullptr;
|
||||
@ -2257,32 +2262,32 @@ class Declarator {
|
||||
return false;
|
||||
|
||||
switch (Context) {
|
||||
case FileContext:
|
||||
case MemberContext:
|
||||
case BlockContext:
|
||||
case ForContext:
|
||||
case InitStmtContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
return true;
|
||||
|
||||
case ConditionContext:
|
||||
case KNRTypeListContext:
|
||||
case TypeNameContext:
|
||||
case FunctionalCastContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case PrototypeContext:
|
||||
case LambdaExprParameterContext:
|
||||
case ObjCParameterContext:
|
||||
case ObjCResultContext:
|
||||
case TemplateParamContext:
|
||||
case CXXNewContext:
|
||||
case CXXCatchContext:
|
||||
case ObjCCatchContext:
|
||||
case BlockLiteralContext:
|
||||
case LambdaExprContext:
|
||||
case ConversionIdContext:
|
||||
case TemplateTypeArgContext:
|
||||
case TrailingReturnContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
@ -2292,32 +2297,35 @@ class Declarator {
|
||||
/// expression could appear.
|
||||
bool isExpressionContext() const {
|
||||
switch (Context) {
|
||||
case FileContext:
|
||||
case KNRTypeListContext:
|
||||
case MemberContext:
|
||||
case TypeNameContext: // FIXME: sizeof(...) permits an expression.
|
||||
case FunctionalCastContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case PrototypeContext:
|
||||
case LambdaExprParameterContext:
|
||||
case ObjCParameterContext:
|
||||
case ObjCResultContext:
|
||||
case TemplateParamContext:
|
||||
case CXXNewContext:
|
||||
case CXXCatchContext:
|
||||
case ObjCCatchContext:
|
||||
case BlockLiteralContext:
|
||||
case LambdaExprContext:
|
||||
case ConversionIdContext:
|
||||
case TrailingReturnContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
|
||||
// FIXME: sizeof(...) permits an expression.
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
return false;
|
||||
|
||||
case BlockContext:
|
||||
case ForContext:
|
||||
case InitStmtContext:
|
||||
case ConditionContext:
|
||||
case TemplateTypeArgContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2430,7 +2438,8 @@ class Declarator {
|
||||
|
||||
/// Returns true if this declares a real member and not a friend.
|
||||
bool isFirstDeclarationOfMember() {
|
||||
return getContext() == MemberContext && !getDeclSpec().isFriendSpecified();
|
||||
return getContext() == DeclaratorContext::MemberContext &&
|
||||
!getDeclSpec().isFriendSpecified();
|
||||
}
|
||||
|
||||
/// Returns true if this declares a static member. This cannot be called on a
|
||||
@ -2451,7 +2460,8 @@ struct FieldDeclarator {
|
||||
Declarator D;
|
||||
Expr *BitfieldSize;
|
||||
explicit FieldDeclarator(const DeclSpec &DS)
|
||||
: D(DS, Declarator::MemberContext), BitfieldSize(nullptr) { }
|
||||
: D(DS, DeclaratorContext::MemberContext),
|
||||
BitfieldSize(nullptr) {}
|
||||
};
|
||||
|
||||
/// \brief Represents a C++11 virt-specifier-seq.
|
||||
|
@ -5547,6 +5547,11 @@ class Sema {
|
||||
ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
sema::LambdaScopeInfo *LSI);
|
||||
|
||||
/// Get the return type to use for a lambda's conversion function(s) to
|
||||
/// function pointer type, given the type of the call operator.
|
||||
QualType
|
||||
getLambdaConversionFunctionResultType(const FunctionProtoType *CallOpType);
|
||||
|
||||
/// \brief Define the "body" of the conversion from a lambda object to a
|
||||
/// function pointer.
|
||||
///
|
||||
@ -7760,6 +7765,9 @@ class Sema {
|
||||
|
||||
void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
|
||||
FunctionDecl *Function);
|
||||
FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
|
||||
const TemplateArgumentList *Args,
|
||||
SourceLocation Loc);
|
||||
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
FunctionDecl *Function,
|
||||
bool Recursive = false,
|
||||
|
@ -779,7 +779,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
// unique-external linkage, it's not legally usable from outside
|
||||
// this translation unit. However, we should use the C linkage
|
||||
// rules instead for extern "C" declarations.
|
||||
if (Context.getLangOpts().CPlusPlus && !Function->isInExternCContext()) {
|
||||
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) {
|
||||
// Only look at the type-as-written. Otherwise, deducing the return type
|
||||
// of a function could change its linkage.
|
||||
QualType TypeAsWritten = Function->getType();
|
||||
@ -1165,7 +1165,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
|
||||
LVComputationKind computation) {
|
||||
if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
|
||||
if (Function->isInAnonymousNamespace() &&
|
||||
!Function->isInExternCContext())
|
||||
!isFirstInExternCContext(Function))
|
||||
return getInternalLinkageFor(Function);
|
||||
|
||||
// This is a "void f();" which got merged with a file static.
|
||||
@ -1188,7 +1188,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
|
||||
|
||||
if (const auto *Var = dyn_cast<VarDecl>(D)) {
|
||||
if (Var->hasExternalStorage()) {
|
||||
if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
|
||||
if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var))
|
||||
return getInternalLinkageFor(Var);
|
||||
|
||||
LinkageInfo LV;
|
||||
|
@ -139,7 +139,6 @@ bool X86TargetInfo::initFeatureMap(
|
||||
setFeatureEnabledImpl(Features, "avx512vnni", true);
|
||||
setFeatureEnabledImpl(Features, "avx512vbmi2", true);
|
||||
setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
|
||||
setFeatureEnabledImpl(Features, "clwb", true);
|
||||
LLVM_FALLTHROUGH;
|
||||
case CK_Cannonlake:
|
||||
setFeatureEnabledImpl(Features, "avx512ifma", true);
|
||||
@ -152,10 +151,8 @@ bool X86TargetInfo::initFeatureMap(
|
||||
setFeatureEnabledImpl(Features, "avx512dq", true);
|
||||
setFeatureEnabledImpl(Features, "avx512bw", true);
|
||||
setFeatureEnabledImpl(Features, "avx512vl", true);
|
||||
if (Kind == CK_SkylakeServer) {
|
||||
setFeatureEnabledImpl(Features, "pku", true);
|
||||
setFeatureEnabledImpl(Features, "clwb", true);
|
||||
}
|
||||
LLVM_FALLTHROUGH;
|
||||
case CK_SkylakeClient:
|
||||
setFeatureEnabledImpl(Features, "xsavec", true);
|
||||
|
@ -36,7 +36,7 @@ std::string getClangRepositoryPath() {
|
||||
|
||||
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
|
||||
// pick up a tag in an SVN export, for example.
|
||||
StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
|
||||
StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_60/lib/Basic/Version.cpp $");
|
||||
if (URL.empty()) {
|
||||
URL = SVNRepository.slice(SVNRepository.find(':'),
|
||||
SVNRepository.find("/lib/Basic"));
|
||||
|
@ -173,10 +173,12 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
|
||||
ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D));
|
||||
|
||||
if (!T->isReferenceType()) {
|
||||
if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>())
|
||||
if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
|
||||
D.hasAttr<OMPThreadPrivateDeclAttr>()) {
|
||||
(void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(
|
||||
&D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
|
||||
PerformInit, this);
|
||||
}
|
||||
if (PerformInit)
|
||||
EmitDeclInit(*this, D, DeclAddr);
|
||||
if (CGM.isTypeConstant(D.getType(), true))
|
||||
|
@ -646,7 +646,7 @@ CodeGenFunction::getMSVCDispatchBlock(EHScopeStack::stable_iterator SI) {
|
||||
return DispatchBlock;
|
||||
|
||||
if (EHS.getKind() == EHScope::Terminate)
|
||||
DispatchBlock = getTerminateHandler();
|
||||
DispatchBlock = getTerminateFunclet();
|
||||
else
|
||||
DispatchBlock = createBasicBlock();
|
||||
CGBuilderTy Builder(*this, DispatchBlock);
|
||||
@ -1334,24 +1334,15 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
|
||||
if (TerminateHandler)
|
||||
return TerminateHandler;
|
||||
|
||||
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
|
||||
|
||||
// Set up the terminate handler. This block is inserted at the very
|
||||
// end of the function by FinishFunction.
|
||||
TerminateHandler = createBasicBlock("terminate.handler");
|
||||
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
|
||||
Builder.SetInsertPoint(TerminateHandler);
|
||||
|
||||
llvm::Value *Exn = nullptr;
|
||||
SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
|
||||
CurrentFuncletPad);
|
||||
if (EHPersonality::get(*this).usesFuncletPads()) {
|
||||
llvm::Value *ParentPad = CurrentFuncletPad;
|
||||
if (!ParentPad)
|
||||
ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
|
||||
CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad);
|
||||
} else {
|
||||
if (getLangOpts().CPlusPlus)
|
||||
Exn = getExceptionFromSlot();
|
||||
}
|
||||
llvm::CallInst *terminateCall =
|
||||
CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
|
||||
terminateCall->setDoesNotReturn();
|
||||
@ -1363,6 +1354,42 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
|
||||
return TerminateHandler;
|
||||
}
|
||||
|
||||
llvm::BasicBlock *CodeGenFunction::getTerminateFunclet() {
|
||||
assert(EHPersonality::get(*this).usesFuncletPads() &&
|
||||
"use getTerminateLandingPad for non-funclet EH");
|
||||
|
||||
llvm::BasicBlock *&TerminateFunclet = TerminateFunclets[CurrentFuncletPad];
|
||||
if (TerminateFunclet)
|
||||
return TerminateFunclet;
|
||||
|
||||
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
|
||||
|
||||
// Set up the terminate handler. This block is inserted at the very
|
||||
// end of the function by FinishFunction.
|
||||
TerminateFunclet = createBasicBlock("terminate.handler");
|
||||
Builder.SetInsertPoint(TerminateFunclet);
|
||||
|
||||
// Create the cleanuppad using the current parent pad as its token. Use 'none'
|
||||
// if this is a top-level terminate scope, which is the common case.
|
||||
SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
|
||||
CurrentFuncletPad);
|
||||
llvm::Value *ParentPad = CurrentFuncletPad;
|
||||
if (!ParentPad)
|
||||
ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
|
||||
CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad);
|
||||
|
||||
// Emit the __std_terminate call.
|
||||
llvm::CallInst *terminateCall =
|
||||
CGM.getCXXABI().emitTerminateForUnexpectedException(*this, nullptr);
|
||||
terminateCall->setDoesNotReturn();
|
||||
Builder.CreateUnreachable();
|
||||
|
||||
// Restore the saved insertion state.
|
||||
Builder.restoreIP(SavedIP);
|
||||
|
||||
return TerminateFunclet;
|
||||
}
|
||||
|
||||
llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
|
||||
if (EHResumeBlock) return EHResumeBlock;
|
||||
|
||||
|
@ -2263,9 +2263,11 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
|
||||
Address Addr(V, Alignment);
|
||||
// Emit reference to the private copy of the variable if it is an OpenMP
|
||||
// threadprivate variable.
|
||||
if (CGF.getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>())
|
||||
if (CGF.getLangOpts().OpenMP && !CGF.getLangOpts().OpenMPSimd &&
|
||||
VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
|
||||
return EmitThreadPrivateVarDeclLValue(CGF, VD, T, Addr, RealVarTy,
|
||||
E->getExprLoc());
|
||||
}
|
||||
LValue LV = VD->getType()->isReferenceType() ?
|
||||
CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
|
||||
AlignmentSource::Decl) :
|
||||
@ -2446,7 +2448,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
|
||||
|
||||
// Check for OpenMP threadprivate variables.
|
||||
if (getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
|
||||
if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
|
||||
VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
|
||||
return EmitThreadPrivateVarDeclLValue(
|
||||
*this, VD, T, addr, getTypes().ConvertTypeForMem(VD->getType()),
|
||||
E->getExprLoc());
|
||||
|
@ -397,6 +397,7 @@ class InlinedOpenMPRegionRAII {
|
||||
CodeGenFunction &CGF;
|
||||
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
|
||||
FieldDecl *LambdaThisCaptureField = nullptr;
|
||||
const CodeGen::CGBlockInfo *BlockInfo = nullptr;
|
||||
|
||||
public:
|
||||
/// \brief Constructs region for combined constructs.
|
||||
@ -412,6 +413,8 @@ class InlinedOpenMPRegionRAII {
|
||||
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
|
||||
LambdaThisCaptureField = CGF.LambdaThisCaptureField;
|
||||
CGF.LambdaThisCaptureField = nullptr;
|
||||
BlockInfo = CGF.BlockInfo;
|
||||
CGF.BlockInfo = nullptr;
|
||||
}
|
||||
|
||||
~InlinedOpenMPRegionRAII() {
|
||||
@ -422,6 +425,7 @@ class InlinedOpenMPRegionRAII {
|
||||
CGF.CapturedStmtInfo = OldCSI;
|
||||
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
|
||||
CGF.LambdaThisCaptureField = LambdaThisCaptureField;
|
||||
CGF.BlockInfo = BlockInfo;
|
||||
}
|
||||
};
|
||||
|
||||
@ -8014,3 +8018,299 @@ Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
|
||||
const VarDecl *TargetParam) const {
|
||||
return CGF.GetAddrOfLocalVar(NativeParam);
|
||||
}
|
||||
|
||||
llvm::Value *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
|
||||
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
|
||||
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
llvm::Value *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
|
||||
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
|
||||
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
llvm::Value *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
|
||||
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
|
||||
const VarDecl *PartIDVar, const VarDecl *TaskTVar,
|
||||
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
|
||||
bool Tied, unsigned &NumberOfParts) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
|
||||
SourceLocation Loc,
|
||||
llvm::Value *OutlinedFn,
|
||||
ArrayRef<llvm::Value *> CapturedVars,
|
||||
const Expr *IfCond) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitCriticalRegion(
|
||||
CodeGenFunction &CGF, StringRef CriticalName,
|
||||
const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
|
||||
const Expr *Hint) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
|
||||
const RegionCodeGenTy &MasterOpGen,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
|
||||
CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitSingleRegion(
|
||||
CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
|
||||
SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
|
||||
ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
|
||||
ArrayRef<const Expr *> AssignmentOps) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
|
||||
const RegionCodeGenTy &OrderedOpGen,
|
||||
SourceLocation Loc,
|
||||
bool IsThreads) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
|
||||
SourceLocation Loc,
|
||||
OpenMPDirectiveKind Kind,
|
||||
bool EmitChecks,
|
||||
bool ForceSimpleCall) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitForDispatchInit(
|
||||
CodeGenFunction &CGF, SourceLocation Loc,
|
||||
const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
|
||||
bool Ordered, const DispatchRTInput &DispatchValues) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitForStaticInit(
|
||||
CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
|
||||
const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
|
||||
CodeGenFunction &CGF, SourceLocation Loc,
|
||||
OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
|
||||
SourceLocation Loc,
|
||||
unsigned IVSize,
|
||||
bool IVSigned) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
|
||||
SourceLocation Loc,
|
||||
OpenMPDirectiveKind DKind) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
|
||||
SourceLocation Loc,
|
||||
unsigned IVSize, bool IVSigned,
|
||||
Address IL, Address LB,
|
||||
Address UB, Address ST) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
|
||||
llvm::Value *NumThreads,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
|
||||
OpenMPProcBindClauseKind ProcBind,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
|
||||
const VarDecl *VD,
|
||||
Address VDAddr,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
|
||||
const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
|
||||
CodeGenFunction *CGF) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
|
||||
CodeGenFunction &CGF, QualType VarType, StringRef Name) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
|
||||
ArrayRef<const Expr *> Vars,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
const OMPExecutableDirective &D,
|
||||
llvm::Value *TaskFunction,
|
||||
QualType SharedsTy, Address Shareds,
|
||||
const Expr *IfCond,
|
||||
const OMPTaskDataTy &Data) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTaskLoopCall(
|
||||
CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
|
||||
llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
|
||||
const Expr *IfCond, const OMPTaskDataTy &Data) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitReduction(
|
||||
CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
|
||||
ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
|
||||
ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
|
||||
assert(Options.SimpleReduction && "Only simple reduction is expected.");
|
||||
CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
|
||||
ReductionOps, Options);
|
||||
}
|
||||
|
||||
llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
|
||||
CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
|
||||
ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
|
||||
SourceLocation Loc,
|
||||
ReductionCodeGen &RCG,
|
||||
unsigned N) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
|
||||
SourceLocation Loc,
|
||||
llvm::Value *ReductionsPtr,
|
||||
LValue SharedLVal) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitCancellationPointCall(
|
||||
CodeGenFunction &CGF, SourceLocation Loc,
|
||||
OpenMPDirectiveKind CancelRegion) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
|
||||
SourceLocation Loc, const Expr *IfCond,
|
||||
OpenMPDirectiveKind CancelRegion) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
|
||||
const OMPExecutableDirective &D, StringRef ParentName,
|
||||
llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
|
||||
bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF,
|
||||
const OMPExecutableDirective &D,
|
||||
llvm::Value *OutlinedFn,
|
||||
llvm::Value *OutlinedFnID,
|
||||
const Expr *IfCond, const Expr *Device,
|
||||
ArrayRef<llvm::Value *> CapturedVars) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
|
||||
return false;
|
||||
}
|
||||
|
||||
llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
|
||||
const OMPExecutableDirective &D,
|
||||
SourceLocation Loc,
|
||||
llvm::Value *OutlinedFn,
|
||||
ArrayRef<llvm::Value *> CapturedVars) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
|
||||
const Expr *NumTeams,
|
||||
const Expr *ThreadLimit,
|
||||
SourceLocation Loc) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTargetDataCalls(
|
||||
CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
|
||||
const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
|
||||
CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
|
||||
const Expr *Device) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
|
||||
const OMPLoopDirective &D) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
|
||||
const OMPDependClause *C) {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
const VarDecl *
|
||||
CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
|
||||
const VarDecl *NativeParam) const {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
Address
|
||||
CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
|
||||
const VarDecl *NativeParam,
|
||||
const VarDecl *TargetParam) const {
|
||||
llvm_unreachable("Not supported in SIMD-only mode");
|
||||
}
|
||||
|
||||
|
@ -1364,6 +1364,571 @@ class CGOpenMPRuntime {
|
||||
ArrayRef<llvm::Value *> Args = llvm::None) const;
|
||||
};
|
||||
|
||||
/// Class supports emissionof SIMD-only code.
|
||||
class CGOpenMPSIMDRuntime final : public CGOpenMPRuntime {
|
||||
public:
|
||||
explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {}
|
||||
~CGOpenMPSIMDRuntime() override {}
|
||||
|
||||
/// \brief Emits outlined function for the specified OpenMP parallel directive
|
||||
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
|
||||
/// kmp_int32 BoundID, struct context_vars*).
|
||||
/// \param D OpenMP directive.
|
||||
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
|
||||
/// \param InnermostKind Kind of innermost directive (for simple directives it
|
||||
/// is a directive itself, for combined - its innermost directive).
|
||||
/// \param CodeGen Code generation sequence for the \a D directive.
|
||||
llvm::Value *
|
||||
emitParallelOutlinedFunction(const OMPExecutableDirective &D,
|
||||
const VarDecl *ThreadIDVar,
|
||||
OpenMPDirectiveKind InnermostKind,
|
||||
const RegionCodeGenTy &CodeGen) override;
|
||||
|
||||
/// \brief Emits outlined function for the specified OpenMP teams directive
|
||||
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
|
||||
/// kmp_int32 BoundID, struct context_vars*).
|
||||
/// \param D OpenMP directive.
|
||||
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
|
||||
/// \param InnermostKind Kind of innermost directive (for simple directives it
|
||||
/// is a directive itself, for combined - its innermost directive).
|
||||
/// \param CodeGen Code generation sequence for the \a D directive.
|
||||
llvm::Value *
|
||||
emitTeamsOutlinedFunction(const OMPExecutableDirective &D,
|
||||
const VarDecl *ThreadIDVar,
|
||||
OpenMPDirectiveKind InnermostKind,
|
||||
const RegionCodeGenTy &CodeGen) override;
|
||||
|
||||
/// \brief Emits outlined function for the OpenMP task directive \a D. This
|
||||
/// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t*
|
||||
/// TaskT).
|
||||
/// \param D OpenMP directive.
|
||||
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
|
||||
/// \param PartIDVar Variable for partition id in the current OpenMP untied
|
||||
/// task region.
|
||||
/// \param TaskTVar Variable for task_t argument.
|
||||
/// \param InnermostKind Kind of innermost directive (for simple directives it
|
||||
/// is a directive itself, for combined - its innermost directive).
|
||||
/// \param CodeGen Code generation sequence for the \a D directive.
|
||||
/// \param Tied true if task is generated for tied task, false otherwise.
|
||||
/// \param NumberOfParts Number of parts in untied task. Ignored for tied
|
||||
/// tasks.
|
||||
///
|
||||
llvm::Value *emitTaskOutlinedFunction(
|
||||
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
|
||||
const VarDecl *PartIDVar, const VarDecl *TaskTVar,
|
||||
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
|
||||
bool Tied, unsigned &NumberOfParts) override;
|
||||
|
||||
/// \brief Emits code for parallel or serial call of the \a OutlinedFn with
|
||||
/// variables captured in a record which address is stored in \a
|
||||
/// CapturedStruct.
|
||||
/// \param OutlinedFn Outlined function to be run in parallel threads. Type of
|
||||
/// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
|
||||
/// \param CapturedVars A pointer to the record with the references to
|
||||
/// variables used in \a OutlinedFn function.
|
||||
/// \param IfCond Condition in the associated 'if' clause, if it was
|
||||
/// specified, nullptr otherwise.
|
||||
///
|
||||
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
llvm::Value *OutlinedFn,
|
||||
ArrayRef<llvm::Value *> CapturedVars,
|
||||
const Expr *IfCond) override;
|
||||
|
||||
/// \brief Emits a critical region.
|
||||
/// \param CriticalName Name of the critical region.
|
||||
/// \param CriticalOpGen Generator for the statement associated with the given
|
||||
/// critical region.
|
||||
/// \param Hint Value of the 'hint' clause (optional).
|
||||
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
|
||||
const RegionCodeGenTy &CriticalOpGen,
|
||||
SourceLocation Loc,
|
||||
const Expr *Hint = nullptr) override;
|
||||
|
||||
/// \brief Emits a master region.
|
||||
/// \param MasterOpGen Generator for the statement associated with the given
|
||||
/// master region.
|
||||
void emitMasterRegion(CodeGenFunction &CGF,
|
||||
const RegionCodeGenTy &MasterOpGen,
|
||||
SourceLocation Loc) override;
|
||||
|
||||
/// \brief Emits code for a taskyield directive.
|
||||
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override;
|
||||
|
||||
/// \brief Emit a taskgroup region.
|
||||
/// \param TaskgroupOpGen Generator for the statement associated with the
|
||||
/// given taskgroup region.
|
||||
void emitTaskgroupRegion(CodeGenFunction &CGF,
|
||||
const RegionCodeGenTy &TaskgroupOpGen,
|
||||
SourceLocation Loc) override;
|
||||
|
||||
/// \brief Emits a single region.
|
||||
/// \param SingleOpGen Generator for the statement associated with the given
|
||||
/// single region.
|
||||
void emitSingleRegion(CodeGenFunction &CGF,
|
||||
const RegionCodeGenTy &SingleOpGen, SourceLocation Loc,
|
||||
ArrayRef<const Expr *> CopyprivateVars,
|
||||
ArrayRef<const Expr *> DestExprs,
|
||||
ArrayRef<const Expr *> SrcExprs,
|
||||
ArrayRef<const Expr *> AssignmentOps) override;
|
||||
|
||||
/// \brief Emit an ordered region.
|
||||
/// \param OrderedOpGen Generator for the statement associated with the given
|
||||
/// ordered region.
|
||||
void emitOrderedRegion(CodeGenFunction &CGF,
|
||||
const RegionCodeGenTy &OrderedOpGen,
|
||||
SourceLocation Loc, bool IsThreads) override;
|
||||
|
||||
/// \brief Emit an implicit/explicit barrier for OpenMP threads.
|
||||
/// \param Kind Directive for which this implicit barrier call must be
|
||||
/// generated. Must be OMPD_barrier for explicit barrier generation.
|
||||
/// \param EmitChecks true if need to emit checks for cancellation barriers.
|
||||
/// \param ForceSimpleCall true simple barrier call must be emitted, false if
|
||||
/// runtime class decides which one to emit (simple or with cancellation
|
||||
/// checks).
|
||||
///
|
||||
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
OpenMPDirectiveKind Kind, bool EmitChecks = true,
|
||||
bool ForceSimpleCall = false) override;
|
||||
|
||||
/// This is used for non static scheduled types and when the ordered
|
||||
/// clause is present on the loop construct.
|
||||
/// Depending on the loop schedule, it is necessary to call some runtime
|
||||
/// routine before start of the OpenMP loop to get the loop upper / lower
|
||||
/// bounds \a LB and \a UB and stride \a ST.
|
||||
///
|
||||
/// \param CGF Reference to current CodeGenFunction.
|
||||
/// \param Loc Clang source location.
|
||||
/// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
|
||||
/// \param IVSize Size of the iteration variable in bits.
|
||||
/// \param IVSigned Sign of the iteration variable.
|
||||
/// \param Ordered true if loop is ordered, false otherwise.
|
||||
/// \param DispatchValues struct containing llvm values for lower bound, upper
|
||||
/// bound, and chunk expression.
|
||||
/// For the default (nullptr) value, the chunk 1 will be used.
|
||||
///
|
||||
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
const OpenMPScheduleTy &ScheduleKind,
|
||||
unsigned IVSize, bool IVSigned, bool Ordered,
|
||||
const DispatchRTInput &DispatchValues) override;
|
||||
|
||||
/// \brief Call the appropriate runtime routine to initialize it before start
|
||||
/// of loop.
|
||||
///
|
||||
/// This is used only in case of static schedule, when the user did not
|
||||
/// specify a ordered clause on the loop construct.
|
||||
/// Depending on the loop schedule, it is necessary to call some runtime
|
||||
/// routine before start of the OpenMP loop to get the loop upper / lower
|
||||
/// bounds LB and UB and stride ST.
|
||||
///
|
||||
/// \param CGF Reference to current CodeGenFunction.
|
||||
/// \param Loc Clang source location.
|
||||
/// \param DKind Kind of the directive.
|
||||
/// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
|
||||
/// \param Values Input arguments for the construct.
|
||||
///
|
||||
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
OpenMPDirectiveKind DKind,
|
||||
const OpenMPScheduleTy &ScheduleKind,
|
||||
const StaticRTInput &Values) override;
|
||||
|
||||
///
|
||||
/// \param CGF Reference to current CodeGenFunction.
|
||||
/// \param Loc Clang source location.
|
||||
/// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause.
|
||||
/// \param Values Input arguments for the construct.
|
||||
///
|
||||
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
OpenMPDistScheduleClauseKind SchedKind,
|
||||
const StaticRTInput &Values) override;
|
||||
|
||||
/// \brief Call the appropriate runtime routine to notify that we finished
|
||||
/// iteration of the ordered loop with the dynamic scheduling.
|
||||
///
|
||||
/// \param CGF Reference to current CodeGenFunction.
|
||||
/// \param Loc Clang source location.
|
||||
/// \param IVSize Size of the iteration variable in bits.
|
||||
/// \param IVSigned Sign of the iteration variable.
|
||||
///
|
||||
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
unsigned IVSize, bool IVSigned) override;
|
||||
|
||||
/// \brief Call the appropriate runtime routine to notify that we finished
|
||||
/// all the work with current loop.
|
||||
///
|
||||
/// \param CGF Reference to current CodeGenFunction.
|
||||
/// \param Loc Clang source location.
|
||||
/// \param DKind Kind of the directive for which the static finish is emitted.
|
||||
///
|
||||
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
OpenMPDirectiveKind DKind) override;
|
||||
|
||||
/// Call __kmpc_dispatch_next(
|
||||
/// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
|
||||
/// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
|
||||
/// kmp_int[32|64] *p_stride);
|
||||
/// \param IVSize Size of the iteration variable in bits.
|
||||
/// \param IVSigned Sign of the iteration variable.
|
||||
/// \param IL Address of the output variable in which the flag of the
|
||||
/// last iteration is returned.
|
||||
/// \param LB Address of the output variable in which the lower iteration
|
||||
/// number is returned.
|
||||
/// \param UB Address of the output variable in which the upper iteration
|
||||
/// number is returned.
|
||||
/// \param ST Address of the output variable in which the stride value is
|
||||
/// returned.
|
||||
llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
unsigned IVSize, bool IVSigned, Address IL,
|
||||
Address LB, Address UB, Address ST) override;
|
||||
|
||||
/// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
|
||||
/// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
|
||||
/// clause.
|
||||
/// \param NumThreads An integer value of threads.
|
||||
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads,
|
||||
SourceLocation Loc) override;
|
||||
|
||||
/// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
|
||||
/// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
|
||||
void emitProcBindClause(CodeGenFunction &CGF,
|
||||
OpenMPProcBindClauseKind ProcBind,
|
||||
SourceLocation Loc) override;
|
||||
|
||||
/// \brief Returns address of the threadprivate variable for the current
|
||||
/// thread.
|
||||
/// \param VD Threadprivate variable.
|
||||
/// \param VDAddr Address of the global variable \a VD.
|
||||
/// \param Loc Location of the reference to threadprivate var.
|
||||
/// \return Address of the threadprivate variable for the current thread.
|
||||
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD,
|
||||
Address VDAddr, SourceLocation Loc) override;
|
||||
|
||||
/// \brief Emit a code for initialization of threadprivate variable. It emits
|
||||
/// a call to runtime library which adds initial value to the newly created
|
||||
/// threadprivate variable (if it is not constant) and registers destructor
|
||||
/// for the variable (if any).
|
||||
/// \param VD Threadprivate variable.
|
||||
/// \param VDAddr Address of the global variable \a VD.
|
||||
/// \param Loc Location of threadprivate declaration.
|
||||
/// \param PerformInit true if initialization expression is not constant.
|
||||
llvm::Function *
|
||||
emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
|
||||
SourceLocation Loc, bool PerformInit,
|
||||
CodeGenFunction *CGF = nullptr) override;
|
||||
|
||||
/// Creates artificial threadprivate variable with name \p Name and type \p
|
||||
/// VarType.
|
||||
/// \param VarType Type of the artificial threadprivate variable.
|
||||
/// \param Name Name of the artificial threadprivate variable.
|
||||
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
|
||||
QualType VarType,
|
||||
StringRef Name) override;
|
||||
|
||||
/// \brief Emit flush of the variables specified in 'omp flush' directive.
|
||||
/// \param Vars List of variables to flush.
|
||||
void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
|
||||
SourceLocation Loc) override;
|
||||
|
||||
/// \brief Emit task region for the task directive. The task region is
|
||||
/// emitted in several steps:
|
||||
/// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
|
||||
/// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
|
||||
/// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
|
||||
/// function:
|
||||
/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
|
||||
/// TaskFunction(gtid, tt->part_id, tt->shareds);
|
||||
/// return 0;
|
||||
/// }
|
||||
/// 2. Copy a list of shared variables to field shareds of the resulting
|
||||
/// structure kmp_task_t returned by the previous call (if any).
|
||||
/// 3. Copy a pointer to destructions function to field destructions of the
|
||||
/// resulting structure kmp_task_t.
|
||||
/// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
|
||||
/// kmp_task_t *new_task), where new_task is a resulting structure from
|
||||
/// previous items.
|
||||
/// \param D Current task directive.
|
||||
/// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
|
||||
/// /*part_id*/, captured_struct */*__context*/);
|
||||
/// \param SharedsTy A type which contains references the shared variables.
|
||||
/// \param Shareds Context with the list of shared variables from the \p
|
||||
/// TaskFunction.
|
||||
/// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
|
||||
/// otherwise.
|
||||
/// \param Data Additional data for task generation like tiednsee, final
|
||||
/// state, list of privates etc.
|
||||
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
const OMPExecutableDirective &D, llvm::Value *TaskFunction,
|
||||
QualType SharedsTy, Address Shareds, const Expr *IfCond,
|
||||
const OMPTaskDataTy &Data) override;
|
||||
|
||||
/// Emit task region for the taskloop directive. The taskloop region is
|
||||
/// emitted in several steps:
|
||||
/// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
|
||||
/// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
|
||||
/// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
|
||||
/// function:
|
||||
/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
|
||||
/// TaskFunction(gtid, tt->part_id, tt->shareds);
|
||||
/// return 0;
|
||||
/// }
|
||||
/// 2. Copy a list of shared variables to field shareds of the resulting
|
||||
/// structure kmp_task_t returned by the previous call (if any).
|
||||
/// 3. Copy a pointer to destructions function to field destructions of the
|
||||
/// resulting structure kmp_task_t.
|
||||
/// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t
|
||||
/// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int
|
||||
/// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task
|
||||
/// is a resulting structure from
|
||||
/// previous items.
|
||||
/// \param D Current task directive.
|
||||
/// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
|
||||
/// /*part_id*/, captured_struct */*__context*/);
|
||||
/// \param SharedsTy A type which contains references the shared variables.
|
||||
/// \param Shareds Context with the list of shared variables from the \p
|
||||
/// TaskFunction.
|
||||
/// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
|
||||
/// otherwise.
|
||||
/// \param Data Additional data for task generation like tiednsee, final
|
||||
/// state, list of privates etc.
|
||||
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
const OMPLoopDirective &D, llvm::Value *TaskFunction,
|
||||
QualType SharedsTy, Address Shareds, const Expr *IfCond,
|
||||
const OMPTaskDataTy &Data) override;
|
||||
|
||||
/// \brief Emit a code for reduction clause. Next code should be emitted for
|
||||
/// reduction:
|
||||
/// \code
|
||||
///
|
||||
/// static kmp_critical_name lock = { 0 };
|
||||
///
|
||||
/// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
|
||||
/// ...
|
||||
/// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// ...
|
||||
/// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
|
||||
/// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
|
||||
/// RedList, reduce_func, &<lock>)) {
|
||||
/// case 1:
|
||||
/// ...
|
||||
/// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
|
||||
/// ...
|
||||
/// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
|
||||
/// break;
|
||||
/// case 2:
|
||||
/// ...
|
||||
/// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
|
||||
/// ...
|
||||
/// break;
|
||||
/// default:;
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \param Privates List of private copies for original reduction arguments.
|
||||
/// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
|
||||
/// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
|
||||
/// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
|
||||
/// or 'operator binop(LHS, RHS)'.
|
||||
/// \param Options List of options for reduction codegen:
|
||||
/// WithNowait true if parent directive has also nowait clause, false
|
||||
/// otherwise.
|
||||
/// SimpleReduction Emit reduction operation only. Used for omp simd
|
||||
/// directive on the host.
|
||||
/// ReductionKind The kind of reduction to perform.
|
||||
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
ArrayRef<const Expr *> Privates,
|
||||
ArrayRef<const Expr *> LHSExprs,
|
||||
ArrayRef<const Expr *> RHSExprs,
|
||||
ArrayRef<const Expr *> ReductionOps,
|
||||
ReductionOptionsTy Options) override;
|
||||
|
||||
/// Emit a code for initialization of task reduction clause. Next code
|
||||
/// should be emitted for reduction:
|
||||
/// \code
|
||||
///
|
||||
/// _task_red_item_t red_data[n];
|
||||
/// ...
|
||||
/// red_data[i].shar = &origs[i];
|
||||
/// red_data[i].size = sizeof(origs[i]);
|
||||
/// red_data[i].f_init = (void*)RedInit<i>;
|
||||
/// red_data[i].f_fini = (void*)RedDest<i>;
|
||||
/// red_data[i].f_comb = (void*)RedOp<i>;
|
||||
/// red_data[i].flags = <Flag_i>;
|
||||
/// ...
|
||||
/// void* tg1 = __kmpc_task_reduction_init(gtid, n, red_data);
|
||||
/// \endcode
|
||||
///
|
||||
/// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations.
|
||||
/// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations.
|
||||
/// \param Data Additional data for task generation like tiedness, final
|
||||
/// state, list of privates, reductions etc.
|
||||
llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
ArrayRef<const Expr *> LHSExprs,
|
||||
ArrayRef<const Expr *> RHSExprs,
|
||||
const OMPTaskDataTy &Data) override;
|
||||
|
||||
/// Required to resolve existing problems in the runtime. Emits threadprivate
|
||||
/// variables to store the size of the VLAs/array sections for
|
||||
/// initializer/combiner/finalizer functions + emits threadprivate variable to
|
||||
/// store the pointer to the original reduction item for the custom
|
||||
/// initializer defined by declare reduction construct.
|
||||
/// \param RCG Allows to reuse an existing data for the reductions.
|
||||
/// \param N Reduction item for which fixups must be emitted.
|
||||
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
ReductionCodeGen &RCG, unsigned N) override;
|
||||
|
||||
/// Get the address of `void *` type of the privatue copy of the reduction
|
||||
/// item specified by the \p SharedLVal.
|
||||
/// \param ReductionsPtr Pointer to the reduction data returned by the
|
||||
/// emitTaskReductionInit function.
|
||||
/// \param SharedLVal Address of the original reduction item.
|
||||
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
llvm::Value *ReductionsPtr,
|
||||
LValue SharedLVal) override;
|
||||
|
||||
/// \brief Emit code for 'taskwait' directive.
|
||||
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override;
|
||||
|
||||
/// \brief Emit code for 'cancellation point' construct.
|
||||
/// \param CancelRegion Region kind for which the cancellation point must be
|
||||
/// emitted.
|
||||
///
|
||||
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
OpenMPDirectiveKind CancelRegion) override;
|
||||
|
||||
/// \brief Emit code for 'cancel' construct.
|
||||
/// \param IfCond Condition in the associated 'if' clause, if it was
|
||||
/// specified, nullptr otherwise.
|
||||
/// \param CancelRegion Region kind for which the cancel must be emitted.
|
||||
///
|
||||
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
|
||||
const Expr *IfCond,
|
||||
OpenMPDirectiveKind CancelRegion) override;
|
||||
|
||||
/// \brief Emit outilined function for 'target' directive.
|
||||
/// \param D Directive to emit.
|
||||
/// \param ParentName Name of the function that encloses the target region.
|
||||
/// \param OutlinedFn Outlined function value to be defined by this call.
|
||||
/// \param OutlinedFnID Outlined function ID value to be defined by this call.
|
||||
/// \param IsOffloadEntry True if the outlined function is an offload entry.
|
||||
/// \param CodeGen Code generation sequence for the \a D directive.
|
||||
/// An outlined function may not be an entry if, e.g. the if clause always
|
||||
/// evaluates to false.
|
||||
void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
|
||||
StringRef ParentName,
|
||||
llvm::Function *&OutlinedFn,
|
||||
llvm::Constant *&OutlinedFnID,
|
||||
bool IsOffloadEntry,
|
||||
const RegionCodeGenTy &CodeGen) override;
|
||||
|
||||
/// \brief Emit the target offloading code associated with \a D. The emitted
|
||||
/// code attempts offloading the execution to the device, an the event of
|
||||
/// a failure it executes the host version outlined in \a OutlinedFn.
|
||||
/// \param D Directive to emit.
|
||||
/// \param OutlinedFn Host version of the code to be offloaded.
|
||||
/// \param OutlinedFnID ID of host version of the code to be offloaded.
|
||||
/// \param IfCond Expression evaluated in if clause associated with the target
|
||||
/// directive, or null if no if clause is used.
|
||||
/// \param Device Expression evaluated in device clause associated with the
|
||||
/// target directive, or null if no device clause is used.
|
||||
/// \param CapturedVars Values captured in the current region.
|
||||
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
|
||||
llvm::Value *OutlinedFn, llvm::Value *OutlinedFnID,
|
||||
const Expr *IfCond, const Expr *Device,
|
||||
ArrayRef<llvm::Value *> CapturedVars) override;
|
||||
|
||||
/// \brief Emit the target regions enclosed in \a GD function definition or
|
||||
/// the function itself in case it is a valid device function. Returns true if
|
||||
/// \a GD was dealt with successfully.
|
||||
/// \param GD Function to scan.
|
||||
bool emitTargetFunctions(GlobalDecl GD) override;
|
||||
|
||||
/// \brief Emit the global variable if it is a valid device global variable.
|
||||
/// Returns true if \a GD was dealt with successfully.
|
||||
/// \param GD Variable declaration to emit.
|
||||
bool emitTargetGlobalVariable(GlobalDecl GD) override;
|
||||
|
||||
/// \brief Emit the global \a GD if it is meaningful for the target. Returns
|
||||
/// if it was emitted successfully.
|
||||
/// \param GD Global to scan.
|
||||
bool emitTargetGlobal(GlobalDecl GD) override;
|
||||
|
||||
/// \brief Creates the offloading descriptor in the event any target region
|
||||
/// was emitted in the current module and return the function that registers
|
||||
/// it.
|
||||
llvm::Function *emitRegistrationFunction() override;
|
||||
|
||||
/// \brief Emits code for teams call of the \a OutlinedFn with
|
||||
/// variables captured in a record which address is stored in \a
|
||||
/// CapturedStruct.
|
||||
/// \param OutlinedFn Outlined function to be run by team masters. Type of
|
||||
/// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
|
||||
/// \param CapturedVars A pointer to the record with the references to
|
||||
/// variables used in \a OutlinedFn function.
|
||||
///
|
||||
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
|
||||
SourceLocation Loc, llvm::Value *OutlinedFn,
|
||||
ArrayRef<llvm::Value *> CapturedVars) override;
|
||||
|
||||
/// \brief Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
|
||||
/// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code
|
||||
/// for num_teams clause.
|
||||
/// \param NumTeams An integer expression of teams.
|
||||
/// \param ThreadLimit An integer expression of threads.
|
||||
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
|
||||
const Expr *ThreadLimit, SourceLocation Loc) override;
|
||||
|
||||
/// \brief Emit the target data mapping code associated with \a D.
|
||||
/// \param D Directive to emit.
|
||||
/// \param IfCond Expression evaluated in if clause associated with the
|
||||
/// target directive, or null if no device clause is used.
|
||||
/// \param Device Expression evaluated in device clause associated with the
|
||||
/// target directive, or null if no device clause is used.
|
||||
/// \param Info A record used to store information that needs to be preserved
|
||||
/// until the region is closed.
|
||||
void emitTargetDataCalls(CodeGenFunction &CGF,
|
||||
const OMPExecutableDirective &D, const Expr *IfCond,
|
||||
const Expr *Device, const RegionCodeGenTy &CodeGen,
|
||||
TargetDataInfo &Info) override;
|
||||
|
||||
/// \brief Emit the data mapping/movement code associated with the directive
|
||||
/// \a D that should be of the form 'target [{enter|exit} data | update]'.
|
||||
/// \param D Directive to emit.
|
||||
/// \param IfCond Expression evaluated in if clause associated with the target
|
||||
/// directive, or null if no if clause is used.
|
||||
/// \param Device Expression evaluated in device clause associated with the
|
||||
/// target directive, or null if no device clause is used.
|
||||
void emitTargetDataStandAloneCall(CodeGenFunction &CGF,
|
||||
const OMPExecutableDirective &D,
|
||||
const Expr *IfCond,
|
||||
const Expr *Device) override;
|
||||
|
||||
/// Emit initialization for doacross loop nesting support.
|
||||
/// \param D Loop-based construct used in doacross nesting construct.
|
||||
void emitDoacrossInit(CodeGenFunction &CGF,
|
||||
const OMPLoopDirective &D) override;
|
||||
|
||||
/// Emit code for doacross ordered directive with 'depend' clause.
|
||||
/// \param C 'depend' clause with 'sink|source' dependency kind.
|
||||
void emitDoacrossOrdered(CodeGenFunction &CGF,
|
||||
const OMPDependClause *C) override;
|
||||
|
||||
/// Translates the native parameter of outlined function if this is required
|
||||
/// for target.
|
||||
/// \param FD Field decl from captured record for the paramater.
|
||||
/// \param NativeParam Parameter itself.
|
||||
const VarDecl *translateParameter(const FieldDecl *FD,
|
||||
const VarDecl *NativeParam) const override;
|
||||
|
||||
/// Gets the address of the native argument basing on the address of the
|
||||
/// target-specific parameter.
|
||||
/// \param NativeParam Parameter itself.
|
||||
/// \param TargetParam Corresponding target-specific parameter.
|
||||
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam,
|
||||
const VarDecl *TargetParam) const override;
|
||||
};
|
||||
|
||||
} // namespace CodeGen
|
||||
} // namespace clang
|
||||
|
||||
|
@ -74,6 +74,15 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
|
||||
// Generate a stoppoint if we are emitting debug info.
|
||||
EmitStopPoint(S);
|
||||
|
||||
// Ignore all OpenMP directives except for simd if OpenMP with Simd is
|
||||
// enabled.
|
||||
if (getLangOpts().OpenMP && getLangOpts().OpenMPSimd) {
|
||||
if (const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
|
||||
EmitSimpleOMPExecutableDirective(*D);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (S->getStmtClass()) {
|
||||
case Stmt::NoStmtClass:
|
||||
case Stmt::CXXCatchStmtClass:
|
||||
|
@ -144,6 +144,71 @@ class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
|
||||
}
|
||||
};
|
||||
|
||||
class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope {
|
||||
CodeGenFunction::OMPPrivateScope InlinedShareds;
|
||||
|
||||
static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
|
||||
return CGF.LambdaCaptureFields.lookup(VD) ||
|
||||
(CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
|
||||
(CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) &&
|
||||
cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
|
||||
}
|
||||
|
||||
public:
|
||||
OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
|
||||
: CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
|
||||
InlinedShareds(CGF) {
|
||||
for (const auto *C : S.clauses()) {
|
||||
if (auto *CPI = OMPClauseWithPreInit::get(C)) {
|
||||
if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
|
||||
for (const auto *I : PreInit->decls()) {
|
||||
if (!I->hasAttr<OMPCaptureNoInitAttr>())
|
||||
CGF.EmitVarDecl(cast<VarDecl>(*I));
|
||||
else {
|
||||
CodeGenFunction::AutoVarEmission Emission =
|
||||
CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
|
||||
CGF.EmitAutoVarCleanups(Emission);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) {
|
||||
for (const Expr *E : UDP->varlists()) {
|
||||
const Decl *D = cast<DeclRefExpr>(E)->getDecl();
|
||||
if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
|
||||
CGF.EmitVarDecl(*OED);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isOpenMPSimdDirective(S.getDirectiveKind()))
|
||||
CGF.EmitOMPPrivateClause(S, InlinedShareds);
|
||||
if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
|
||||
if (const Expr *E = TG->getReductionRef())
|
||||
CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()));
|
||||
}
|
||||
const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
|
||||
while (CS) {
|
||||
for (auto &C : CS->captures()) {
|
||||
if (C.capturesVariable() || C.capturesVariableByCopy()) {
|
||||
auto *VD = C.getCapturedVar();
|
||||
assert(VD == VD->getCanonicalDecl() &&
|
||||
"Canonical decl must be captured.");
|
||||
DeclRefExpr DRE(const_cast<VarDecl *>(VD),
|
||||
isCapturedVar(CGF, VD) ||
|
||||
(CGF.CapturedStmtInfo &&
|
||||
InlinedShareds.isGlobalVarCaptured(VD)),
|
||||
VD->getType().getNonReferenceType(), VK_LValue,
|
||||
SourceLocation());
|
||||
InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
|
||||
return CGF.EmitLValue(&DRE).getAddress();
|
||||
});
|
||||
}
|
||||
}
|
||||
CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt());
|
||||
}
|
||||
(void)InlinedShareds.Privatize();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
|
||||
@ -863,7 +928,8 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
|
||||
llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
|
||||
for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
|
||||
HasAtLeastOneLastprivate = true;
|
||||
if (isOpenMPTaskLoopDirective(D.getDirectiveKind()))
|
||||
if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
|
||||
!getLangOpts().OpenMPSimd)
|
||||
break;
|
||||
auto IRef = C->varlist_begin();
|
||||
auto IDestRef = C->destination_exprs().begin();
|
||||
@ -1100,9 +1166,8 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
|
||||
if (HasAtLeastOneReduction) {
|
||||
bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
|
||||
isOpenMPParallelDirective(D.getDirectiveKind()) ||
|
||||
D.getDirectiveKind() == OMPD_simd;
|
||||
bool SimpleReduction = D.getDirectiveKind() == OMPD_simd ||
|
||||
D.getDirectiveKind() == OMPD_distribute_simd;
|
||||
ReductionKind == OMPD_simd;
|
||||
bool SimpleReduction = ReductionKind == OMPD_simd;
|
||||
// Emit nowait reduction if nowait clause is present or directive is a
|
||||
// parallel directive (it always has implicit barrier).
|
||||
CGM.getOpenMPRuntime().emitReduction(
|
||||
@ -1570,6 +1635,14 @@ static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF,
|
||||
CGF.EmitStopPoint(&S);
|
||||
}
|
||||
|
||||
/// Emit a helper variable and return corresponding lvalue.
|
||||
static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
|
||||
const DeclRefExpr *Helper) {
|
||||
auto VDecl = cast<VarDecl>(Helper->getDecl());
|
||||
CGF.EmitVarDecl(*VDecl);
|
||||
return CGF.EmitLValue(Helper);
|
||||
}
|
||||
|
||||
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
|
||||
PrePostActionTy &Action) {
|
||||
Action.Enter(CGF);
|
||||
@ -1581,6 +1654,12 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
|
||||
// <Final counter/linear vars updates>;
|
||||
// }
|
||||
//
|
||||
if (isOpenMPDistributeDirective(S.getDirectiveKind()) ||
|
||||
isOpenMPWorksharingDirective(S.getDirectiveKind()) ||
|
||||
isOpenMPTaskLoopDirective(S.getDirectiveKind())) {
|
||||
(void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()));
|
||||
(void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()));
|
||||
}
|
||||
|
||||
// Emit: if (PreCond) - begin.
|
||||
// If the condition constant folds and can be elided, avoid emitting the
|
||||
@ -1933,14 +2012,6 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
|
||||
emitEmptyOrdered);
|
||||
}
|
||||
|
||||
/// Emit a helper variable and return corresponding lvalue.
|
||||
static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
|
||||
const DeclRefExpr *Helper) {
|
||||
auto VDecl = cast<VarDecl>(Helper->getDecl());
|
||||
CGF.EmitVarDecl(*VDecl);
|
||||
return CGF.EmitLValue(Helper);
|
||||
}
|
||||
|
||||
static std::pair<LValue, LValue>
|
||||
emitDistributeParallelForInnerBounds(CodeGenFunction &CGF,
|
||||
const OMPExecutableDirective &S) {
|
||||
@ -4721,3 +4792,35 @@ void CodeGenFunction::EmitOMPTargetUpdateDirective(
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitSimpleOMPExecutableDirective(
|
||||
const OMPExecutableDirective &D) {
|
||||
if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
|
||||
return;
|
||||
auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) {
|
||||
if (isOpenMPSimdDirective(D.getDirectiveKind())) {
|
||||
emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
|
||||
} else {
|
||||
if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
|
||||
for (const auto *E : LD->counters()) {
|
||||
if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
|
||||
cast<DeclRefExpr>(E)->getDecl())) {
|
||||
// Emit only those that were not explicitly referenced in clauses.
|
||||
if (!CGF.LocalDeclMap.count(VD))
|
||||
CGF.EmitVarDecl(*VD);
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
|
||||
while (const auto *CCS = dyn_cast<CapturedStmt>(CS->getCapturedStmt()))
|
||||
CS = CCS;
|
||||
CGF.EmitStmt(CS->getCapturedStmt());
|
||||
}
|
||||
};
|
||||
OMPSimdLexicalScope Scope(*this, D);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(
|
||||
*this,
|
||||
isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
|
||||
: D.getDirectiveKind(),
|
||||
CodeGen);
|
||||
}
|
||||
|
@ -419,6 +419,9 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
|
||||
EmitIfUsed(*this, TerminateHandler);
|
||||
EmitIfUsed(*this, UnreachableBlock);
|
||||
|
||||
for (const auto &FuncletAndParent : TerminateFunclets)
|
||||
EmitIfUsed(*this, FuncletAndParent.second);
|
||||
|
||||
if (CGM.getCodeGenOpts().EmitDeclMetadata)
|
||||
EmitDeclMetadata();
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "clang/Frontend/CodeGenOptions.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
@ -1420,6 +1421,9 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
llvm::BasicBlock *TerminateHandler;
|
||||
llvm::BasicBlock *TrapBB;
|
||||
|
||||
/// Terminate funclets keyed by parent funclet pad.
|
||||
llvm::MapVector<llvm::Value *, llvm::BasicBlock *> TerminateFunclets;
|
||||
|
||||
/// True if we need emit the life-time markers.
|
||||
const bool ShouldEmitLifetimeMarkers;
|
||||
|
||||
@ -1808,6 +1812,10 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
/// getTerminateLandingPad - Return a landing pad that just calls terminate.
|
||||
llvm::BasicBlock *getTerminateLandingPad();
|
||||
|
||||
/// getTerminateLandingPad - Return a cleanup funclet that just calls
|
||||
/// terminate.
|
||||
llvm::BasicBlock *getTerminateFunclet();
|
||||
|
||||
/// getTerminateHandler - Return a handler (not a landing pad, just
|
||||
/// a catch handler) that just calls terminate. This is used when
|
||||
/// a terminate scope encloses a try.
|
||||
@ -2655,6 +2663,9 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
llvm::Value *EmitSEHExceptionInfo();
|
||||
llvm::Value *EmitSEHAbnormalTermination();
|
||||
|
||||
/// Emit simple code for OpenMP directives in Simd-only mode.
|
||||
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D);
|
||||
|
||||
/// Scan the outlined statement for captures from the parent function. For
|
||||
/// each capture, mark the capture as escaped and emit a call to
|
||||
/// llvm.localrecover. Insert the localrecover result into the LocalDeclMap.
|
||||
|
@ -208,6 +208,9 @@ void CodeGenModule::createOpenMPRuntime() {
|
||||
OpenMPRuntime.reset(new CGOpenMPRuntimeNVPTX(*this));
|
||||
break;
|
||||
default:
|
||||
if (LangOpts.OpenMPSimd)
|
||||
OpenMPRuntime.reset(new CGOpenMPSIMDRuntime(*this));
|
||||
else
|
||||
OpenMPRuntime.reset(new CGOpenMPRuntime(*this));
|
||||
break;
|
||||
}
|
||||
@ -4515,6 +4518,9 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
|
||||
// Do not emit threadprivates in simd-only mode.
|
||||
if (LangOpts.OpenMP && LangOpts.OpenMPSimd)
|
||||
return;
|
||||
for (auto RefExpr : D->varlists()) {
|
||||
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(RefExpr)->getDecl());
|
||||
bool PerformInit =
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "llvm/Option/OptSpecifier.h"
|
||||
#include "llvm/Option/OptTable.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
@ -70,6 +71,7 @@
|
||||
#include "llvm/Support/Program.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
@ -92,7 +94,8 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
|
||||
CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
|
||||
CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false),
|
||||
CCGenDiagnostics(false), DefaultTargetTriple(DefaultTargetTriple),
|
||||
CCCGenericGCCName(""), CheckInputsExist(true), CCCUsePCH(true),
|
||||
CCCGenericGCCName(""), Saver(Alloc),
|
||||
CheckInputsExist(true), CCCUsePCH(true),
|
||||
GenReproducer(false), SuppressMissingInputWarning(false) {
|
||||
|
||||
// Provide a sane fallback if no VFS is specified.
|
||||
@ -103,6 +106,13 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
|
||||
Dir = llvm::sys::path::parent_path(ClangExecutable);
|
||||
InstalledDir = Dir; // Provide a sensible default installed dir.
|
||||
|
||||
#if defined(CLANG_CONFIG_FILE_SYSTEM_DIR)
|
||||
SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;
|
||||
#endif
|
||||
#if defined(CLANG_CONFIG_FILE_USER_DIR)
|
||||
UserConfigDir = CLANG_CONFIG_FILE_USER_DIR;
|
||||
#endif
|
||||
|
||||
// Compute the path to the resource directory.
|
||||
StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
|
||||
SmallString<128> P(Dir);
|
||||
@ -600,6 +610,216 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
|
||||
//
|
||||
}
|
||||
|
||||
/// Looks the given directories for the specified file.
|
||||
///
|
||||
/// \param[out] FilePath File path, if the file was found.
|
||||
/// \param[in] Dirs Directories used for the search.
|
||||
/// \param[in] FileName Name of the file to search for.
|
||||
/// \return True if file was found.
|
||||
///
|
||||
/// Looks for file specified by FileName sequentially in directories specified
|
||||
/// by Dirs.
|
||||
///
|
||||
static bool searchForFile(SmallVectorImpl<char> &FilePath,
|
||||
ArrayRef<std::string> Dirs,
|
||||
StringRef FileName) {
|
||||
SmallString<128> WPath;
|
||||
for (const StringRef &Dir : Dirs) {
|
||||
if (Dir.empty())
|
||||
continue;
|
||||
WPath.clear();
|
||||
llvm::sys::path::append(WPath, Dir, FileName);
|
||||
llvm::sys::path::native(WPath);
|
||||
if (llvm::sys::fs::is_regular_file(WPath)) {
|
||||
FilePath = std::move(WPath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Driver::readConfigFile(StringRef FileName) {
|
||||
// Try reading the given file.
|
||||
SmallVector<const char *, 32> NewCfgArgs;
|
||||
if (!llvm::cl::readConfigFile(FileName, Saver, NewCfgArgs)) {
|
||||
Diag(diag::err_drv_cannot_read_config_file) << FileName;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read options from config file.
|
||||
llvm::SmallString<128> CfgFileName(FileName);
|
||||
llvm::sys::path::native(CfgFileName);
|
||||
ConfigFile = CfgFileName.str();
|
||||
bool ContainErrors;
|
||||
CfgOptions = llvm::make_unique<InputArgList>(
|
||||
ParseArgStrings(NewCfgArgs, ContainErrors));
|
||||
if (ContainErrors) {
|
||||
CfgOptions.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CfgOptions->hasArg(options::OPT_config)) {
|
||||
CfgOptions.reset();
|
||||
Diag(diag::err_drv_nested_config_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Claim all arguments that come from a configuration file so that the driver
|
||||
// does not warn on any that is unused.
|
||||
for (Arg *A : *CfgOptions)
|
||||
A->claim();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Driver::loadConfigFile() {
|
||||
std::string CfgFileName;
|
||||
bool FileSpecifiedExplicitly = false;
|
||||
|
||||
// Process options that change search path for config files.
|
||||
if (CLOptions) {
|
||||
if (CLOptions->hasArg(options::OPT_config_system_dir_EQ)) {
|
||||
SmallString<128> CfgDir;
|
||||
CfgDir.append(
|
||||
CLOptions->getLastArgValue(options::OPT_config_system_dir_EQ));
|
||||
if (!CfgDir.empty()) {
|
||||
if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
|
||||
SystemConfigDir.clear();
|
||||
else
|
||||
SystemConfigDir = std::string(CfgDir.begin(), CfgDir.end());
|
||||
}
|
||||
}
|
||||
if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) {
|
||||
SmallString<128> CfgDir;
|
||||
CfgDir.append(
|
||||
CLOptions->getLastArgValue(options::OPT_config_user_dir_EQ));
|
||||
if (!CfgDir.empty()) {
|
||||
if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
|
||||
UserConfigDir.clear();
|
||||
else
|
||||
UserConfigDir = std::string(CfgDir.begin(), CfgDir.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// First try to find config file specified in command line.
|
||||
if (CLOptions) {
|
||||
std::vector<std::string> ConfigFiles =
|
||||
CLOptions->getAllArgValues(options::OPT_config);
|
||||
if (ConfigFiles.size() > 1) {
|
||||
Diag(diag::err_drv_duplicate_config);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ConfigFiles.empty()) {
|
||||
CfgFileName = ConfigFiles.front();
|
||||
assert(!CfgFileName.empty());
|
||||
|
||||
// If argument contains directory separator, treat it as a path to
|
||||
// configuration file.
|
||||
if (llvm::sys::path::has_parent_path(CfgFileName)) {
|
||||
SmallString<128> CfgFilePath;
|
||||
if (llvm::sys::path::is_relative(CfgFileName))
|
||||
llvm::sys::fs::current_path(CfgFilePath);
|
||||
llvm::sys::path::append(CfgFilePath, CfgFileName);
|
||||
if (!llvm::sys::fs::is_regular_file(CfgFilePath)) {
|
||||
Diag(diag::err_drv_config_file_not_exist) << CfgFilePath;
|
||||
return true;
|
||||
}
|
||||
return readConfigFile(CfgFilePath);
|
||||
}
|
||||
|
||||
FileSpecifiedExplicitly = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If config file is not specified explicitly, try to deduce configuration
|
||||
// from executable name. For instance, an executable 'armv7l-clang' will
|
||||
// search for config file 'armv7l-clang.cfg'.
|
||||
if (CfgFileName.empty() && !ClangNameParts.TargetPrefix.empty())
|
||||
CfgFileName = ClangNameParts.TargetPrefix + '-' + ClangNameParts.ModeSuffix;
|
||||
|
||||
if (CfgFileName.empty())
|
||||
return false;
|
||||
|
||||
// Determine architecture part of the file name, if it is present.
|
||||
StringRef CfgFileArch = CfgFileName;
|
||||
size_t ArchPrefixLen = CfgFileArch.find('-');
|
||||
if (ArchPrefixLen == StringRef::npos)
|
||||
ArchPrefixLen = CfgFileArch.size();
|
||||
llvm::Triple CfgTriple;
|
||||
CfgFileArch = CfgFileArch.take_front(ArchPrefixLen);
|
||||
CfgTriple = llvm::Triple(llvm::Triple::normalize(CfgFileArch));
|
||||
if (CfgTriple.getArch() == llvm::Triple::ArchType::UnknownArch)
|
||||
ArchPrefixLen = 0;
|
||||
|
||||
if (!StringRef(CfgFileName).endswith(".cfg"))
|
||||
CfgFileName += ".cfg";
|
||||
|
||||
// If config file starts with architecture name and command line options
|
||||
// redefine architecture (with options like -m32 -LE etc), try finding new
|
||||
// config file with that architecture.
|
||||
SmallString<128> FixedConfigFile;
|
||||
size_t FixedArchPrefixLen = 0;
|
||||
if (ArchPrefixLen) {
|
||||
// Get architecture name from config file name like 'i386.cfg' or
|
||||
// 'armv7l-clang.cfg'.
|
||||
// Check if command line options changes effective triple.
|
||||
llvm::Triple EffectiveTriple = computeTargetTriple(*this,
|
||||
CfgTriple.getTriple(), *CLOptions);
|
||||
if (CfgTriple.getArch() != EffectiveTriple.getArch()) {
|
||||
FixedConfigFile = EffectiveTriple.getArchName();
|
||||
FixedArchPrefixLen = FixedConfigFile.size();
|
||||
// Append the rest of original file name so that file name transforms
|
||||
// like: i386-clang.cfg -> x86_64-clang.cfg.
|
||||
if (ArchPrefixLen < CfgFileName.size())
|
||||
FixedConfigFile += CfgFileName.substr(ArchPrefixLen);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare list of directories where config file is searched for.
|
||||
SmallVector<std::string, 3> CfgFileSearchDirs;
|
||||
CfgFileSearchDirs.push_back(UserConfigDir);
|
||||
CfgFileSearchDirs.push_back(SystemConfigDir);
|
||||
CfgFileSearchDirs.push_back(Dir);
|
||||
|
||||
// Try to find config file. First try file with corrected architecture.
|
||||
llvm::SmallString<128> CfgFilePath;
|
||||
if (!FixedConfigFile.empty()) {
|
||||
if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile))
|
||||
return readConfigFile(CfgFilePath);
|
||||
// If 'x86_64-clang.cfg' was not found, try 'x86_64.cfg'.
|
||||
FixedConfigFile.resize(FixedArchPrefixLen);
|
||||
FixedConfigFile.append(".cfg");
|
||||
if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile))
|
||||
return readConfigFile(CfgFilePath);
|
||||
}
|
||||
|
||||
// Then try original file name.
|
||||
if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName))
|
||||
return readConfigFile(CfgFilePath);
|
||||
|
||||
// Finally try removing driver mode part: 'x86_64-clang.cfg' -> 'x86_64.cfg'.
|
||||
if (!ClangNameParts.ModeSuffix.empty() &&
|
||||
!ClangNameParts.TargetPrefix.empty()) {
|
||||
CfgFileName.assign(ClangNameParts.TargetPrefix);
|
||||
CfgFileName.append(".cfg");
|
||||
if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName))
|
||||
return readConfigFile(CfgFilePath);
|
||||
}
|
||||
|
||||
// Report error but only if config file was specified explicitly, by option
|
||||
// --config. If it was deduced from executable name, it is not an error.
|
||||
if (FileSpecifiedExplicitly) {
|
||||
Diag(diag::err_drv_config_file_not_found) << CfgFileName;
|
||||
for (const std::string &SearchDir : CfgFileSearchDirs)
|
||||
if (!SearchDir.empty())
|
||||
Diag(diag::note_drv_config_file_searched_in) << SearchDir;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
|
||||
llvm::PrettyStackTraceString CrashInfo("Compilation construction");
|
||||
|
||||
@ -623,12 +843,35 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
|
||||
|
||||
// FIXME: What are we going to do with -V and -b?
|
||||
|
||||
// Arguments specified in command line.
|
||||
bool ContainsError;
|
||||
CLOptions = llvm::make_unique<InputArgList>(
|
||||
ParseArgStrings(ArgList.slice(1), ContainsError));
|
||||
|
||||
// Try parsing configuration file.
|
||||
if (!ContainsError)
|
||||
ContainsError = loadConfigFile();
|
||||
bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
|
||||
|
||||
// All arguments, from both config file and command line.
|
||||
InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
|
||||
: std::move(*CLOptions));
|
||||
if (HasConfigFile)
|
||||
for (auto *Opt : *CLOptions) {
|
||||
const Arg *BaseArg = &Opt->getBaseArg();
|
||||
if (BaseArg == Opt)
|
||||
BaseArg = nullptr;
|
||||
Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Opt->getSpelling(),
|
||||
Args.size(), BaseArg);
|
||||
Copy->getValues() = Opt->getValues();
|
||||
if (Opt->isClaimed())
|
||||
Copy->claim();
|
||||
Args.append(Copy);
|
||||
}
|
||||
|
||||
// FIXME: This stuff needs to go into the Compilation, not the driver.
|
||||
bool CCCPrintPhases;
|
||||
|
||||
bool ContainsError;
|
||||
InputArgList Args = ParseArgStrings(ArgList.slice(1), ContainsError);
|
||||
|
||||
// Silence driver warnings if requested
|
||||
Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
|
||||
|
||||
@ -1144,6 +1387,10 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
|
||||
|
||||
// Print out the install directory.
|
||||
OS << "InstalledDir: " << InstalledDir << '\n';
|
||||
|
||||
// If configuration file was used, print its path.
|
||||
if (!ConfigFile.empty())
|
||||
OS << "Configuration file: " << ConfigFile << '\n';
|
||||
}
|
||||
|
||||
/// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
|
||||
@ -1250,6 +1497,15 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
|
||||
SuppressMissingInputWarning = true;
|
||||
}
|
||||
|
||||
if (C.getArgs().hasArg(options::OPT_v)) {
|
||||
if (!SystemConfigDir.empty())
|
||||
llvm::errs() << "System configuration file directory: "
|
||||
<< SystemConfigDir << "\n";
|
||||
if (!UserConfigDir.empty())
|
||||
llvm::errs() << "User configuration file directory: "
|
||||
<< UserConfigDir << "\n";
|
||||
}
|
||||
|
||||
const ToolChain &TC = C.getDefaultToolChain();
|
||||
|
||||
if (C.getArgs().hasArg(options::OPT_v))
|
||||
|
@ -3901,6 +3901,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
// semantic analysis, etc.
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
|
||||
options::OPT_fno_openmp_simd);
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
|
||||
}
|
||||
|
||||
const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
|
||||
|
@ -1192,6 +1192,13 @@ struct DarwinPlatform {
|
||||
return OSVersion;
|
||||
}
|
||||
|
||||
void setOSVersion(StringRef S) {
|
||||
assert(Kind == TargetArg && "Unexpected kind!");
|
||||
OSVersion = S;
|
||||
}
|
||||
|
||||
bool hasOSVersion() const { return HasOSVersion; }
|
||||
|
||||
/// Returns true if the target OS was explicitly specified.
|
||||
bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
|
||||
|
||||
@ -1235,17 +1242,21 @@ struct DarwinPlatform {
|
||||
llvm_unreachable("Unsupported Darwin Source Kind");
|
||||
}
|
||||
|
||||
static DarwinPlatform createFromTarget(llvm::Triple::OSType OS,
|
||||
StringRef OSVersion, Arg *A,
|
||||
llvm::Triple::EnvironmentType Env) {
|
||||
DarwinPlatform Result(TargetArg, getPlatformFromOS(OS), OSVersion, A);
|
||||
switch (Env) {
|
||||
static DarwinPlatform createFromTarget(const llvm::Triple &TT,
|
||||
StringRef OSVersion, Arg *A) {
|
||||
DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
|
||||
A);
|
||||
switch (TT.getEnvironment()) {
|
||||
case llvm::Triple::Simulator:
|
||||
Result.Environment = DarwinEnvironmentKind::Simulator;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
unsigned Major, Minor, Micro;
|
||||
TT.getOSVersion(Major, Minor, Micro);
|
||||
if (Major == 0)
|
||||
Result.HasOSVersion = false;
|
||||
return Result;
|
||||
}
|
||||
static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
|
||||
@ -1295,6 +1306,7 @@ struct DarwinPlatform {
|
||||
DarwinPlatformKind Platform;
|
||||
DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
|
||||
std::string OSVersion;
|
||||
bool HasOSVersion = true;
|
||||
Arg *Argument;
|
||||
StringRef EnvVarName;
|
||||
};
|
||||
@ -1489,9 +1501,8 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
|
||||
Triple.getOS() == llvm::Triple::UnknownOS)
|
||||
return None;
|
||||
std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
|
||||
return DarwinPlatform::createFromTarget(Triple.getOS(), OSVersion,
|
||||
Args.getLastArg(options::OPT_target),
|
||||
Triple.getEnvironment());
|
||||
return DarwinPlatform::createFromTarget(Triple, OSVersion,
|
||||
Args.getLastArg(options::OPT_target));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -1537,14 +1548,22 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
|
||||
(VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
|
||||
VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
|
||||
TargetExtra != ArgExtra))) {
|
||||
// Select the OS version from the -m<os>-version-min argument when
|
||||
// the -target does not include an OS version.
|
||||
if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
|
||||
!OSTarget->hasOSVersion()) {
|
||||
OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
|
||||
} else {
|
||||
// Warn about -m<os>-version-min that doesn't match the OS version
|
||||
// that's specified in the target.
|
||||
std::string OSVersionArg = OSVersionArgTarget->getAsString(Args, Opts);
|
||||
std::string OSVersionArg =
|
||||
OSVersionArgTarget->getAsString(Args, Opts);
|
||||
std::string TargetArg = OSTarget->getAsString(Args, Opts);
|
||||
getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
|
||||
<< OSVersionArg << TargetArg;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The OS target can be specified using the -m<os>version-min argument.
|
||||
OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
|
||||
|
@ -2407,16 +2407,22 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
||||
|
||||
// Check if -fopenmp is specified.
|
||||
Opts.OpenMP = Args.hasArg(options::OPT_fopenmp) ? 1 : 0;
|
||||
// Check if -fopenmp-simd is specified.
|
||||
Opts.OpenMPSimd = !Opts.OpenMP && Args.hasFlag(options::OPT_fopenmp_simd,
|
||||
options::OPT_fno_openmp_simd,
|
||||
/*Default=*/false);
|
||||
Opts.OpenMPUseTLS =
|
||||
Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
|
||||
Opts.OpenMPIsDevice =
|
||||
Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device);
|
||||
|
||||
if (Opts.OpenMP) {
|
||||
int Version =
|
||||
getLastArgIntValue(Args, OPT_fopenmp_version_EQ, Opts.OpenMP, Diags);
|
||||
if (Version != 0)
|
||||
if (Opts.OpenMP || Opts.OpenMPSimd) {
|
||||
if (int Version =
|
||||
getLastArgIntValue(Args, OPT_fopenmp_version_EQ,
|
||||
Opts.OpenMPSimd ? 45 : Opts.OpenMP, Diags))
|
||||
Opts.OpenMP = Version;
|
||||
else if (Opts.OpenMPSimd)
|
||||
Opts.OpenMP = 45;
|
||||
// Provide diagnostic when a given target is not expected to be an OpenMP
|
||||
// device or host.
|
||||
if (!Opts.OpenMPIsDevice) {
|
||||
|
@ -1021,8 +1021,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
||||
Builder.defineMacro("_OPENMP", "201511");
|
||||
break;
|
||||
default:
|
||||
// Default version is OpenMP 3.1
|
||||
Builder.defineMacro("_OPENMP", "201107");
|
||||
// Default version is OpenMP 3.1, in Simd only mode - 4.5
|
||||
Builder.defineMacro("_OPENMP", LangOpts.OpenMPSimd ? "201511" : "201107");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -217,8 +217,8 @@ _mm_div_pd(__m128d __a, __m128d __b)
|
||||
|
||||
/// \brief Calculates the square root of the lower double-precision value of
|
||||
/// the second operand and returns it in the lower 64 bits of the result.
|
||||
/// The upper 64 bits of the result are copied from the upper double-
|
||||
/// precision value of the first operand.
|
||||
/// The upper 64 bits of the result are copied from the upper
|
||||
/// double-precision value of the first operand.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -260,8 +260,8 @@ _mm_sqrt_pd(__m128d __a)
|
||||
|
||||
/// \brief Compares lower 64-bit double-precision values of both operands, and
|
||||
/// returns the lesser of the pair of values in the lower 64-bits of the
|
||||
/// result. The upper 64 bits of the result are copied from the upper double-
|
||||
/// precision value of the first operand.
|
||||
/// result. The upper 64 bits of the result are copied from the upper
|
||||
/// double-precision value of the first operand.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -304,8 +304,8 @@ _mm_min_pd(__m128d __a, __m128d __b)
|
||||
|
||||
/// \brief Compares lower 64-bit double-precision values of both operands, and
|
||||
/// returns the greater of the pair of values in the lower 64-bits of the
|
||||
/// result. The upper 64 bits of the result are copied from the upper double-
|
||||
/// precision value of the first operand.
|
||||
/// result. The upper 64 bits of the result are copied from the upper
|
||||
/// double-precision value of the first operand.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -983,8 +983,10 @@ _mm_cmpnge_sd(__m128d __a, __m128d __b)
|
||||
}
|
||||
|
||||
/// \brief Compares the lower double-precision floating-point values in each of
|
||||
/// the two 128-bit floating-point vectors of [2 x double] for equality. The
|
||||
/// comparison yields 0 for false, 1 for true.
|
||||
/// the two 128-bit floating-point vectors of [2 x double] for equality.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -996,7 +998,8 @@ _mm_cmpnge_sd(__m128d __a, __m128d __b)
|
||||
/// \param __b
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_comieq_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1008,7 +1011,8 @@ _mm_comieq_sd(__m128d __a, __m128d __b)
|
||||
/// the value in the first parameter is less than the corresponding value in
|
||||
/// the second parameter.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true.
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1020,7 +1024,8 @@ _mm_comieq_sd(__m128d __a, __m128d __b)
|
||||
/// \param __b
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_comilt_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1032,7 +1037,8 @@ _mm_comilt_sd(__m128d __a, __m128d __b)
|
||||
/// the value in the first parameter is less than or equal to the
|
||||
/// corresponding value in the second parameter.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true.
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1044,7 +1050,8 @@ _mm_comilt_sd(__m128d __a, __m128d __b)
|
||||
/// \param __b
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_comile_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1056,7 +1063,8 @@ _mm_comile_sd(__m128d __a, __m128d __b)
|
||||
/// the value in the first parameter is greater than the corresponding value
|
||||
/// in the second parameter.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true.
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1068,7 +1076,8 @@ _mm_comile_sd(__m128d __a, __m128d __b)
|
||||
/// \param __b
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_comigt_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1080,7 +1089,8 @@ _mm_comigt_sd(__m128d __a, __m128d __b)
|
||||
/// the value in the first parameter is greater than or equal to the
|
||||
/// corresponding value in the second parameter.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true.
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1092,7 +1102,8 @@ _mm_comigt_sd(__m128d __a, __m128d __b)
|
||||
/// \param __b
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_comige_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1104,7 +1115,8 @@ _mm_comige_sd(__m128d __a, __m128d __b)
|
||||
/// the value in the first parameter is unequal to the corresponding value in
|
||||
/// the second parameter.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true.
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two
|
||||
/// lower double-precision values is NaN, 1 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1116,7 +1128,8 @@ _mm_comige_sd(__m128d __a, __m128d __b)
|
||||
/// \param __b
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 1 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_comineq_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1127,7 +1140,7 @@ _mm_comineq_sd(__m128d __a, __m128d __b)
|
||||
/// the two 128-bit floating-point vectors of [2 x double] for equality. The
|
||||
/// comparison yields 0 for false, 1 for true.
|
||||
///
|
||||
/// If either of the two lower double-precision values is NaN, 1 is returned.
|
||||
/// If either of the two lower double-precision values is NaN, 0 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1140,7 +1153,7 @@ _mm_comineq_sd(__m128d __a, __m128d __b)
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 1 is returned.
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_ucomieq_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1153,7 +1166,7 @@ _mm_ucomieq_sd(__m128d __a, __m128d __b)
|
||||
/// the second parameter.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two lower
|
||||
/// double-precision values is NaN, 1 is returned.
|
||||
/// double-precision values is NaN, 0 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1166,7 +1179,7 @@ _mm_ucomieq_sd(__m128d __a, __m128d __b)
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 1 is returned.
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_ucomilt_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1179,7 +1192,7 @@ _mm_ucomilt_sd(__m128d __a, __m128d __b)
|
||||
/// corresponding value in the second parameter.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two lower
|
||||
/// double-precision values is NaN, 1 is returned.
|
||||
/// double-precision values is NaN, 0 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1192,7 +1205,7 @@ _mm_ucomilt_sd(__m128d __a, __m128d __b)
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison results. If either of the two
|
||||
/// lower double-precision values is NaN, 1 is returned.
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_ucomile_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1257,7 +1270,7 @@ _mm_ucomige_sd(__m128d __a, __m128d __b)
|
||||
/// the second parameter.
|
||||
///
|
||||
/// The comparison yields 0 for false, 1 for true. If either of the two lower
|
||||
/// double-precision values is NaN, 0 is returned.
|
||||
/// double-precision values is NaN, 1 is returned.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -1270,7 +1283,7 @@ _mm_ucomige_sd(__m128d __a, __m128d __b)
|
||||
/// A 128-bit vector of [2 x double]. The lower double-precision value is
|
||||
/// compared to the lower double-precision value of \a __a.
|
||||
/// \returns An integer containing the comparison result. If either of the two
|
||||
/// lower double-precision values is NaN, 0 is returned.
|
||||
/// lower double-precision values is NaN, 1 is returned.
|
||||
static __inline__ int __DEFAULT_FN_ATTRS
|
||||
_mm_ucomineq_sd(__m128d __a, __m128d __b)
|
||||
{
|
||||
@ -1935,14 +1948,15 @@ _mm_store_pd(double *__dp, __m128d __a)
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
/// This intrinsic corresponds to the <c>VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
|
||||
/// This intrinsic corresponds to the
|
||||
/// <c> VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
|
||||
///
|
||||
/// \param __dp
|
||||
/// A pointer to a memory location that can store two double-precision
|
||||
/// values.
|
||||
/// \param __a
|
||||
/// A 128-bit vector of [2 x double] whose lower 64 bits are copied to each
|
||||
/// of the values in \a dp.
|
||||
/// of the values in \a __dp.
|
||||
static __inline__ void __DEFAULT_FN_ATTRS
|
||||
_mm_store1_pd(double *__dp, __m128d __a)
|
||||
{
|
||||
@ -1950,18 +1964,20 @@ _mm_store1_pd(double *__dp, __m128d __a)
|
||||
_mm_store_pd(__dp, __a);
|
||||
}
|
||||
|
||||
/// \brief Stores a 128-bit vector of [2 x double] into an aligned memory
|
||||
/// location.
|
||||
/// \brief Moves the lower 64 bits of a 128-bit vector of [2 x double] twice to
|
||||
/// the upper and lower 64 bits of a memory location.
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
/// This intrinsic corresponds to the <c> VMOVAPD / MOVAPD </c> instruction.
|
||||
/// This intrinsic corresponds to the
|
||||
/// <c> VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
|
||||
///
|
||||
/// \param __dp
|
||||
/// A pointer to a 128-bit memory location. The address of the memory
|
||||
/// location has to be 16-byte aligned.
|
||||
/// A pointer to a memory location that can store two double-precision
|
||||
/// values.
|
||||
/// \param __a
|
||||
/// A 128-bit vector of [2 x double] containing the values to be stored.
|
||||
/// A 128-bit vector of [2 x double] whose lower 64 bits are copied to each
|
||||
/// of the values in \a __dp.
|
||||
static __inline__ void __DEFAULT_FN_ATTRS
|
||||
_mm_store_pd1(double *__dp, __m128d __a)
|
||||
{
|
||||
@ -3846,8 +3862,7 @@ _mm_set1_epi8(char __b)
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
/// This intrinsic corresponds to the <c> VPUNPCKLQDQ / PUNPCKLQDQ </c>
|
||||
/// instruction.
|
||||
/// This intrinsic does not correspond to a specific instruction.
|
||||
///
|
||||
/// \param __q0
|
||||
/// A 64-bit integral value used to initialize the lower 64 bits of the
|
||||
@ -4018,7 +4033,7 @@ _mm_storeu_si128(__m128i *__p, __m128i __b)
|
||||
/// specified unaligned memory location. When a mask bit is 1, the
|
||||
/// corresponding byte is written, otherwise it is not written.
|
||||
///
|
||||
/// To minimize caching, the date is flagged as non-temporal (unlikely to be
|
||||
/// To minimize caching, the data is flagged as non-temporal (unlikely to be
|
||||
/// used again soon). Exception and trap behavior for elements not selected
|
||||
/// for storage to memory are implementation dependent.
|
||||
///
|
||||
@ -4532,8 +4547,8 @@ _mm_unpackhi_epi32(__m128i __a, __m128i __b)
|
||||
return (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si)__b, 2, 4+2, 3, 4+3);
|
||||
}
|
||||
|
||||
/// \brief Unpacks the high-order (odd-indexed) values from two 128-bit vectors
|
||||
/// of [2 x i64] and interleaves them into a 128-bit vector of [2 x i64].
|
||||
/// \brief Unpacks the high-order 64-bit elements from two 128-bit vectors of
|
||||
/// [2 x i64] and interleaves them into a 128-bit vector of [2 x i64].
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
@ -4665,7 +4680,7 @@ _mm_unpacklo_epi64(__m128i __a, __m128i __b)
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
/// This intrinsic has no corresponding instruction.
|
||||
/// This intrinsic corresponds to the <c> MOVDQ2Q </c> instruction.
|
||||
///
|
||||
/// \param __a
|
||||
/// A 128-bit integer vector operand. The lower 64 bits are moved to the
|
||||
@ -4682,7 +4697,7 @@ _mm_movepi64_pi64(__m128i __a)
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
///
|
||||
/// This intrinsic corresponds to the <c> VMOVQ / MOVQ / MOVD </c> instruction.
|
||||
/// This intrinsic corresponds to the <c> MOVD+VMOVQ </c> instruction.
|
||||
///
|
||||
/// \param __a
|
||||
/// A 64-bit value.
|
||||
@ -4712,8 +4727,8 @@ _mm_move_epi64(__m128i __a)
|
||||
return __builtin_shufflevector((__v2di)__a, (__m128i){ 0 }, 0, 2);
|
||||
}
|
||||
|
||||
/// \brief Unpacks the high-order (odd-indexed) values from two 128-bit vectors
|
||||
/// of [2 x double] and interleaves them into a 128-bit vector of [2 x
|
||||
/// \brief Unpacks the high-order 64-bit elements from two 128-bit vectors of
|
||||
/// [2 x double] and interleaves them into a 128-bit vector of [2 x
|
||||
/// double].
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
@ -4733,7 +4748,7 @@ _mm_unpackhi_pd(__m128d __a, __m128d __b)
|
||||
return __builtin_shufflevector((__v2df)__a, (__v2df)__b, 1, 2+1);
|
||||
}
|
||||
|
||||
/// \brief Unpacks the low-order (even-indexed) values from two 128-bit vectors
|
||||
/// \brief Unpacks the low-order 64-bit elements from two 128-bit vectors
|
||||
/// of [2 x double] and interleaves them into a 128-bit vector of [2 x
|
||||
/// double].
|
||||
///
|
||||
@ -4792,9 +4807,9 @@ _mm_movemask_pd(__m128d __a)
|
||||
/// A 128-bit vector of [2 x double].
|
||||
/// \param i
|
||||
/// An 8-bit immediate value. The least significant two bits specify which
|
||||
/// elements to copy from a and b: \n
|
||||
/// Bit[0] = 0: lower element of a copied to lower element of result. \n
|
||||
/// Bit[0] = 1: upper element of a copied to lower element of result. \n
|
||||
/// elements to copy from \a a and \a b: \n
|
||||
/// Bit[0] = 0: lower element of \a a copied to lower element of result. \n
|
||||
/// Bit[0] = 1: upper element of \a a copied to lower element of result. \n
|
||||
/// Bit[1] = 0: lower element of \a b copied to upper element of result. \n
|
||||
/// Bit[1] = 1: upper element of \a b copied to upper element of result. \n
|
||||
/// \returns A 128-bit vector of [2 x double] containing the shuffled values.
|
||||
|
@ -115,8 +115,8 @@ _mm_hsub_ps(__m128 __a, __m128 __b)
|
||||
return __builtin_ia32_hsubps((__v4sf)__a, (__v4sf)__b);
|
||||
}
|
||||
|
||||
/// \brief Moves and duplicates high-order (odd-indexed) values from a 128-bit
|
||||
/// vector of [4 x float] to float values stored in a 128-bit vector of
|
||||
/// \brief Moves and duplicates odd-indexed values from a 128-bit vector
|
||||
/// of [4 x float] to float values stored in a 128-bit vector of
|
||||
/// [4 x float].
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
@ -137,7 +137,7 @@ _mm_movehdup_ps(__m128 __a)
|
||||
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 1, 1, 3, 3);
|
||||
}
|
||||
|
||||
/// \brief Duplicates low-order (even-indexed) values from a 128-bit vector of
|
||||
/// \brief Duplicates even-indexed values from a 128-bit vector of
|
||||
/// [4 x float] to float values stored in a 128-bit vector of [4 x float].
|
||||
///
|
||||
/// \headerfile <x86intrin.h>
|
||||
|
@ -648,7 +648,7 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
|
||||
/// input vectors are used as an input for dot product; otherwise that input
|
||||
/// is treated as zero. Bits [1:0] determine which elements of the result
|
||||
/// will receive a copy of the final dot product, with bit [0] corresponding
|
||||
/// to the lowest element and bit [3] corresponding to the highest element of
|
||||
/// to the lowest element and bit [1] corresponding to the highest element of
|
||||
/// each [2 x double] vector. If a bit is set, the dot product is returned in
|
||||
/// the corresponding element; otherwise that element is set to zero.
|
||||
#define _mm_dp_pd(X, Y, M) __extension__ ({\
|
||||
@ -866,8 +866,8 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
|
||||
/// 11: Copies the selected bits from \a Y to result bits [127:96]. \n
|
||||
/// Bits[3:0]: If any of these bits are set, the corresponding result
|
||||
/// element is cleared.
|
||||
/// \returns A 128-bit vector of [4 x float] containing the copied single-
|
||||
/// precision floating point elements from the operands.
|
||||
/// \returns A 128-bit vector of [4 x float] containing the copied
|
||||
/// single-precision floating point elements from the operands.
|
||||
#define _mm_insert_ps(X, Y, N) __builtin_ia32_insertps128((X), (Y), (N))
|
||||
|
||||
/// \brief Extracts a 32-bit integer from a 128-bit vector of [4 x float] and
|
||||
|
@ -43,13 +43,13 @@ using namespace clang;
|
||||
///
|
||||
/// Called type-id in C++.
|
||||
TypeResult Parser::ParseTypeName(SourceRange *Range,
|
||||
Declarator::TheContext Context,
|
||||
DeclaratorContext Context,
|
||||
AccessSpecifier AS,
|
||||
Decl **OwnedType,
|
||||
ParsedAttributes *Attrs) {
|
||||
DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
|
||||
if (DSC == DSC_normal)
|
||||
DSC = DSC_type_specifier;
|
||||
if (DSC == DeclSpecContext::DSC_normal)
|
||||
DSC = DeclSpecContext::DSC_type_specifier;
|
||||
|
||||
// Parse the common declaration-specifiers piece.
|
||||
DeclSpec DS(AttrFactory);
|
||||
@ -1639,7 +1639,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
|
||||
|
||||
/// ParseDeclaration - Parse a full 'declaration', which consists of
|
||||
/// declaration-specifiers, some number of declarators, and a semicolon.
|
||||
/// 'Context' should be a Declarator::TheContext value. This returns the
|
||||
/// 'Context' should be a DeclaratorContext value. This returns the
|
||||
/// location of the semicolon in DeclEnd.
|
||||
///
|
||||
/// declaration: [C99 6.7]
|
||||
@ -1653,7 +1653,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
|
||||
/// [C++11/C11] static_assert-declaration
|
||||
/// others... [FIXME]
|
||||
///
|
||||
Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
|
||||
Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
ParsedAttributesWithRange &attrs) {
|
||||
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
||||
@ -1714,7 +1714,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
|
||||
/// of a simple-declaration. If we find that we are, we also parse the
|
||||
/// for-range-initializer, and place it here.
|
||||
Parser::DeclGroupPtrTy
|
||||
Parser::ParseSimpleDeclaration(unsigned Context,
|
||||
Parser::ParseSimpleDeclaration(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
ParsedAttributesWithRange &Attrs,
|
||||
bool RequireSemi, ForRangeInit *FRI) {
|
||||
@ -1753,7 +1753,7 @@ Parser::ParseSimpleDeclaration(unsigned Context,
|
||||
|
||||
/// Returns true if this might be the start of a declarator, or a common typo
|
||||
/// for a declarator.
|
||||
bool Parser::MightBeDeclarator(unsigned Context) {
|
||||
bool Parser::MightBeDeclarator(DeclaratorContext Context) {
|
||||
switch (Tok.getKind()) {
|
||||
case tok::annot_cxxscope:
|
||||
case tok::annot_template_id:
|
||||
@ -1772,11 +1772,12 @@ bool Parser::MightBeDeclarator(unsigned Context) {
|
||||
return getLangOpts().CPlusPlus;
|
||||
|
||||
case tok::l_square: // Might be an attribute on an unnamed bit-field.
|
||||
return Context == Declarator::MemberContext && getLangOpts().CPlusPlus11 &&
|
||||
NextToken().is(tok::l_square);
|
||||
return Context == DeclaratorContext::MemberContext &&
|
||||
getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square);
|
||||
|
||||
case tok::colon: // Might be a typo for '::' or an unnamed bit-field.
|
||||
return Context == Declarator::MemberContext || getLangOpts().CPlusPlus;
|
||||
return Context == DeclaratorContext::MemberContext ||
|
||||
getLangOpts().CPlusPlus;
|
||||
|
||||
case tok::identifier:
|
||||
switch (NextToken().getKind()) {
|
||||
@ -1802,8 +1803,9 @@ bool Parser::MightBeDeclarator(unsigned Context) {
|
||||
// At namespace scope, 'identifier:' is probably a typo for 'identifier::'
|
||||
// and in block scope it's probably a label. Inside a class definition,
|
||||
// this is a bit-field.
|
||||
return Context == Declarator::MemberContext ||
|
||||
(getLangOpts().CPlusPlus && Context == Declarator::FileContext);
|
||||
return Context == DeclaratorContext::MemberContext ||
|
||||
(getLangOpts().CPlusPlus &&
|
||||
Context == DeclaratorContext::FileContext);
|
||||
|
||||
case tok::identifier: // Possible virt-specifier.
|
||||
return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken());
|
||||
@ -1902,11 +1904,11 @@ void Parser::SkipMalformedDecl() {
|
||||
/// definition or a group of object declarations, actually parse the
|
||||
/// result.
|
||||
Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
|
||||
unsigned Context,
|
||||
DeclaratorContext Context,
|
||||
SourceLocation *DeclEnd,
|
||||
ForRangeInit *FRI) {
|
||||
// Parse the first declarator.
|
||||
ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
|
||||
ParsingDeclarator D(*this, DS, Context);
|
||||
ParseDeclarator(D);
|
||||
|
||||
// Bail out if the first declarator didn't seem well-formed.
|
||||
@ -1953,7 +1955,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
|
||||
// Function definitions are only allowed at file scope and in C++ classes.
|
||||
// The C++ inline method definition case is handled elsewhere, so we only
|
||||
// need to handle the file scope definition case.
|
||||
if (Context == Declarator::FileContext) {
|
||||
if (Context == DeclaratorContext::FileContext) {
|
||||
if (isStartOfFunctionDefinition(D)) {
|
||||
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
|
||||
Diag(Tok, diag::err_function_declared_typedef);
|
||||
@ -2024,7 +2026,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
|
||||
if (FirstDecl)
|
||||
DeclsInGroup.push_back(FirstDecl);
|
||||
|
||||
bool ExpectSemi = Context != Declarator::ForContext;
|
||||
bool ExpectSemi = Context != DeclaratorContext::ForContext;
|
||||
|
||||
// If we don't have a comma, it is either the end of the list (a ';') or an
|
||||
// error, bail out.
|
||||
@ -2070,7 +2072,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
|
||||
*DeclEnd = Tok.getLocation();
|
||||
|
||||
if (ExpectSemi &&
|
||||
ExpectAndConsumeSemi(Context == Declarator::FileContext
|
||||
ExpectAndConsumeSemi(Context == DeclaratorContext::FileContext
|
||||
? diag::err_invalid_token_after_toplevel_declarator
|
||||
: diag::err_expected_semi_declaration)) {
|
||||
// Okay, there was no semicolon and one was expected. If we see a
|
||||
@ -2199,7 +2201,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
|
||||
// FIXME: This check should be for a variable template instantiation only.
|
||||
|
||||
// Check that this is a valid instantiation
|
||||
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
|
||||
if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
|
||||
// If the declarator-id is not a template-id, issue a diagnostic and
|
||||
// recover by ignoring the 'template' keyword.
|
||||
Diag(Tok, diag::err_template_defn_explicit_instantiation)
|
||||
@ -2273,8 +2275,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
|
||||
if (Init.isInvalid()) {
|
||||
SmallVector<tok::TokenKind, 2> StopTokens;
|
||||
StopTokens.push_back(tok::comma);
|
||||
if (D.getContext() == Declarator::ForContext ||
|
||||
D.getContext() == Declarator::InitStmtContext)
|
||||
if (D.getContext() == DeclaratorContext::ForContext ||
|
||||
D.getContext() == DeclaratorContext::InitStmtContext)
|
||||
StopTokens.push_back(tok::r_paren);
|
||||
SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);
|
||||
Actions.ActOnInitializerError(ThisDecl);
|
||||
@ -2397,7 +2399,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
|
||||
}
|
||||
|
||||
// Issue diagnostic and remove constexpr specfier if present.
|
||||
if (DS.isConstexprSpecified() && DSC != DSC_condition) {
|
||||
if (DS.isConstexprSpecified() && DSC != DeclSpecContext::DSC_condition) {
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr);
|
||||
DS.ClearConstexprSpec();
|
||||
}
|
||||
@ -2486,7 +2488,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
|
||||
// classes.
|
||||
if (ParsedType T = Actions.ActOnMSVCUnknownTypeName(
|
||||
*Tok.getIdentifierInfo(), Tok.getLocation(),
|
||||
DSC == DSC_template_type_arg)) {
|
||||
DSC == DeclSpecContext::DSC_template_type_arg)) {
|
||||
const char *PrevSpec;
|
||||
unsigned DiagID;
|
||||
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
|
||||
@ -2540,18 +2542,20 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
|
||||
|
||||
// Parse this as a tag as if the missing tag were present.
|
||||
if (TagKind == tok::kw_enum)
|
||||
ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSC_normal);
|
||||
ParseEnumSpecifier(Loc, DS, TemplateInfo, AS,
|
||||
DeclSpecContext::DSC_normal);
|
||||
else
|
||||
ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS,
|
||||
/*EnteringContext*/ false, DSC_normal, Attrs);
|
||||
/*EnteringContext*/ false,
|
||||
DeclSpecContext::DSC_normal, Attrs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine whether this identifier could plausibly be the name of something
|
||||
// being declared (with a missing type).
|
||||
if (!isTypeSpecifier(DSC) &&
|
||||
(!SS || DSC == DSC_top_level || DSC == DSC_class)) {
|
||||
if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level ||
|
||||
DSC == DeclSpecContext::DSC_class)) {
|
||||
// Look ahead to the next token to try to figure out what this declaration
|
||||
// was supposed to be.
|
||||
switch (NextToken().getKind()) {
|
||||
@ -2575,7 +2579,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
|
||||
|
||||
// If we're in a context where we could be declaring a constructor,
|
||||
// check whether this is a constructor declaration with a bogus name.
|
||||
if (DSC == DSC_class || (DSC == DSC_top_level && SS)) {
|
||||
if (DSC == DeclSpecContext::DSC_class ||
|
||||
(DSC == DeclSpecContext::DSC_top_level && SS)) {
|
||||
IdentifierInfo *II = Tok.getIdentifierInfo();
|
||||
if (Actions.isCurrentClassNameTypo(II, SS)) {
|
||||
Diag(Loc, diag::err_constructor_bad_name)
|
||||
@ -2655,23 +2660,23 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
|
||||
/// context.
|
||||
///
|
||||
/// \param Context the declarator context, which is one of the
|
||||
/// Declarator::TheContext enumerator values.
|
||||
/// DeclaratorContext enumerator values.
|
||||
Parser::DeclSpecContext
|
||||
Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
|
||||
if (Context == Declarator::MemberContext)
|
||||
return DSC_class;
|
||||
if (Context == Declarator::FileContext)
|
||||
return DSC_top_level;
|
||||
if (Context == Declarator::TemplateParamContext)
|
||||
return DSC_template_param;
|
||||
if (Context == Declarator::TemplateTypeArgContext)
|
||||
return DSC_template_type_arg;
|
||||
if (Context == Declarator::TrailingReturnContext)
|
||||
return DSC_trailing;
|
||||
if (Context == Declarator::AliasDeclContext ||
|
||||
Context == Declarator::AliasTemplateContext)
|
||||
return DSC_alias_declaration;
|
||||
return DSC_normal;
|
||||
Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
|
||||
if (Context == DeclaratorContext::MemberContext)
|
||||
return DeclSpecContext::DSC_class;
|
||||
if (Context == DeclaratorContext::FileContext)
|
||||
return DeclSpecContext::DSC_top_level;
|
||||
if (Context == DeclaratorContext::TemplateParamContext)
|
||||
return DeclSpecContext::DSC_template_param;
|
||||
if (Context == DeclaratorContext::TemplateTypeArgContext)
|
||||
return DeclSpecContext::DSC_template_type_arg;
|
||||
if (Context == DeclaratorContext::TrailingReturnContext)
|
||||
return DeclSpecContext::DSC_trailing;
|
||||
if (Context == DeclaratorContext::AliasDeclContext ||
|
||||
Context == DeclaratorContext::AliasTemplateContext)
|
||||
return DeclSpecContext::DSC_alias_declaration;
|
||||
return DeclSpecContext::DSC_normal;
|
||||
}
|
||||
|
||||
/// ParseAlignArgument - Parse the argument to an alignment-specifier.
|
||||
@ -2751,7 +2756,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
|
||||
LateParsedAttrList *LateAttrs) {
|
||||
assert(DS.hasTagDefinition() && "shouldn't call this");
|
||||
|
||||
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
|
||||
bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
|
||||
DSContext == DeclSpecContext::DSC_top_level);
|
||||
|
||||
if (getLangOpts().CPlusPlus &&
|
||||
Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
|
||||
@ -2885,7 +2891,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
DS.SetRangeEnd(SourceLocation());
|
||||
}
|
||||
|
||||
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
|
||||
bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
|
||||
DSContext == DeclSpecContext::DSC_top_level);
|
||||
bool AttrsLastTime = false;
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
// We use Sema's policy to get bool macros right.
|
||||
@ -2955,8 +2962,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
Scope::FunctionPrototypeScope |
|
||||
Scope::AtCatchScope)) == 0;
|
||||
bool AllowNestedNameSpecifiers
|
||||
= DSContext == DSC_top_level ||
|
||||
(DSContext == DSC_class && DS.isFriendSpecified());
|
||||
= DSContext == DeclSpecContext::DSC_top_level ||
|
||||
(DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified());
|
||||
|
||||
Actions.CodeCompleteDeclSpec(getCurScope(), DS,
|
||||
AllowNonIdentifiers,
|
||||
@ -2967,9 +2974,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
|
||||
CCC = Sema::PCC_LocalDeclarationSpecifiers;
|
||||
else if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
|
||||
CCC = DSContext == DSC_class? Sema::PCC_MemberTemplate
|
||||
CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate
|
||||
: Sema::PCC_Template;
|
||||
else if (DSContext == DSC_class)
|
||||
else if (DSContext == DeclSpecContext::DSC_class)
|
||||
CCC = Sema::PCC_Class;
|
||||
else if (CurParsedObjCImpl)
|
||||
CCC = Sema::PCC_ObjCImplementation;
|
||||
@ -3013,7 +3020,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
// To improve diagnostics for this case, parse the declaration as a
|
||||
// constructor (and reject the extra template arguments later).
|
||||
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);
|
||||
if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
|
||||
if ((DSContext == DeclSpecContext::DSC_top_level ||
|
||||
DSContext == DeclSpecContext::DSC_class) &&
|
||||
TemplateId->Name &&
|
||||
Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) &&
|
||||
isConstructorDeclarator(/*Unqualified*/ false)) {
|
||||
@ -3055,7 +3063,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
// Check whether this is a constructor declaration. If we're in a
|
||||
// context where the identifier could be a class name, and it has the
|
||||
// shape of a constructor declaration, process it as one.
|
||||
if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
|
||||
if ((DSContext == DeclSpecContext::DSC_top_level ||
|
||||
DSContext == DeclSpecContext::DSC_class) &&
|
||||
Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
|
||||
&SS) &&
|
||||
isConstructorDeclarator(/*Unqualified*/ false))
|
||||
@ -3193,7 +3202,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
if (DS.isTypeAltiVecVector())
|
||||
goto DoneWithDeclSpec;
|
||||
|
||||
if (DSContext == DSC_objc_method_result && isObjCInstancetype()) {
|
||||
if (DSContext == DeclSpecContext::DSC_objc_method_result &&
|
||||
isObjCInstancetype()) {
|
||||
ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc);
|
||||
assert(TypeRep);
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
|
||||
@ -3227,7 +3237,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
|
||||
// If we're in a context where the identifier could be a class name,
|
||||
// check whether this is a constructor declaration.
|
||||
if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
|
||||
if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
|
||||
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
|
||||
isConstructorDeclarator(/*Unqualified*/true))
|
||||
goto DoneWithDeclSpec;
|
||||
@ -3235,7 +3245,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
// Likewise, if this is a context where the identifier could be a template
|
||||
// name, check whether this is a deduction guide declaration.
|
||||
if (getLangOpts().CPlusPlus17 &&
|
||||
(DSContext == DSC_class || DSContext == DSC_top_level) &&
|
||||
(DSContext == DeclSpecContext::DSC_class ||
|
||||
DSContext == DeclSpecContext::DSC_top_level) &&
|
||||
Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
|
||||
Tok.getLocation()) &&
|
||||
isConstructorDeclarator(/*Unqualified*/ true,
|
||||
@ -3281,7 +3292,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
// If we're in a context where the template-id could be a
|
||||
// constructor name or specialization, check whether this is a
|
||||
// constructor declaration.
|
||||
if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
|
||||
if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
|
||||
Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
|
||||
isConstructorDeclarator(TemplateId->SS.isEmpty()))
|
||||
goto DoneWithDeclSpec;
|
||||
@ -3451,7 +3462,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
|
||||
// friend
|
||||
case tok::kw_friend:
|
||||
if (DSContext == DSC_class)
|
||||
if (DSContext == DeclSpecContext::DSC_class)
|
||||
isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
|
||||
else {
|
||||
PrevSpec = ""; // not actually used by the diagnostic
|
||||
@ -4070,7 +4081,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
||||
SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
|
||||
|
||||
// Enum definitions should not be parsed in a trailing-return-type.
|
||||
bool AllowDeclaration = DSC != DSC_trailing;
|
||||
bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing;
|
||||
|
||||
bool AllowFixedUnderlyingType = AllowDeclaration &&
|
||||
(getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt ||
|
||||
@ -4296,14 +4307,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
||||
bool IsDependent = false;
|
||||
const char *PrevSpec = nullptr;
|
||||
unsigned DiagID;
|
||||
Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
|
||||
StartLoc, SS, Name, NameLoc, attrs.getList(),
|
||||
AS, DS.getModulePrivateSpecLoc(), TParams,
|
||||
Owned, IsDependent, ScopedEnumKWLoc,
|
||||
IsScopedUsingClassTag, BaseType,
|
||||
DSC == DSC_type_specifier,
|
||||
DSC == DSC_template_param ||
|
||||
DSC == DSC_template_type_arg, &SkipBody);
|
||||
Decl *TagDecl = Actions.ActOnTag(
|
||||
getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc,
|
||||
attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned,
|
||||
IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType,
|
||||
DSC == DeclSpecContext::DSC_type_specifier,
|
||||
DSC == DeclSpecContext::DSC_template_param ||
|
||||
DSC == DeclSpecContext::DSC_template_type_arg,
|
||||
&SkipBody);
|
||||
|
||||
if (SkipBody.ShouldSkip) {
|
||||
assert(TUK == Sema::TUK_Definition && "can only skip a definition");
|
||||
@ -5175,7 +5186,7 @@ void Parser::ParseDeclarator(Declarator &D) {
|
||||
}
|
||||
|
||||
static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
|
||||
unsigned TheContext) {
|
||||
DeclaratorContext TheContext) {
|
||||
if (Kind == tok::star || Kind == tok::caret)
|
||||
return true;
|
||||
|
||||
@ -5194,8 +5205,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
|
||||
// (The same thing can in theory happen after a trailing-return-type, but
|
||||
// since those are a C++11 feature, there is no rejects-valid issue there.)
|
||||
if (Kind == tok::ampamp)
|
||||
return Lang.CPlusPlus11 || (TheContext != Declarator::ConversionIdContext &&
|
||||
TheContext != Declarator::CXXNewContext);
|
||||
return Lang.CPlusPlus11 ||
|
||||
(TheContext != DeclaratorContext::ConversionIdContext &&
|
||||
TheContext != DeclaratorContext::CXXNewContext);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -5249,8 +5261,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
|
||||
(Tok.is(tok::identifier) &&
|
||||
(NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
|
||||
Tok.is(tok::annot_cxxscope))) {
|
||||
bool EnteringContext = D.getContext() == Declarator::FileContext ||
|
||||
D.getContext() == Declarator::MemberContext;
|
||||
bool EnteringContext =
|
||||
D.getContext() == DeclaratorContext::FileContext ||
|
||||
D.getContext() == DeclaratorContext::MemberContext;
|
||||
CXXScopeSpec SS;
|
||||
ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext);
|
||||
|
||||
@ -5316,7 +5329,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
|
||||
// GNU attributes are not allowed here in a new-type-id, but Declspec and
|
||||
// C++11 attributes are allowed.
|
||||
unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed |
|
||||
((D.getContext() != Declarator::CXXNewContext)
|
||||
((D.getContext() != DeclaratorContext::CXXNewContext)
|
||||
? AR_GNUAttributesParsed
|
||||
: AR_GNUAttributesParsedAndRejected);
|
||||
ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier());
|
||||
@ -5470,15 +5483,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||
// Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in
|
||||
// this context it is a bitfield. Also in range-based for statement colon
|
||||
// may delimit for-range-declaration.
|
||||
ColonProtectionRAIIObject X(*this,
|
||||
D.getContext() == Declarator::MemberContext ||
|
||||
(D.getContext() == Declarator::ForContext &&
|
||||
ColonProtectionRAIIObject X(
|
||||
*this, D.getContext() == DeclaratorContext::MemberContext ||
|
||||
(D.getContext() == DeclaratorContext::ForContext &&
|
||||
getLangOpts().CPlusPlus11));
|
||||
|
||||
// ParseDeclaratorInternal might already have parsed the scope.
|
||||
if (D.getCXXScopeSpec().isEmpty()) {
|
||||
bool EnteringContext = D.getContext() == Declarator::FileContext ||
|
||||
D.getContext() == Declarator::MemberContext;
|
||||
bool EnteringContext =
|
||||
D.getContext() == DeclaratorContext::FileContext ||
|
||||
D.getContext() == DeclaratorContext::MemberContext;
|
||||
ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), nullptr,
|
||||
EnteringContext);
|
||||
}
|
||||
@ -5507,9 +5521,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||
// been expanded or contains auto; otherwise, it is parsed as part of the
|
||||
// parameter-declaration-clause.
|
||||
if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
|
||||
!((D.getContext() == Declarator::PrototypeContext ||
|
||||
D.getContext() == Declarator::LambdaExprParameterContext ||
|
||||
D.getContext() == Declarator::BlockLiteralContext) &&
|
||||
!((D.getContext() == DeclaratorContext::PrototypeContext ||
|
||||
D.getContext() == DeclaratorContext::LambdaExprParameterContext ||
|
||||
D.getContext() == DeclaratorContext::BlockLiteralContext) &&
|
||||
NextToken().is(tok::r_paren) &&
|
||||
!D.hasGroupingParens() &&
|
||||
!Actions.containsUnexpandedParameterPacks(D) &&
|
||||
@ -5541,14 +5555,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||
AllowDeductionGuide = false;
|
||||
} else if (D.getCXXScopeSpec().isSet()) {
|
||||
AllowConstructorName =
|
||||
(D.getContext() == Declarator::FileContext ||
|
||||
D.getContext() == Declarator::MemberContext);
|
||||
(D.getContext() == DeclaratorContext::FileContext ||
|
||||
D.getContext() == DeclaratorContext::MemberContext);
|
||||
AllowDeductionGuide = false;
|
||||
} else {
|
||||
AllowConstructorName = (D.getContext() == Declarator::MemberContext);
|
||||
AllowConstructorName =
|
||||
(D.getContext() == DeclaratorContext::MemberContext);
|
||||
AllowDeductionGuide =
|
||||
(D.getContext() == Declarator::FileContext ||
|
||||
D.getContext() == Declarator::MemberContext);
|
||||
(D.getContext() == DeclaratorContext::FileContext ||
|
||||
D.getContext() == DeclaratorContext::MemberContext);
|
||||
}
|
||||
|
||||
SourceLocation TemplateKWLoc;
|
||||
@ -5604,15 +5619,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||
// An identifier within parens is unlikely to be intended to be anything
|
||||
// other than a name being "declared".
|
||||
DiagnoseIdentifier = true;
|
||||
else if (D.getContext() == Declarator::TemplateTypeArgContext)
|
||||
else if (D.getContext() == DeclaratorContext::TemplateTypeArgContext)
|
||||
// T<int N> is an accidental identifier; T<int N indicates a missing '>'.
|
||||
DiagnoseIdentifier =
|
||||
NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater);
|
||||
else if (D.getContext() == Declarator::AliasDeclContext ||
|
||||
D.getContext() == Declarator::AliasTemplateContext)
|
||||
else if (D.getContext() == DeclaratorContext::AliasDeclContext ||
|
||||
D.getContext() == DeclaratorContext::AliasTemplateContext)
|
||||
// The most likely error is that the ';' was forgotten.
|
||||
DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
|
||||
else if (D.getContext() == Declarator::TrailingReturnContext &&
|
||||
else if (D.getContext() == DeclaratorContext::TrailingReturnContext &&
|
||||
!isCXX11VirtSpecifier(Tok))
|
||||
DiagnoseIdentifier = NextToken().isOneOf(
|
||||
tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
|
||||
@ -5659,7 +5674,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||
LLVM_BUILTIN_TRAP;
|
||||
if (Tok.is(tok::l_square))
|
||||
return ParseMisplacedBracketDeclarator(D);
|
||||
if (D.getContext() == Declarator::MemberContext) {
|
||||
if (D.getContext() == DeclaratorContext::MemberContext) {
|
||||
// Objective-C++: Detect C++ keywords and try to prevent further errors by
|
||||
// treating these keyword as valid member names.
|
||||
if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus &&
|
||||
@ -6042,9 +6057,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
|
||||
bool IsCXX11MemberFunction =
|
||||
getLangOpts().CPlusPlus11 &&
|
||||
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
|
||||
(D.getContext() == Declarator::MemberContext
|
||||
(D.getContext() == DeclaratorContext::MemberContext
|
||||
? !D.getDeclSpec().isFriendSpecified()
|
||||
: D.getContext() == Declarator::FileContext &&
|
||||
: D.getContext() == DeclaratorContext::FileContext &&
|
||||
D.getCXXScopeSpec().isValid() &&
|
||||
Actions.CurContext->isRecord());
|
||||
Sema::CXXThisScopeRAII ThisScope(Actions,
|
||||
@ -6309,10 +6324,10 @@ void Parser::ParseParameterDeclarationClause(
|
||||
// Parse the declarator. This is "PrototypeContext" or
|
||||
// "LambdaExprParameterContext", because we must accept either
|
||||
// 'declarator' or 'abstract-declarator' here.
|
||||
Declarator ParmDeclarator(DS,
|
||||
D.getContext() == Declarator::LambdaExprContext ?
|
||||
Declarator::LambdaExprParameterContext :
|
||||
Declarator::PrototypeContext);
|
||||
Declarator ParmDeclarator(
|
||||
DS, D.getContext() == DeclaratorContext::LambdaExprContext
|
||||
? DeclaratorContext::LambdaExprParameterContext
|
||||
: DeclaratorContext::PrototypeContext);
|
||||
ParseDeclarator(ParmDeclarator);
|
||||
|
||||
// Parse GNU attributes, if present.
|
||||
@ -6355,7 +6370,7 @@ void Parser::ParseParameterDeclarationClause(
|
||||
SourceLocation EqualLoc = Tok.getLocation();
|
||||
|
||||
// Parse the default argument
|
||||
if (D.getContext() == Declarator::MemberContext) {
|
||||
if (D.getContext() == DeclaratorContext::MemberContext) {
|
||||
// If we're inside a class definition, cache the tokens
|
||||
// corresponding to the default argument. We'll actually parse
|
||||
// them when we see the end of the class definition.
|
||||
|
@ -55,7 +55,7 @@ using namespace clang;
|
||||
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
|
||||
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
|
||||
///
|
||||
Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context,
|
||||
Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
SourceLocation InlineLoc) {
|
||||
assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
|
||||
@ -307,7 +307,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
|
||||
/// 'extern' string-literal '{' declaration-seq[opt] '}'
|
||||
/// 'extern' string-literal declaration
|
||||
///
|
||||
Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
|
||||
Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
|
||||
assert(isTokenStringLiteral() && "Not a string literal!");
|
||||
ExprResult Lang = ParseStringLiteralExpression(false);
|
||||
|
||||
@ -434,7 +434,7 @@ Decl *Parser::ParseExportDeclaration() {
|
||||
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
|
||||
/// using-directive. Assumes that current token is 'using'.
|
||||
Parser::DeclGroupPtrTy
|
||||
Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
|
||||
Parser::ParseUsingDirectiveOrDeclaration(DeclaratorContext Context,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
SourceLocation &DeclEnd,
|
||||
ParsedAttributesWithRange &attrs) {
|
||||
@ -482,7 +482,7 @@ Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
|
||||
/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
|
||||
/// namespace-name attributes[opt] ;
|
||||
///
|
||||
Decl *Parser::ParseUsingDirective(unsigned Context,
|
||||
Decl *Parser::ParseUsingDirective(DeclaratorContext Context,
|
||||
SourceLocation UsingLoc,
|
||||
SourceLocation &DeclEnd,
|
||||
ParsedAttributes &attrs) {
|
||||
@ -551,7 +551,8 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
|
||||
/// using-declarator:
|
||||
/// 'typename'[opt] nested-name-specifier unqualified-id
|
||||
///
|
||||
bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
|
||||
bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
|
||||
UsingDeclarator &D) {
|
||||
D.clear();
|
||||
|
||||
// Ignore optional 'typename'.
|
||||
@ -582,7 +583,8 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
|
||||
// or the simple-template-id's template-name in the last component of the
|
||||
// nested-name-specifier, the name is [...] considered to name the
|
||||
// constructor.
|
||||
if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext &&
|
||||
if (getLangOpts().CPlusPlus11 &&
|
||||
Context == DeclaratorContext::MemberContext &&
|
||||
Tok.is(tok::identifier) &&
|
||||
(NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
|
||||
NextToken().is(tok::ellipsis)) &&
|
||||
@ -629,7 +631,7 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
|
||||
/// 'using' identifier attribute-specifier-seq[opt] = type-id ;
|
||||
///
|
||||
Parser::DeclGroupPtrTy
|
||||
Parser::ParseUsingDeclaration(unsigned Context,
|
||||
Parser::ParseUsingDeclaration(DeclaratorContext Context,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
SourceLocation UsingLoc, SourceLocation &DeclEnd,
|
||||
AccessSpecifier AS) {
|
||||
@ -699,7 +701,7 @@ Parser::ParseUsingDeclaration(unsigned Context,
|
||||
// "typename" keyword is allowed for identifiers only,
|
||||
// because it may be a type definition.
|
||||
if (D.TypenameLoc.isValid() &&
|
||||
D.Name.getKind() != UnqualifiedId::IK_Identifier) {
|
||||
D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {
|
||||
Diag(D.Name.getSourceRange().getBegin(),
|
||||
diag::err_typename_identifiers_only)
|
||||
<< FixItHint::CreateRemoval(SourceRange(D.TypenameLoc));
|
||||
@ -753,7 +755,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
|
||||
// Type alias templates cannot be specialized.
|
||||
int SpecKind = -1;
|
||||
if (TemplateInfo.Kind == ParsedTemplateInfo::Template &&
|
||||
D.Name.getKind() == UnqualifiedId::IK_TemplateId)
|
||||
D.Name.getKind() == UnqualifiedIdKind::IK_TemplateId)
|
||||
SpecKind = 0;
|
||||
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization)
|
||||
SpecKind = 1;
|
||||
@ -773,7 +775,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
|
||||
}
|
||||
|
||||
// Name must be an identifier.
|
||||
if (D.Name.getKind() != UnqualifiedId::IK_Identifier) {
|
||||
if (D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {
|
||||
Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier);
|
||||
// No removal fixit: can't recover from this.
|
||||
SkipUntil(tok::semi);
|
||||
@ -791,10 +793,10 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
|
||||
<< FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc));
|
||||
|
||||
Decl *DeclFromDeclSpec = nullptr;
|
||||
TypeResult TypeAlias =
|
||||
ParseTypeName(nullptr,
|
||||
TemplateInfo.Kind ? Declarator::AliasTemplateContext
|
||||
: Declarator::AliasDeclContext,
|
||||
TypeResult TypeAlias = ParseTypeName(
|
||||
nullptr,
|
||||
TemplateInfo.Kind ? DeclaratorContext::AliasTemplateContext
|
||||
: DeclaratorContext::AliasDeclContext,
|
||||
AS, &DeclFromDeclSpec, &Attrs);
|
||||
if (OwnedType)
|
||||
*OwnedType = DeclFromDeclSpec;
|
||||
@ -1094,7 +1096,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
|
||||
|
||||
EndLocation = ParseDecltypeSpecifier(DS);
|
||||
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
|
||||
}
|
||||
|
||||
@ -1195,7 +1197,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
|
||||
DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,
|
||||
Actions.getASTContext().getPrintingPolicy());
|
||||
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
|
||||
}
|
||||
|
||||
@ -1612,14 +1614,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||
// new struct s;
|
||||
// or
|
||||
// &T::operator struct s;
|
||||
// For these, DSC is DSC_type_specifier or DSC_alias_declaration.
|
||||
// For these, DSC is DeclSpecContext::DSC_type_specifier or
|
||||
// DeclSpecContext::DSC_alias_declaration.
|
||||
|
||||
// If there are attributes after class name, parse them.
|
||||
MaybeParseCXX11Attributes(Attributes);
|
||||
|
||||
const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
|
||||
Sema::TagUseKind TUK;
|
||||
if (DSC == DSC_trailing)
|
||||
if (DSC == DeclSpecContext::DSC_trailing)
|
||||
TUK = Sema::TUK_Reference;
|
||||
else if (Tok.is(tok::l_brace) ||
|
||||
(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
|
||||
@ -1881,15 +1884,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||
stripTypeAttributesOffDeclSpec(attrs, DS, TUK);
|
||||
|
||||
// Declaration or definition of a class type
|
||||
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
|
||||
SS, Name, NameLoc, attrs.getList(), AS,
|
||||
DS.getModulePrivateSpecLoc(),
|
||||
TParams, Owned, IsDependent,
|
||||
SourceLocation(), false,
|
||||
clang::TypeResult(),
|
||||
DSC == DSC_type_specifier,
|
||||
DSC == DSC_template_param ||
|
||||
DSC == DSC_template_type_arg, &SkipBody);
|
||||
TagOrTempResult = Actions.ActOnTag(
|
||||
getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc,
|
||||
attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned,
|
||||
IsDependent, SourceLocation(), false, clang::TypeResult(),
|
||||
DSC == DeclSpecContext::DSC_type_specifier,
|
||||
DSC == DeclSpecContext::DSC_template_param ||
|
||||
DSC == DeclSpecContext::DSC_template_type_arg,
|
||||
&SkipBody);
|
||||
|
||||
// If ActOnTag said the type was dependent, try again with the
|
||||
// less common call.
|
||||
@ -2509,7 +2511,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
SourceLocation DeclEnd;
|
||||
return DeclGroupPtrTy::make(
|
||||
DeclGroupRef(ParseTemplateDeclarationOrSpecialization(
|
||||
Declarator::MemberContext, DeclEnd, AS, AccessAttrs)));
|
||||
DeclaratorContext::MemberContext, DeclEnd, AS, AccessAttrs)));
|
||||
}
|
||||
|
||||
// Handle: member-declaration ::= '__extension__' member-declaration
|
||||
@ -2545,7 +2547,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
}
|
||||
SourceLocation DeclEnd;
|
||||
// Otherwise, it must be a using-declaration or an alias-declaration.
|
||||
return ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
|
||||
return ParseUsingDeclaration(DeclaratorContext::MemberContext, TemplateInfo,
|
||||
UsingLoc, DeclEnd, AS);
|
||||
}
|
||||
|
||||
@ -2559,7 +2561,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
if (MalformedTypeSpec)
|
||||
DS.SetTypeSpecError();
|
||||
|
||||
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
|
||||
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class,
|
||||
&CommonLateParsedAttrs);
|
||||
|
||||
// Turn off colon protection that was set for declspec.
|
||||
@ -2569,7 +2571,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
// may get this far before the problem becomes obvious.
|
||||
if (DS.hasTagDefinition() &&
|
||||
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate &&
|
||||
DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class,
|
||||
DiagnoseMissingSemiAfterTagDefinition(DS, AS, DeclSpecContext::DSC_class,
|
||||
&CommonLateParsedAttrs))
|
||||
return nullptr;
|
||||
|
||||
@ -2593,7 +2595,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
return Actions.ConvertDeclToDeclGroup(TheDecl);
|
||||
}
|
||||
|
||||
ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
|
||||
ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::MemberContext);
|
||||
VirtSpecifiers VS;
|
||||
|
||||
// Hold late-parsed attributes so we can attach a Decl to them later.
|
||||
@ -2852,7 +2854,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
break;
|
||||
|
||||
if (Tok.isAtStartOfLine() &&
|
||||
!MightBeDeclarator(Declarator::MemberContext)) {
|
||||
!MightBeDeclarator(DeclaratorContext::MemberContext)) {
|
||||
// This comma was followed by a line-break and something which can't be
|
||||
// the start of a declarator. The comma was probably a typo for a
|
||||
// semicolon.
|
||||
@ -3709,7 +3711,7 @@ TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) {
|
||||
|
||||
ConsumeToken();
|
||||
|
||||
return ParseTypeName(&Range, Declarator::TrailingReturnContext);
|
||||
return ParseTypeName(&Range, DeclaratorContext::TrailingReturnContext);
|
||||
}
|
||||
|
||||
/// \brief We have just started parsing the definition of a new class,
|
||||
|
@ -1000,7 +1000,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
||||
DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
|
||||
Actions.getASTContext().getPrintingPolicy());
|
||||
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
|
||||
DeclaratorInfo);
|
||||
if (Ty.isInvalid())
|
||||
@ -1209,7 +1209,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
||||
PrevSpec, DiagID, Type,
|
||||
Actions.getASTContext().getPrintingPolicy());
|
||||
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
|
||||
if (Ty.isInvalid())
|
||||
break;
|
||||
@ -1824,7 +1824,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
|
||||
if (isTypeIdUnambiguously()) {
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseSpecifierQualifierList(DS);
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation());
|
||||
@ -2381,7 +2381,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
|
||||
// Parse the type declarator.
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseSpecifierQualifierList(DS);
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
// If our type is followed by an identifier and either ':' or ']', then
|
||||
@ -2858,7 +2858,7 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) {
|
||||
ParseSpecifierQualifierList(DS);
|
||||
|
||||
// Parse the block-declarator.
|
||||
Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::BlockLiteralContext);
|
||||
DeclaratorInfo.setFunctionDefinitionKind(FDK_Definition);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
@ -2897,7 +2897,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
|
||||
|
||||
// Parse the return type if present.
|
||||
DeclSpec DS(AttrFactory);
|
||||
Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
|
||||
Declarator ParamInfo(DS, DeclaratorContext::BlockLiteralContext);
|
||||
ParamInfo.setFunctionDefinitionKind(FDK_Definition);
|
||||
// FIXME: Since the return type isn't actually parsed, it can't be used to
|
||||
// fill ParamInfo with an initial valid range, so do it manually.
|
||||
|
@ -292,8 +292,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||
break;
|
||||
}
|
||||
|
||||
if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
|
||||
TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
|
||||
if (TemplateName.getKind() != UnqualifiedIdKind::IK_OperatorFunctionId &&
|
||||
TemplateName.getKind() != UnqualifiedIdKind::IK_LiteralOperatorId) {
|
||||
Diag(TemplateName.getSourceRange().getBegin(),
|
||||
diag::err_id_after_template_in_nested_name_spec)
|
||||
<< TemplateName.getSourceRange();
|
||||
@ -1090,7 +1090,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
||||
|
||||
// Parse lambda-declarator[opt].
|
||||
DeclSpec DS(AttrFactory);
|
||||
Declarator D(DS, Declarator::LambdaExprContext);
|
||||
Declarator D(DS, DeclaratorContext::LambdaExprContext);
|
||||
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
|
||||
Actions.PushLambdaScope();
|
||||
|
||||
@ -1353,7 +1353,7 @@ ExprResult Parser::ParseCXXCasts() {
|
||||
ParseSpecifierQualifierList(DS);
|
||||
|
||||
// Parse the abstract-declarator, if present.
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
SourceLocation RAngleBracketLoc = Tok.getLocation();
|
||||
@ -1660,7 +1660,7 @@ ExprResult Parser::ParseCXXThis() {
|
||||
/// In C++1z onwards, the type specifier can also be a template-name.
|
||||
ExprResult
|
||||
Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
||||
Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::FunctionalCastContext);
|
||||
ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
|
||||
|
||||
assert((Tok.is(tok::l_paren) ||
|
||||
@ -1767,8 +1767,9 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
|
||||
: diag::ext_init_statement)
|
||||
<< (CK == Sema::ConditionKind::Switch);
|
||||
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
|
||||
DeclGroupPtrTy DG = ParseSimpleDeclaration(
|
||||
Declarator::InitStmtContext, DeclEnd, attrs, /*RequireSemi=*/true);
|
||||
DeclGroupPtrTy DG =
|
||||
ParseSimpleDeclaration(DeclaratorContext::InitStmtContext, DeclEnd,
|
||||
attrs, /*RequireSemi=*/true);
|
||||
*InitStmt = Actions.ActOnDeclStmt(DG, DeclStart, DeclEnd);
|
||||
return ParseCXXCondition(nullptr, Loc, CK);
|
||||
}
|
||||
@ -1781,10 +1782,10 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
|
||||
// type-specifier-seq
|
||||
DeclSpec DS(AttrFactory);
|
||||
DS.takeAttributesFrom(attrs);
|
||||
ParseSpecifierQualifierList(DS, AS_none, DSC_condition);
|
||||
ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_condition);
|
||||
|
||||
// declarator
|
||||
Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::ConditionContext);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
// simple-asm-expr[opt]
|
||||
@ -1982,7 +1983,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
|
||||
/// type-specifier type-specifier-seq[opt]
|
||||
///
|
||||
bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
|
||||
ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier);
|
||||
ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_type_specifier);
|
||||
DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
|
||||
return false;
|
||||
}
|
||||
@ -2033,9 +2034,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
||||
TemplateTy Template;
|
||||
TemplateNameKind TNK = TNK_Non_template;
|
||||
switch (Id.getKind()) {
|
||||
case UnqualifiedId::IK_Identifier:
|
||||
case UnqualifiedId::IK_OperatorFunctionId:
|
||||
case UnqualifiedId::IK_LiteralOperatorId:
|
||||
case UnqualifiedIdKind::IK_Identifier:
|
||||
case UnqualifiedIdKind::IK_OperatorFunctionId:
|
||||
case UnqualifiedIdKind::IK_LiteralOperatorId:
|
||||
if (AssumeTemplateId) {
|
||||
// We defer the injected-class-name checks until we've found whether
|
||||
// this template-id is used to form a nested-name-specifier or not.
|
||||
@ -2058,11 +2059,11 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
||||
// parse correctly as a template, so suggest the keyword 'template'
|
||||
// before 'getAs' and treat this as a dependent template name.
|
||||
std::string Name;
|
||||
if (Id.getKind() == UnqualifiedId::IK_Identifier)
|
||||
if (Id.getKind() == UnqualifiedIdKind::IK_Identifier)
|
||||
Name = Id.Identifier->getName();
|
||||
else {
|
||||
Name = "operator ";
|
||||
if (Id.getKind() == UnqualifiedId::IK_OperatorFunctionId)
|
||||
if (Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId)
|
||||
Name += getOperatorSpelling(Id.OperatorFunctionId.Operator);
|
||||
else
|
||||
Name += Id.Identifier->getName();
|
||||
@ -2079,7 +2080,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
||||
}
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_ConstructorName: {
|
||||
case UnqualifiedIdKind::IK_ConstructorName: {
|
||||
UnqualifiedId TemplateName;
|
||||
bool MemberOfUnknownSpecialization;
|
||||
TemplateName.setIdentifier(Name, NameLoc);
|
||||
@ -2090,7 +2091,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
||||
break;
|
||||
}
|
||||
|
||||
case UnqualifiedId::IK_DestructorName: {
|
||||
case UnqualifiedIdKind::IK_DestructorName: {
|
||||
UnqualifiedId TemplateName;
|
||||
bool MemberOfUnknownSpecialization;
|
||||
TemplateName.setIdentifier(Name, NameLoc);
|
||||
@ -2129,16 +2130,18 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
||||
true, LAngleLoc, TemplateArgs, RAngleLoc))
|
||||
return true;
|
||||
|
||||
if (Id.getKind() == UnqualifiedId::IK_Identifier ||
|
||||
Id.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
|
||||
Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
|
||||
if (Id.getKind() == UnqualifiedIdKind::IK_Identifier ||
|
||||
Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId ||
|
||||
Id.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) {
|
||||
// Form a parsed representation of the template-id to be stored in the
|
||||
// UnqualifiedId.
|
||||
|
||||
// FIXME: Store name for literal operator too.
|
||||
IdentifierInfo *TemplateII =
|
||||
Id.getKind() == UnqualifiedId::IK_Identifier ? Id.Identifier : nullptr;
|
||||
OverloadedOperatorKind OpKind = Id.getKind() == UnqualifiedId::IK_Identifier
|
||||
Id.getKind() == UnqualifiedIdKind::IK_Identifier ? Id.Identifier
|
||||
: nullptr;
|
||||
OverloadedOperatorKind OpKind =
|
||||
Id.getKind() == UnqualifiedIdKind::IK_Identifier
|
||||
? OO_None
|
||||
: Id.OperatorFunctionId.Operator;
|
||||
|
||||
@ -2162,7 +2165,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
||||
if (Type.isInvalid())
|
||||
return true;
|
||||
|
||||
if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
|
||||
if (Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
|
||||
Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
|
||||
else
|
||||
Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
|
||||
@ -2395,7 +2398,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
|
||||
|
||||
// Parse the conversion-declarator, which is merely a sequence of
|
||||
// ptr-operators.
|
||||
Declarator D(DS, Declarator::ConversionIdContext);
|
||||
Declarator D(DS, DeclaratorContext::ConversionIdContext);
|
||||
ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr);
|
||||
|
||||
// Finish up the type.
|
||||
@ -2556,8 +2559,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
||||
//
|
||||
// template-id:
|
||||
// operator-function-id < template-argument-list[opt] >
|
||||
if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
|
||||
Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
|
||||
if ((Result.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId ||
|
||||
Result.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) &&
|
||||
(TemplateSpecified || Tok.is(tok::less)))
|
||||
return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
|
||||
nullptr, SourceLocation(),
|
||||
@ -2696,7 +2699,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
|
||||
|
||||
SourceRange TypeIdParens;
|
||||
DeclSpec DS(AttrFactory);
|
||||
Declarator DeclaratorInfo(DS, Declarator::CXXNewContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::CXXNewContext);
|
||||
if (Tok.is(tok::l_paren)) {
|
||||
// If it turns out to be a placement, we change the type location.
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren);
|
||||
@ -3172,7 +3175,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
|
||||
if (ParseAs >= CompoundLiteral) {
|
||||
// Parse the type declarator.
|
||||
DeclSpec DS(AttrFactory);
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
{
|
||||
ColonProtectionRAIIObject InnerColonProtection(*this);
|
||||
ParseSpecifierQualifierList(DS);
|
||||
|
@ -1140,14 +1140,14 @@ bool Parser::isTokIdentifier_in() const {
|
||||
/// 'null_unspecified'
|
||||
///
|
||||
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
|
||||
Declarator::TheContext Context) {
|
||||
assert(Context == Declarator::ObjCParameterContext ||
|
||||
Context == Declarator::ObjCResultContext);
|
||||
DeclaratorContext Context) {
|
||||
assert(Context == DeclaratorContext::ObjCParameterContext ||
|
||||
Context == DeclaratorContext::ObjCResultContext);
|
||||
|
||||
while (1) {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
|
||||
Context == Declarator::ObjCParameterContext);
|
||||
Context == DeclaratorContext::ObjCParameterContext);
|
||||
return cutOffParsing();
|
||||
}
|
||||
|
||||
@ -1242,12 +1242,12 @@ static void takeDeclAttributes(ParsedAttributes &attrs,
|
||||
/// '(' objc-type-qualifiers[opt] ')'
|
||||
///
|
||||
ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
|
||||
Declarator::TheContext context,
|
||||
DeclaratorContext context,
|
||||
ParsedAttributes *paramAttrs) {
|
||||
assert(context == Declarator::ObjCParameterContext ||
|
||||
context == Declarator::ObjCResultContext);
|
||||
assert(context == DeclaratorContext::ObjCParameterContext ||
|
||||
context == DeclaratorContext::ObjCResultContext);
|
||||
assert((paramAttrs != nullptr) ==
|
||||
(context == Declarator::ObjCParameterContext));
|
||||
(context == DeclaratorContext::ObjCParameterContext));
|
||||
|
||||
assert(Tok.is(tok::l_paren) && "expected (");
|
||||
|
||||
@ -1265,9 +1265,9 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
|
||||
// Parse an abstract declarator.
|
||||
DeclSpec declSpec(AttrFactory);
|
||||
declSpec.setObjCQualifiers(&DS);
|
||||
DeclSpecContext dsContext = DSC_normal;
|
||||
if (context == Declarator::ObjCResultContext)
|
||||
dsContext = DSC_objc_method_result;
|
||||
DeclSpecContext dsContext = DeclSpecContext::DSC_normal;
|
||||
if (context == DeclaratorContext::ObjCResultContext)
|
||||
dsContext = DeclSpecContext::DSC_objc_method_result;
|
||||
ParseSpecifierQualifierList(declSpec, AS_none, dsContext);
|
||||
Declarator declarator(declSpec, context);
|
||||
ParseDeclarator(declarator);
|
||||
@ -1288,7 +1288,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
|
||||
|
||||
// If we're parsing a parameter, steal all the decl attributes
|
||||
// and add them to the decl spec.
|
||||
if (context == Declarator::ObjCParameterContext)
|
||||
if (context == DeclaratorContext::ObjCParameterContext)
|
||||
takeDeclAttributes(*paramAttrs, declarator);
|
||||
}
|
||||
}
|
||||
@ -1352,7 +1352,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
||||
ParsedType ReturnType;
|
||||
ObjCDeclSpec DSRet;
|
||||
if (Tok.is(tok::l_paren))
|
||||
ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext,
|
||||
ReturnType = ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResultContext,
|
||||
nullptr);
|
||||
|
||||
// If attributes exist before the method, parse them.
|
||||
@ -1416,7 +1416,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
||||
ArgInfo.Type = nullptr;
|
||||
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
|
||||
ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec,
|
||||
Declarator::ObjCParameterContext,
|
||||
DeclaratorContext::ObjCParameterContext,
|
||||
¶mAttrs);
|
||||
|
||||
// If attributes exist before the argument name, parse them.
|
||||
@ -1494,7 +1494,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
// Parse the declarator.
|
||||
Declarator ParmDecl(DS, Declarator::PrototypeContext);
|
||||
Declarator ParmDecl(DS, DeclaratorContext::PrototypeContext);
|
||||
ParseDeclarator(ParmDecl);
|
||||
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
|
||||
Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
|
||||
@ -1703,7 +1703,7 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers(
|
||||
typeArg, Actions.getASTContext().getPrintingPolicy());
|
||||
|
||||
// Form a declarator to turn this into a type.
|
||||
Declarator D(DS, Declarator::TypeNameContext);
|
||||
Declarator D(DS, DeclaratorContext::TypeNameContext);
|
||||
TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D);
|
||||
if (fullTypeArg.isUsable()) {
|
||||
typeArgs.push_back(fullTypeArg.get());
|
||||
@ -2543,7 +2543,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
||||
if (Tok.isNot(tok::ellipsis)) {
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
Declarator ParmDecl(DS, Declarator::ObjCCatchContext);
|
||||
Declarator ParmDecl(DS, DeclaratorContext::ObjCCatchContext);
|
||||
ParseDeclarator(ParmDecl);
|
||||
|
||||
// Inform the actions module about the declarator, so it
|
||||
@ -2945,7 +2945,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
|
||||
// We have a class message. Turn the simple-type-specifier or
|
||||
// typename-specifier we parsed into a type and parse the
|
||||
// remainder of the class message.
|
||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
|
||||
TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
|
||||
if (Type.isInvalid())
|
||||
return true;
|
||||
|
@ -250,7 +250,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
|
||||
do {
|
||||
ColonProtectionRAIIObject ColonRAII(*this);
|
||||
SourceRange Range;
|
||||
TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS);
|
||||
TypeResult TR =
|
||||
ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
|
||||
if (TR.isUsable()) {
|
||||
auto ReductionType =
|
||||
Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
|
||||
|
@ -211,7 +211,7 @@ Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
|
||||
Allowed == ACK_Any) &&
|
||||
isDeclarationStatement()) {
|
||||
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
|
||||
DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext,
|
||||
DeclGroupPtrTy Decl = ParseDeclaration(DeclaratorContext::BlockContext,
|
||||
DeclEnd, Attrs);
|
||||
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
|
||||
}
|
||||
@ -1021,8 +1021,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
||||
ExtensionRAIIObject O(Diags);
|
||||
|
||||
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
|
||||
DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
|
||||
attrs);
|
||||
DeclGroupPtrTy Res =
|
||||
ParseDeclaration(DeclaratorContext::BlockContext, DeclEnd, attrs);
|
||||
R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
|
||||
} else {
|
||||
// Otherwise this was a unary __extension__ marker.
|
||||
@ -1631,7 +1631,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
|
||||
|
||||
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
|
||||
DeclGroupPtrTy DG = ParseSimpleDeclaration(
|
||||
Declarator::ForContext, DeclEnd, attrs, false,
|
||||
DeclaratorContext::ForContext, DeclEnd, attrs, false,
|
||||
MightBeForRangeStmt ? &ForRangeInit : nullptr);
|
||||
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
|
||||
if (ForRangeInit.ParsedForRangeDecl()) {
|
||||
@ -2181,7 +2181,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
|
||||
if (ParseCXXTypeSpecifierSeq(DS))
|
||||
return StmtError();
|
||||
|
||||
Declarator ExDecl(DS, Declarator::CXXCatchContext);
|
||||
Declarator ExDecl(DS, DeclaratorContext::CXXCatchContext);
|
||||
ParseDeclarator(ExDecl);
|
||||
ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
|
||||
} else
|
||||
|
@ -24,7 +24,7 @@ using namespace clang;
|
||||
/// \brief Parse a template declaration, explicit instantiation, or
|
||||
/// explicit specialization.
|
||||
Decl *
|
||||
Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
|
||||
Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
AccessSpecifier AS,
|
||||
AttributeList *AccessAttrs) {
|
||||
@ -57,7 +57,7 @@ Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
|
||||
/// explicit-specialization: [ C++ temp.expl.spec]
|
||||
/// 'template' '<' '>' declaration
|
||||
Decl *
|
||||
Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
||||
Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
|
||||
SourceLocation &DeclEnd,
|
||||
AccessSpecifier AS,
|
||||
AttributeList *AccessAttrs) {
|
||||
@ -169,7 +169,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
||||
/// \returns the new declaration.
|
||||
Decl *
|
||||
Parser::ParseSingleDeclarationAfterTemplate(
|
||||
unsigned Context,
|
||||
DeclaratorContext Context,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
ParsingDeclRAIIObject &DiagsFromTParams,
|
||||
SourceLocation &DeclEnd,
|
||||
@ -186,7 +186,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
|
||||
return ParseStaticAssertDeclaration(DeclEnd);
|
||||
}
|
||||
|
||||
if (Context == Declarator::MemberContext) {
|
||||
if (Context == DeclaratorContext::MemberContext) {
|
||||
// We are parsing a member template.
|
||||
ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
|
||||
&DiagsFromTParams);
|
||||
@ -234,7 +234,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
|
||||
DS.takeAttributesFrom(prefixAttrs);
|
||||
|
||||
// Parse the declarator.
|
||||
ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
|
||||
ParsingDeclarator DeclaratorInfo(*this, DS, (DeclaratorContext)Context);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
// Error parsing the declarator?
|
||||
if (!DeclaratorInfo.hasName()) {
|
||||
@ -255,7 +255,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
|
||||
// Function definitions are only allowed at file scope and in C++ classes.
|
||||
// The C++ inline method definition case is handled elsewhere, so we only
|
||||
// need to handle the file scope definition case.
|
||||
if (Context != Declarator::FileContext) {
|
||||
if (Context != DeclaratorContext::FileContext) {
|
||||
Diag(Tok, diag::err_function_definition_not_allowed);
|
||||
SkipMalformedDecl();
|
||||
return nullptr;
|
||||
@ -271,7 +271,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
|
||||
}
|
||||
|
||||
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
|
||||
if (DeclaratorInfo.getName().getKind() != UnqualifiedId::IK_TemplateId) {
|
||||
if (DeclaratorInfo.getName().getKind() !=
|
||||
UnqualifiedIdKind::IK_TemplateId) {
|
||||
// If the declarator-id is not a template-id, issue a diagnostic and
|
||||
// recover by ignoring the 'template' keyword.
|
||||
Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
|
||||
@ -369,7 +370,7 @@ bool Parser::ParseTemplateParameters(
|
||||
/// template-parameter
|
||||
/// template-parameter-list ',' template-parameter
|
||||
bool
|
||||
Parser::ParseTemplateParameterList(unsigned Depth,
|
||||
Parser::ParseTemplateParameterList(const unsigned Depth,
|
||||
SmallVectorImpl<NamedDecl*> &TemplateParams) {
|
||||
while (1) {
|
||||
|
||||
@ -546,7 +547,7 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
|
||||
ParsedType DefaultArg;
|
||||
if (TryConsumeToken(tok::equal, EqualLoc))
|
||||
DefaultArg = ParseTypeName(/*Range=*/nullptr,
|
||||
Declarator::TemplateTypeArgContext).get();
|
||||
DeclaratorContext::TemplateTypeArgContext).get();
|
||||
|
||||
return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc,
|
||||
KeyLoc, ParamName, NameLoc, Depth, Position,
|
||||
@ -676,10 +677,10 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
|
||||
// declarators (parts of declarators?) are accepted for parameters.
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
|
||||
DSC_template_param);
|
||||
DeclSpecContext::DSC_template_param);
|
||||
|
||||
// Parse this as a typename.
|
||||
Declarator ParamDecl(DS, Declarator::TemplateParamContext);
|
||||
Declarator ParamDecl(DS, DeclaratorContext::TemplateParamContext);
|
||||
ParseDeclarator(ParamDecl);
|
||||
if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
|
||||
Diag(Tok.getLocation(), diag::err_expected_template_parameter);
|
||||
@ -1015,12 +1016,12 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
|
||||
Tok.setKind(tok::annot_template_id);
|
||||
|
||||
IdentifierInfo *TemplateII =
|
||||
TemplateName.getKind() == UnqualifiedId::IK_Identifier
|
||||
TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier
|
||||
? TemplateName.Identifier
|
||||
: nullptr;
|
||||
|
||||
OverloadedOperatorKind OpKind =
|
||||
TemplateName.getKind() == UnqualifiedId::IK_Identifier
|
||||
TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier
|
||||
? OO_None
|
||||
: TemplateName.OperatorFunctionId.Operator;
|
||||
|
||||
@ -1193,8 +1194,8 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
|
||||
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
|
||||
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr,
|
||||
Declarator::TemplateTypeArgContext);
|
||||
TypeResult TypeArg = ParseTypeName(
|
||||
/*Range=*/nullptr, DeclaratorContext::TemplateTypeArgContext);
|
||||
if (TypeArg.isInvalid())
|
||||
return ParsedTemplateArgument();
|
||||
|
||||
@ -1297,7 +1298,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
|
||||
/// 'extern' [opt] 'template' declaration
|
||||
///
|
||||
/// Note that the 'extern' is a GNU extension and C++11 feature.
|
||||
Decl *Parser::ParseExplicitInstantiation(unsigned Context,
|
||||
Decl *Parser::ParseExplicitInstantiation(DeclaratorContext Context,
|
||||
SourceLocation ExternLoc,
|
||||
SourceLocation TemplateLoc,
|
||||
SourceLocation &DeclEnd,
|
||||
|
@ -783,7 +783,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
||||
// A function definition cannot start with any of these keywords.
|
||||
{
|
||||
SourceLocation DeclEnd;
|
||||
return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
|
||||
return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
|
||||
}
|
||||
|
||||
case tok::kw_static:
|
||||
@ -793,7 +793,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
||||
Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
|
||||
<< 0;
|
||||
SourceLocation DeclEnd;
|
||||
return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
|
||||
return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
|
||||
}
|
||||
goto dont_know;
|
||||
|
||||
@ -804,7 +804,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
||||
// Inline namespaces. Allowed as an extension even in C++03.
|
||||
if (NextKind == tok::kw_namespace) {
|
||||
SourceLocation DeclEnd;
|
||||
return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
|
||||
return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
|
||||
}
|
||||
|
||||
// Parse (then ignore) 'inline' prior to a template instantiation. This is
|
||||
@ -813,7 +813,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
||||
Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
|
||||
<< 1;
|
||||
SourceLocation DeclEnd;
|
||||
return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
|
||||
return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
|
||||
}
|
||||
}
|
||||
goto dont_know;
|
||||
@ -828,7 +828,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
||||
diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc);
|
||||
SourceLocation DeclEnd;
|
||||
return Actions.ConvertDeclToDeclGroup(
|
||||
ParseExplicitInstantiation(Declarator::FileContext,
|
||||
ParseExplicitInstantiation(DeclaratorContext::FileContext,
|
||||
ExternLoc, TemplateLoc, DeclEnd));
|
||||
}
|
||||
goto dont_know;
|
||||
@ -919,12 +919,13 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
|
||||
AccessSpecifier AS) {
|
||||
MaybeParseMicrosoftAttributes(DS.getAttributes());
|
||||
// Parse the common declaration-specifiers piece.
|
||||
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
|
||||
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS,
|
||||
DeclSpecContext::DSC_top_level);
|
||||
|
||||
// If we had a free-standing type definition with a missing semicolon, we
|
||||
// may get this far before the problem becomes obvious.
|
||||
if (DS.hasTagDefinition() &&
|
||||
DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_top_level))
|
||||
if (DS.hasTagDefinition() && DiagnoseMissingSemiAfterTagDefinition(
|
||||
DS, AS, DeclSpecContext::DSC_top_level))
|
||||
return nullptr;
|
||||
|
||||
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
|
||||
@ -1004,11 +1005,11 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
|
||||
if (getLangOpts().CPlusPlus && isTokenStringLiteral() &&
|
||||
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
|
||||
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
|
||||
Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext);
|
||||
Decl *TheDecl = ParseLinkage(DS, DeclaratorContext::FileContext);
|
||||
return Actions.ConvertDeclToDeclGroup(TheDecl);
|
||||
}
|
||||
|
||||
return ParseDeclGroup(DS, Declarator::FileContext);
|
||||
return ParseDeclGroup(DS, DeclaratorContext::FileContext);
|
||||
}
|
||||
|
||||
Parser::DeclGroupPtrTy
|
||||
@ -1313,7 +1314,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
|
||||
}
|
||||
|
||||
// Parse the first declarator attached to this declspec.
|
||||
Declarator ParmDeclarator(DS, Declarator::KNRTypeListContext);
|
||||
Declarator ParmDeclarator(DS, DeclaratorContext::KNRTypeListContext);
|
||||
ParseDeclarator(ParmDeclarator);
|
||||
|
||||
// Handle the full declarator list.
|
||||
|
@ -30,7 +30,7 @@ using namespace clang;
|
||||
|
||||
void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
|
||||
assert(TemplateId && "NULL template-id annotation?");
|
||||
Kind = IK_TemplateId;
|
||||
Kind = UnqualifiedIdKind::IK_TemplateId;
|
||||
this->TemplateId = TemplateId;
|
||||
StartLocation = TemplateId->TemplateNameLoc;
|
||||
EndLocation = TemplateId->RAngleLoc;
|
||||
@ -38,7 +38,7 @@ void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
|
||||
|
||||
void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
|
||||
assert(TemplateId && "NULL template-id annotation?");
|
||||
Kind = IK_ConstructorTemplateId;
|
||||
Kind = UnqualifiedIdKind::IK_ConstructorTemplateId;
|
||||
this->TemplateId = TemplateId;
|
||||
StartLocation = TemplateId->TemplateNameLoc;
|
||||
EndLocation = TemplateId->RAngleLoc;
|
||||
@ -387,16 +387,16 @@ bool Declarator::isDeclarationOfFunction() const {
|
||||
}
|
||||
|
||||
bool Declarator::isStaticMember() {
|
||||
assert(getContext() == MemberContext);
|
||||
assert(getContext() == DeclaratorContext::MemberContext);
|
||||
return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
|
||||
(getName().Kind == UnqualifiedId::IK_OperatorFunctionId &&
|
||||
(getName().Kind == UnqualifiedIdKind::IK_OperatorFunctionId &&
|
||||
CXXMethodDecl::isStaticOverloadedOperator(
|
||||
getName().OperatorFunctionId.Operator));
|
||||
}
|
||||
|
||||
bool Declarator::isCtorOrDtor() {
|
||||
return (getName().getKind() == UnqualifiedId::IK_ConstructorName) ||
|
||||
(getName().getKind() == UnqualifiedId::IK_DestructorName);
|
||||
return (getName().getKind() == UnqualifiedIdKind::IK_ConstructorName) ||
|
||||
(getName().getKind() == UnqualifiedIdKind::IK_DestructorName);
|
||||
}
|
||||
|
||||
bool DeclSpec::hasTagDefinition() const {
|
||||
@ -1281,7 +1281,7 @@ bool DeclSpec::isMissingDeclaratorOk() {
|
||||
void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
|
||||
OverloadedOperatorKind Op,
|
||||
SourceLocation SymbolLocations[3]) {
|
||||
Kind = IK_OperatorFunctionId;
|
||||
Kind = UnqualifiedIdKind::IK_OperatorFunctionId;
|
||||
StartLocation = OperatorLoc;
|
||||
EndLocation = OperatorLoc;
|
||||
OperatorFunctionId.Operator = Op;
|
||||
|
@ -4171,8 +4171,8 @@ void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
|
||||
AddTypeQualifierResults(DS, Results, LangOpts);
|
||||
if (LangOpts.CPlusPlus11) {
|
||||
Results.AddResult("noexcept");
|
||||
if (D.getContext() == Declarator::MemberContext && !D.isCtorOrDtor() &&
|
||||
!D.isStaticMember()) {
|
||||
if (D.getContext() == DeclaratorContext::MemberContext &&
|
||||
!D.isCtorOrDtor() && !D.isStaticMember()) {
|
||||
if (!VS || !VS->isFinalSpecified())
|
||||
Results.AddResult("final");
|
||||
if (!VS || !VS->isOverrideSpecified())
|
||||
|
@ -4746,7 +4746,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
|
||||
}
|
||||
|
||||
// Mock up a declarator.
|
||||
Declarator Dc(DS, Declarator::MemberContext);
|
||||
Declarator Dc(DS, DeclaratorContext::MemberContext);
|
||||
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
|
||||
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
|
||||
|
||||
@ -4843,7 +4843,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
|
||||
assert(Record && "expected a record!");
|
||||
|
||||
// Mock up a declarator.
|
||||
Declarator Dc(DS, Declarator::TypeNameContext);
|
||||
Declarator Dc(DS, DeclaratorContext::TypeNameContext);
|
||||
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
|
||||
assert(TInfo && "couldn't build declarator info for anonymous struct");
|
||||
|
||||
@ -4897,13 +4897,13 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
|
||||
|
||||
switch (Name.getKind()) {
|
||||
|
||||
case UnqualifiedId::IK_ImplicitSelfParam:
|
||||
case UnqualifiedId::IK_Identifier:
|
||||
case UnqualifiedIdKind::IK_ImplicitSelfParam:
|
||||
case UnqualifiedIdKind::IK_Identifier:
|
||||
NameInfo.setName(Name.Identifier);
|
||||
NameInfo.setLoc(Name.StartLocation);
|
||||
return NameInfo;
|
||||
|
||||
case UnqualifiedId::IK_DeductionGuideName: {
|
||||
case UnqualifiedIdKind::IK_DeductionGuideName: {
|
||||
// C++ [temp.deduct.guide]p3:
|
||||
// The simple-template-id shall name a class template specialization.
|
||||
// The template-name shall be the same identifier as the template-name
|
||||
@ -4931,7 +4931,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
|
||||
return NameInfo;
|
||||
}
|
||||
|
||||
case UnqualifiedId::IK_OperatorFunctionId:
|
||||
case UnqualifiedIdKind::IK_OperatorFunctionId:
|
||||
NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
|
||||
Name.OperatorFunctionId.Operator));
|
||||
NameInfo.setLoc(Name.StartLocation);
|
||||
@ -4941,14 +4941,14 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
|
||||
= Name.EndLocation.getRawEncoding();
|
||||
return NameInfo;
|
||||
|
||||
case UnqualifiedId::IK_LiteralOperatorId:
|
||||
case UnqualifiedIdKind::IK_LiteralOperatorId:
|
||||
NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName(
|
||||
Name.Identifier));
|
||||
NameInfo.setLoc(Name.StartLocation);
|
||||
NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation);
|
||||
return NameInfo;
|
||||
|
||||
case UnqualifiedId::IK_ConversionFunctionId: {
|
||||
case UnqualifiedIdKind::IK_ConversionFunctionId: {
|
||||
TypeSourceInfo *TInfo;
|
||||
QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo);
|
||||
if (Ty.isNull())
|
||||
@ -4960,7 +4960,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
|
||||
return NameInfo;
|
||||
}
|
||||
|
||||
case UnqualifiedId::IK_ConstructorName: {
|
||||
case UnqualifiedIdKind::IK_ConstructorName: {
|
||||
TypeSourceInfo *TInfo;
|
||||
QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo);
|
||||
if (Ty.isNull())
|
||||
@ -4972,7 +4972,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
|
||||
return NameInfo;
|
||||
}
|
||||
|
||||
case UnqualifiedId::IK_ConstructorTemplateId: {
|
||||
case UnqualifiedIdKind::IK_ConstructorTemplateId: {
|
||||
// In well-formed code, we can only have a constructor
|
||||
// template-id that refers to the current context, so go there
|
||||
// to find the actual type being constructed.
|
||||
@ -4995,7 +4995,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
|
||||
return NameInfo;
|
||||
}
|
||||
|
||||
case UnqualifiedId::IK_DestructorName: {
|
||||
case UnqualifiedIdKind::IK_DestructorName: {
|
||||
TypeSourceInfo *TInfo;
|
||||
QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo);
|
||||
if (Ty.isNull())
|
||||
@ -5007,7 +5007,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
|
||||
return NameInfo;
|
||||
}
|
||||
|
||||
case UnqualifiedId::IK_TemplateId: {
|
||||
case UnqualifiedIdKind::IK_TemplateId: {
|
||||
TemplateName TName = Name.TemplateId->Template.get();
|
||||
SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc;
|
||||
return Context.getNameForTemplate(TName, TNameLoc);
|
||||
@ -5670,8 +5670,8 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
|
||||
<< 1;
|
||||
|
||||
if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
|
||||
if (D.getName().Kind == UnqualifiedId::IK_DeductionGuideName)
|
||||
if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) {
|
||||
if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName)
|
||||
Diag(D.getName().StartLocation,
|
||||
diag::err_deduction_guide_invalid_specifier)
|
||||
<< "typedef";
|
||||
@ -6425,7 +6425,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
||||
TemplateParams = MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(),
|
||||
D.getName().getKind() == UnqualifiedId::IK_TemplateId
|
||||
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
|
||||
? D.getName().TemplateId
|
||||
: nullptr,
|
||||
TemplateParamLists,
|
||||
@ -6433,7 +6433,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
||||
|
||||
if (TemplateParams) {
|
||||
if (!TemplateParams->size() &&
|
||||
D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
|
||||
D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
|
||||
// There is an extraneous 'template<>' for this variable. Complain
|
||||
// about it, but allow the declaration of the variable.
|
||||
Diag(TemplateParams->getTemplateLoc(),
|
||||
@ -6443,7 +6443,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
||||
TemplateParams->getRAngleLoc());
|
||||
TemplateParams = nullptr;
|
||||
} else {
|
||||
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
|
||||
// This is an explicit specialization or a partial specialization.
|
||||
// FIXME: Check that we can declare a specialization here.
|
||||
IsVariableTemplateSpecialization = true;
|
||||
@ -6464,8 +6464,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(
|
||||
(Invalid || D.getName().getKind() != UnqualifiedId::IK_TemplateId) &&
|
||||
assert((Invalid ||
|
||||
D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) &&
|
||||
"should have a 'template<>' for this decl");
|
||||
}
|
||||
|
||||
@ -8261,7 +8261,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(),
|
||||
D.getName().getKind() == UnqualifiedId::IK_TemplateId
|
||||
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
|
||||
? D.getName().TemplateId
|
||||
: nullptr,
|
||||
TemplateParamLists, isFriend, isMemberSpecialization,
|
||||
@ -8318,7 +8318,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
// and clearly the user wants a template specialization. So
|
||||
// we need to insert '<>' after the name.
|
||||
SourceLocation InsertLoc;
|
||||
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
|
||||
if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
|
||||
InsertLoc = D.getName().getSourceRange().getEnd();
|
||||
InsertLoc = getLocForEndOfToken(InsertLoc);
|
||||
}
|
||||
@ -8719,7 +8719,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
|
||||
// If the declarator is a template-id, translate the parser's template
|
||||
// argument list into our AST format.
|
||||
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
|
||||
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
|
||||
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
|
||||
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
|
||||
@ -10893,7 +10893,7 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
|
||||
DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID,
|
||||
getPrintingPolicy());
|
||||
|
||||
Declarator D(DS, Declarator::ForContext);
|
||||
Declarator D(DS, DeclaratorContext::ForContext);
|
||||
D.SetIdentifier(Ident, IdentLoc);
|
||||
D.takeAttributes(Attrs, AttrEnd);
|
||||
|
||||
@ -11809,7 +11809,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
|
||||
// Use the identifier location for the type source range.
|
||||
DS.SetRangeStart(FTI.Params[i].IdentLoc);
|
||||
DS.SetRangeEnd(FTI.Params[i].IdentLoc);
|
||||
Declarator ParamD(DS, Declarator::KNRTypeListContext);
|
||||
Declarator ParamD(DS, DeclaratorContext::KNRTypeListContext);
|
||||
ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc);
|
||||
FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD);
|
||||
}
|
||||
@ -12574,7 +12574,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
||||
(void)Error; // Silence warning.
|
||||
assert(!Error && "Error setting up implicit decl!");
|
||||
SourceLocation NoLoc;
|
||||
Declarator D(DS, Declarator::BlockContext);
|
||||
Declarator D(DS, DeclaratorContext::BlockContext);
|
||||
D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false,
|
||||
/*IsAmbiguous=*/false,
|
||||
/*LParenLoc=*/NoLoc,
|
||||
|
@ -712,7 +712,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
|
||||
Diag(Decomp.getLSquareLoc(),
|
||||
!getLangOpts().CPlusPlus17
|
||||
? diag::ext_decomp_decl
|
||||
: D.getContext() == Declarator::ConditionContext
|
||||
: D.getContext() == DeclaratorContext::ConditionContext
|
||||
? diag::ext_decomp_decl_cond
|
||||
: diag::warn_cxx14_compat_decomp_decl)
|
||||
<< Decomp.getSourceRange();
|
||||
@ -8986,15 +8986,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
|
||||
}
|
||||
|
||||
switch (Name.getKind()) {
|
||||
case UnqualifiedId::IK_ImplicitSelfParam:
|
||||
case UnqualifiedId::IK_Identifier:
|
||||
case UnqualifiedId::IK_OperatorFunctionId:
|
||||
case UnqualifiedId::IK_LiteralOperatorId:
|
||||
case UnqualifiedId::IK_ConversionFunctionId:
|
||||
case UnqualifiedIdKind::IK_ImplicitSelfParam:
|
||||
case UnqualifiedIdKind::IK_Identifier:
|
||||
case UnqualifiedIdKind::IK_OperatorFunctionId:
|
||||
case UnqualifiedIdKind::IK_LiteralOperatorId:
|
||||
case UnqualifiedIdKind::IK_ConversionFunctionId:
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_ConstructorName:
|
||||
case UnqualifiedId::IK_ConstructorTemplateId:
|
||||
case UnqualifiedIdKind::IK_ConstructorName:
|
||||
case UnqualifiedIdKind::IK_ConstructorTemplateId:
|
||||
// C++11 inheriting constructors.
|
||||
Diag(Name.getLocStart(),
|
||||
getLangOpts().CPlusPlus11 ?
|
||||
@ -9006,17 +9006,17 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
|
||||
|
||||
return nullptr;
|
||||
|
||||
case UnqualifiedId::IK_DestructorName:
|
||||
case UnqualifiedIdKind::IK_DestructorName:
|
||||
Diag(Name.getLocStart(), diag::err_using_decl_destructor)
|
||||
<< SS.getRange();
|
||||
return nullptr;
|
||||
|
||||
case UnqualifiedId::IK_TemplateId:
|
||||
case UnqualifiedIdKind::IK_TemplateId:
|
||||
Diag(Name.getLocStart(), diag::err_using_decl_template_id)
|
||||
<< SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
|
||||
return nullptr;
|
||||
|
||||
case UnqualifiedId::IK_DeductionGuideName:
|
||||
case UnqualifiedIdKind::IK_DeductionGuideName:
|
||||
llvm_unreachable("cannot parse qualified deduction guide name");
|
||||
}
|
||||
|
||||
@ -10040,7 +10040,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
|
||||
Previous.clear();
|
||||
}
|
||||
|
||||
assert(Name.Kind == UnqualifiedId::IK_Identifier &&
|
||||
assert(Name.Kind == UnqualifiedIdKind::IK_Identifier &&
|
||||
"name in alias declaration must be an identifier");
|
||||
TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc,
|
||||
Name.StartLocation,
|
||||
@ -12215,30 +12215,27 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
|
||||
SourceLocation CurrentLocation,
|
||||
CXXConversionDecl *Conv) {
|
||||
SynthesizedFunctionScope Scope(*this, Conv);
|
||||
assert(!Conv->getReturnType()->isUndeducedType());
|
||||
|
||||
CXXRecordDecl *Lambda = Conv->getParent();
|
||||
CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
|
||||
// If we are defining a specialization of a conversion to function-ptr
|
||||
// cache the deduced template arguments for this specialization
|
||||
// so that we can use them to retrieve the corresponding call-operator
|
||||
// and static-invoker.
|
||||
const TemplateArgumentList *DeducedTemplateArgs = nullptr;
|
||||
FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
|
||||
FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();
|
||||
|
||||
// Retrieve the corresponding call-operator specialization.
|
||||
if (Lambda->isGenericLambda()) {
|
||||
assert(Conv->isFunctionTemplateSpecialization());
|
||||
FunctionTemplateDecl *CallOpTemplate =
|
||||
CallOp->getDescribedFunctionTemplate();
|
||||
DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
|
||||
void *InsertPos = nullptr;
|
||||
FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
|
||||
DeducedTemplateArgs->asArray(),
|
||||
InsertPos);
|
||||
assert(CallOpSpec &&
|
||||
"Conversion operator must have a corresponding call operator");
|
||||
CallOp = cast<CXXMethodDecl>(CallOpSpec);
|
||||
if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
|
||||
CallOp = InstantiateFunctionDeclaration(
|
||||
CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
|
||||
if (!CallOp)
|
||||
return;
|
||||
|
||||
Invoker = InstantiateFunctionDeclaration(
|
||||
Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
|
||||
if (!Invoker)
|
||||
return;
|
||||
}
|
||||
|
||||
if (CallOp->isInvalidDecl())
|
||||
return;
|
||||
|
||||
// Mark the call operator referenced (and add to pending instantiations
|
||||
// if necessary).
|
||||
// For both the conversion and static-invoker template specializations
|
||||
@ -12246,22 +12243,14 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
|
||||
// to the PendingInstantiations.
|
||||
MarkFunctionReferenced(CurrentLocation, CallOp);
|
||||
|
||||
// Retrieve the static invoker...
|
||||
CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
|
||||
// ... and get the corresponding specialization for a generic lambda.
|
||||
if (Lambda->isGenericLambda()) {
|
||||
assert(DeducedTemplateArgs &&
|
||||
"Must have deduced template arguments from Conversion Operator");
|
||||
FunctionTemplateDecl *InvokeTemplate =
|
||||
Invoker->getDescribedFunctionTemplate();
|
||||
void *InsertPos = nullptr;
|
||||
FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
|
||||
DeducedTemplateArgs->asArray(),
|
||||
InsertPos);
|
||||
assert(InvokeSpec &&
|
||||
"Must have a corresponding static invoker specialization");
|
||||
Invoker = cast<CXXMethodDecl>(InvokeSpec);
|
||||
}
|
||||
// Fill in the __invoke function with a dummy implementation. IR generation
|
||||
// will fill in the actual details. Update its type in case it contained
|
||||
// an 'auto'.
|
||||
Invoker->markUsed(Context);
|
||||
Invoker->setReferenced();
|
||||
Invoker->setType(Conv->getReturnType()->getPointeeType());
|
||||
Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
|
||||
|
||||
// Construct the body of the conversion function { return __invoke; }.
|
||||
Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
|
||||
VK_LValue, Conv->getLocation()).get();
|
||||
@ -12269,16 +12258,9 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
|
||||
Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get();
|
||||
Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(),
|
||||
Conv->getLocation()));
|
||||
|
||||
Conv->markUsed(Context);
|
||||
Conv->setReferenced();
|
||||
|
||||
// Fill in the __invoke function with a dummy implementation. IR generation
|
||||
// will fill in the actual details.
|
||||
Invoker->markUsed(Context);
|
||||
Invoker->setReferenced();
|
||||
Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
|
||||
|
||||
if (ASTMutationListener *L = getASTMutationListener()) {
|
||||
L->CompletedImplicitDefinition(Conv);
|
||||
L->CompletedImplicitDefinition(Invoker);
|
||||
@ -13625,7 +13607,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
||||
// Try to convert the decl specifier to a type. This works for
|
||||
// friend templates because ActOnTag never produces a ClassTemplateDecl
|
||||
// for a TUK_Friend.
|
||||
Declarator TheDeclarator(DS, Declarator::MemberContext);
|
||||
Declarator TheDeclarator(DS, DeclaratorContext::MemberContext);
|
||||
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
|
||||
QualType T = TSI->getType();
|
||||
if (TheDeclarator.isInvalidType())
|
||||
@ -13799,7 +13781,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
|
||||
// elaborated-type-specifier, the lookup to determine whether
|
||||
// the entity has been previously declared shall not consider
|
||||
// any scopes outside the innermost enclosing namespace.
|
||||
bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
|
||||
bool isTemplateId =
|
||||
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;
|
||||
|
||||
// Find the appropriate context according to the above.
|
||||
DC = CurContext;
|
||||
@ -13910,24 +13893,24 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
|
||||
if (!DC->isRecord()) {
|
||||
int DiagArg = -1;
|
||||
switch (D.getName().getKind()) {
|
||||
case UnqualifiedId::IK_ConstructorTemplateId:
|
||||
case UnqualifiedId::IK_ConstructorName:
|
||||
case UnqualifiedIdKind::IK_ConstructorTemplateId:
|
||||
case UnqualifiedIdKind::IK_ConstructorName:
|
||||
DiagArg = 0;
|
||||
break;
|
||||
case UnqualifiedId::IK_DestructorName:
|
||||
case UnqualifiedIdKind::IK_DestructorName:
|
||||
DiagArg = 1;
|
||||
break;
|
||||
case UnqualifiedId::IK_ConversionFunctionId:
|
||||
case UnqualifiedIdKind::IK_ConversionFunctionId:
|
||||
DiagArg = 2;
|
||||
break;
|
||||
case UnqualifiedId::IK_DeductionGuideName:
|
||||
case UnqualifiedIdKind::IK_DeductionGuideName:
|
||||
DiagArg = 3;
|
||||
break;
|
||||
case UnqualifiedId::IK_Identifier:
|
||||
case UnqualifiedId::IK_ImplicitSelfParam:
|
||||
case UnqualifiedId::IK_LiteralOperatorId:
|
||||
case UnqualifiedId::IK_OperatorFunctionId:
|
||||
case UnqualifiedId::IK_TemplateId:
|
||||
case UnqualifiedIdKind::IK_Identifier:
|
||||
case UnqualifiedIdKind::IK_ImplicitSelfParam:
|
||||
case UnqualifiedIdKind::IK_LiteralOperatorId:
|
||||
case UnqualifiedIdKind::IK_OperatorFunctionId:
|
||||
case UnqualifiedIdKind::IK_TemplateId:
|
||||
break;
|
||||
}
|
||||
// This implies that it has to be an operator or function.
|
||||
|
@ -1538,7 +1538,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
|
||||
DS.SetRangeEnd(loc);
|
||||
|
||||
// Form the declarator.
|
||||
Declarator D(DS, Declarator::TypeNameContext);
|
||||
Declarator D(DS, DeclaratorContext::TypeNameContext);
|
||||
|
||||
// If we have a typedef of an Objective-C class type that is missing a '*',
|
||||
// add the '*'.
|
||||
|
@ -1711,7 +1711,7 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
|
||||
TemplateArgumentListInfo &Buffer,
|
||||
DeclarationNameInfo &NameInfo,
|
||||
const TemplateArgumentListInfo *&TemplateArgs) {
|
||||
if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
|
||||
if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId) {
|
||||
Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
|
||||
Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
|
||||
|
||||
@ -2071,8 +2071,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
|
||||
|
||||
// Perform the required lookup.
|
||||
LookupResult R(*this, NameInfo,
|
||||
(Id.getKind() == UnqualifiedId::IK_ImplicitSelfParam)
|
||||
? LookupObjCImplicitSelfParam : LookupOrdinaryName);
|
||||
(Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam)
|
||||
? LookupObjCImplicitSelfParam
|
||||
: LookupOrdinaryName);
|
||||
if (TemplateArgs) {
|
||||
// Lookup the template name again to correctly establish the context in
|
||||
// which it was found. This is really unfortunate as we already did the
|
||||
@ -2243,7 +2244,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
|
||||
// In C++1y, if this is a variable template id, then check it
|
||||
// in BuildTemplateIdExpr().
|
||||
// The single lookup result must be a variable template declaration.
|
||||
if (Id.getKind() == UnqualifiedId::IK_TemplateId && Id.TemplateId &&
|
||||
if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId && Id.TemplateId &&
|
||||
Id.TemplateId->Kind == TNK_Var_template) {
|
||||
assert(R.getAsSingle<VarTemplateDecl>() &&
|
||||
"There should only be one declaration found.");
|
||||
@ -2401,7 +2402,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
|
||||
IdentifierInfo &II = Context.Idents.get("self");
|
||||
UnqualifiedId SelfName;
|
||||
SelfName.setIdentifier(&II, SourceLocation());
|
||||
SelfName.setKind(UnqualifiedId::IK_ImplicitSelfParam);
|
||||
SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
|
||||
CXXScopeSpec SelfScopeSpec;
|
||||
SourceLocation TemplateKWLoc;
|
||||
ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc,
|
||||
@ -12834,7 +12835,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
|
||||
Scope *CurScope) {
|
||||
assert(ParamInfo.getIdentifier() == nullptr &&
|
||||
"block-id should have no identifier!");
|
||||
assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
|
||||
assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteralContext);
|
||||
BlockScopeInfo *CurBlock = getCurBlock();
|
||||
|
||||
TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
|
||||
|
@ -356,7 +356,7 @@ ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS,
|
||||
|
||||
bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
|
||||
const UnqualifiedId &Name) {
|
||||
assert(Name.getKind() == UnqualifiedId::IK_LiteralOperatorId);
|
||||
assert(Name.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId);
|
||||
|
||||
if (!SS.isValid())
|
||||
return false;
|
||||
@ -6716,11 +6716,11 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
|
||||
SourceLocation CCLoc,
|
||||
SourceLocation TildeLoc,
|
||||
UnqualifiedId &SecondTypeName) {
|
||||
assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
|
||||
FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
|
||||
assert((FirstTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
|
||||
FirstTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) &&
|
||||
"Invalid first type name in pseudo-destructor");
|
||||
assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
|
||||
SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
|
||||
assert((SecondTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
|
||||
SecondTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) &&
|
||||
"Invalid second type name in pseudo-destructor");
|
||||
|
||||
QualType ObjectType;
|
||||
@ -6742,7 +6742,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
|
||||
QualType DestructedType;
|
||||
TypeSourceInfo *DestructedTypeInfo = nullptr;
|
||||
PseudoDestructorTypeStorage Destructed;
|
||||
if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
|
||||
if (SecondTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) {
|
||||
ParsedType T = getTypeName(*SecondTypeName.Identifier,
|
||||
SecondTypeName.StartLocation,
|
||||
S, &SS, true, false, ObjectTypePtrForLookup,
|
||||
@ -6800,9 +6800,9 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
|
||||
// Convert the name of the scope type (the type prior to '::') into a type.
|
||||
TypeSourceInfo *ScopeTypeInfo = nullptr;
|
||||
QualType ScopeType;
|
||||
if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
|
||||
if (FirstTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
|
||||
FirstTypeName.Identifier) {
|
||||
if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
|
||||
if (FirstTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) {
|
||||
ParsedType T = getTypeName(*FirstTypeName.Identifier,
|
||||
FirstTypeName.StartLocation,
|
||||
S, &SS, true, false, ObjectTypePtrForLookup,
|
||||
|
@ -1707,7 +1707,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
|
||||
|
||||
// Warn about the explicit constructor calls Microsoft extension.
|
||||
if (getLangOpts().MicrosoftExt &&
|
||||
Id.getKind() == UnqualifiedId::IK_ConstructorName)
|
||||
Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
|
||||
Diag(Id.getSourceRange().getBegin(),
|
||||
diag::ext_ms_explicit_constructor_call);
|
||||
|
||||
|
@ -1167,6 +1167,24 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
|
||||
PopFunctionScopeInfo();
|
||||
}
|
||||
|
||||
QualType Sema::getLambdaConversionFunctionResultType(
|
||||
const FunctionProtoType *CallOpProto) {
|
||||
// The function type inside the pointer type is the same as the call
|
||||
// operator with some tweaks. The calling convention is the default free
|
||||
// function convention, and the type qualifications are lost.
|
||||
const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
|
||||
CallOpProto->getExtProtoInfo();
|
||||
FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
|
||||
CallingConv CC = Context.getDefaultCallingConvention(
|
||||
CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
|
||||
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
|
||||
InvokerExtInfo.TypeQuals = 0;
|
||||
assert(InvokerExtInfo.RefQualifier == RQ_None &&
|
||||
"Lambda's call operator should not have a reference qualifier");
|
||||
return Context.getFunctionType(CallOpProto->getReturnType(),
|
||||
CallOpProto->getParamTypes(), InvokerExtInfo);
|
||||
}
|
||||
|
||||
/// \brief Add a lambda's conversion to function pointer, as described in
|
||||
/// C++11 [expr.prim.lambda]p6.
|
||||
static void addFunctionPointerConversion(Sema &S,
|
||||
@ -1182,25 +1200,9 @@ static void addFunctionPointerConversion(Sema &S,
|
||||
return;
|
||||
|
||||
// Add the conversion to function pointer.
|
||||
const FunctionProtoType *CallOpProto =
|
||||
CallOperator->getType()->getAs<FunctionProtoType>();
|
||||
const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
|
||||
CallOpProto->getExtProtoInfo();
|
||||
QualType PtrToFunctionTy;
|
||||
QualType InvokerFunctionTy;
|
||||
{
|
||||
FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
|
||||
CallingConv CC = S.Context.getDefaultCallingConvention(
|
||||
CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
|
||||
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
|
||||
InvokerExtInfo.TypeQuals = 0;
|
||||
assert(InvokerExtInfo.RefQualifier == RQ_None &&
|
||||
"Lambda's call operator should not have a reference qualifier");
|
||||
InvokerFunctionTy =
|
||||
S.Context.getFunctionType(CallOpProto->getReturnType(),
|
||||
CallOpProto->getParamTypes(), InvokerExtInfo);
|
||||
PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
|
||||
}
|
||||
QualType InvokerFunctionTy = S.getLambdaConversionFunctionResultType(
|
||||
CallOperator->getType()->castAs<FunctionProtoType>());
|
||||
QualType PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
|
||||
|
||||
// Create the type of the conversion function.
|
||||
FunctionProtoType::ExtProtoInfo ConvExtInfo(
|
||||
@ -1357,19 +1359,8 @@ static void addBlockPointerConversion(Sema &S,
|
||||
SourceRange IntroducerRange,
|
||||
CXXRecordDecl *Class,
|
||||
CXXMethodDecl *CallOperator) {
|
||||
const FunctionProtoType *Proto =
|
||||
CallOperator->getType()->getAs<FunctionProtoType>();
|
||||
|
||||
// The function type inside the block pointer type is the same as the call
|
||||
// operator with some tweaks. The calling convention is the default free
|
||||
// function convention, and the type qualifications are lost.
|
||||
FunctionProtoType::ExtProtoInfo BlockEPI = Proto->getExtProtoInfo();
|
||||
BlockEPI.ExtInfo =
|
||||
BlockEPI.ExtInfo.withCallingConv(S.Context.getDefaultCallingConvention(
|
||||
Proto->isVariadic(), /*IsCXXMethod=*/false));
|
||||
BlockEPI.TypeQuals = 0;
|
||||
QualType FunctionTy = S.Context.getFunctionType(
|
||||
Proto->getReturnType(), Proto->getParamTypes(), BlockEPI);
|
||||
QualType FunctionTy = S.getLambdaConversionFunctionResultType(
|
||||
CallOperator->getType()->castAs<FunctionProtoType>());
|
||||
QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
|
||||
|
||||
FunctionProtoType::ExtProtoInfo ConversionEPI(
|
||||
|
@ -5145,7 +5145,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
|
||||
*this, From->getLocStart(), From->getType(), FromClassification, Method,
|
||||
Method->getParent());
|
||||
if (ICS.isBad()) {
|
||||
if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
|
||||
switch (ICS.Bad.Kind) {
|
||||
case BadConversionSequence::bad_qualifiers: {
|
||||
Qualifiers FromQs = FromRecordType.getQualifiers();
|
||||
Qualifiers ToQs = DestType.getQualifiers();
|
||||
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
|
||||
@ -5158,10 +5159,28 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
|
||||
<< Method->getDeclName();
|
||||
return ExprError();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BadConversionSequence::lvalue_ref_to_rvalue:
|
||||
case BadConversionSequence::rvalue_ref_to_lvalue: {
|
||||
bool IsRValueQualified =
|
||||
Method->getRefQualifier() == RefQualifierKind::RQ_RValue;
|
||||
Diag(From->getLocStart(), diag::err_member_function_call_bad_ref)
|
||||
<< Method->getDeclName() << FromClassification.isRValue()
|
||||
<< IsRValueQualified;
|
||||
Diag(Method->getLocation(), diag::note_previous_decl)
|
||||
<< Method->getDeclName();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
case BadConversionSequence::no_conversion:
|
||||
case BadConversionSequence::unrelated_class:
|
||||
break;
|
||||
}
|
||||
|
||||
return Diag(From->getLocStart(),
|
||||
diag::err_implicit_object_parameter_init)
|
||||
diag::err_member_function_call_bad_type)
|
||||
<< ImplicitParamRecordType << FromRecordType << From->getSourceRange();
|
||||
}
|
||||
|
||||
@ -11309,9 +11328,6 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
|
||||
return Matched;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Resolve and fix an overloaded expression that can be resolved
|
||||
// because it identifies a single function template specialization.
|
||||
//
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "clang/Sema/SemaInternal.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTDiagnostic.h"
|
||||
#include "clang/AST/ASTLambda.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
@ -3228,6 +3229,12 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
|
||||
SourceLocation ReturnLoc,
|
||||
Expr *&RetExpr,
|
||||
AutoType *AT) {
|
||||
// If this is the conversion function for a lambda, we choose to deduce it
|
||||
// type from the corresponding call operator, not from the synthesized return
|
||||
// statement within it. See Sema::DeduceReturnType.
|
||||
if (isLambdaConversionOperator(FD))
|
||||
return false;
|
||||
|
||||
TypeLoc OrigResultType = getReturnTypeLoc(FD);
|
||||
QualType Deduced;
|
||||
|
||||
|
@ -169,16 +169,16 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
|
||||
MemberOfUnknownSpecialization = false;
|
||||
|
||||
switch (Name.getKind()) {
|
||||
case UnqualifiedId::IK_Identifier:
|
||||
case UnqualifiedIdKind::IK_Identifier:
|
||||
TName = DeclarationName(Name.Identifier);
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_OperatorFunctionId:
|
||||
case UnqualifiedIdKind::IK_OperatorFunctionId:
|
||||
TName = Context.DeclarationNames.getCXXOperatorName(
|
||||
Name.OperatorFunctionId.Operator);
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_LiteralOperatorId:
|
||||
case UnqualifiedIdKind::IK_LiteralOperatorId:
|
||||
TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
|
||||
break;
|
||||
|
||||
@ -3557,7 +3557,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
|
||||
TemplateParameterList *TemplateParams, StorageClass SC,
|
||||
bool IsPartialSpecialization) {
|
||||
// D must be variable template id.
|
||||
assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
|
||||
assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId &&
|
||||
"Variable template specialization is declared with a template it.");
|
||||
|
||||
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
|
||||
@ -4084,8 +4084,8 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
|
||||
// We found something; return it.
|
||||
auto *LookupRD = dyn_cast<CXXRecordDecl>(LookupCtx);
|
||||
if (!AllowInjectedClassName && SS.isSet() && LookupRD &&
|
||||
Name.getKind() == UnqualifiedId::IK_Identifier && Name.Identifier &&
|
||||
LookupRD->getIdentifier() == Name.Identifier) {
|
||||
Name.getKind() == UnqualifiedIdKind::IK_Identifier &&
|
||||
Name.Identifier && LookupRD->getIdentifier() == Name.Identifier) {
|
||||
// C++14 [class.qual]p2:
|
||||
// In a lookup in which function names are not ignored and the
|
||||
// nested-name-specifier nominates a class C, if the name specified
|
||||
@ -4107,17 +4107,17 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
|
||||
NestedNameSpecifier *Qualifier = SS.getScopeRep();
|
||||
|
||||
switch (Name.getKind()) {
|
||||
case UnqualifiedId::IK_Identifier:
|
||||
case UnqualifiedIdKind::IK_Identifier:
|
||||
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
|
||||
Name.Identifier));
|
||||
return TNK_Dependent_template_name;
|
||||
|
||||
case UnqualifiedId::IK_OperatorFunctionId:
|
||||
case UnqualifiedIdKind::IK_OperatorFunctionId:
|
||||
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
|
||||
Name.OperatorFunctionId.Operator));
|
||||
return TNK_Function_template;
|
||||
|
||||
case UnqualifiedId::IK_LiteralOperatorId:
|
||||
case UnqualifiedIdKind::IK_LiteralOperatorId:
|
||||
llvm_unreachable("literal operator id cannot have a dependent scope");
|
||||
|
||||
default:
|
||||
@ -9044,7 +9044,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
|
||||
if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
|
||||
// C++1y [temp.explicit]p3:
|
||||
// If the explicit instantiation is for a variable, the unqualified-id
|
||||
// in the declaration shall be a template-id.
|
||||
@ -9126,7 +9126,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
// argument list into our AST format.
|
||||
bool HasExplicitTemplateArgs = false;
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
|
||||
TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
|
||||
HasExplicitTemplateArgs = true;
|
||||
}
|
||||
@ -9292,7 +9292,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
//
|
||||
// C++98 has the same restriction, just worded differently.
|
||||
FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
|
||||
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl &&
|
||||
if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId && !FunTmpl &&
|
||||
D.getCXXScopeSpec().isSet() &&
|
||||
!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
|
||||
Diag(D.getIdentifierLoc(),
|
||||
|
@ -3940,117 +3940,6 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
||||
return TDK_Success;
|
||||
}
|
||||
|
||||
/// \brief Given a function declaration (e.g. a generic lambda conversion
|
||||
/// function) that contains an 'auto' in its result type, substitute it
|
||||
/// with TypeToReplaceAutoWith. Be careful to pass in the type you want
|
||||
/// to replace 'auto' with and not the actual result type you want
|
||||
/// to set the function to.
|
||||
static inline void
|
||||
SubstAutoWithinFunctionReturnType(FunctionDecl *F,
|
||||
QualType TypeToReplaceAutoWith, Sema &S) {
|
||||
assert(!TypeToReplaceAutoWith->getContainedAutoType());
|
||||
QualType AutoResultType = F->getReturnType();
|
||||
assert(AutoResultType->getContainedAutoType());
|
||||
QualType DeducedResultType = S.SubstAutoType(AutoResultType,
|
||||
TypeToReplaceAutoWith);
|
||||
S.Context.adjustDeducedFunctionResultType(F, DeducedResultType);
|
||||
}
|
||||
|
||||
/// \brief Given a specialized conversion operator of a generic lambda
|
||||
/// create the corresponding specializations of the call operator and
|
||||
/// the static-invoker. If the return type of the call operator is auto,
|
||||
/// deduce its return type and check if that matches the
|
||||
/// return type of the destination function ptr.
|
||||
|
||||
static inline Sema::TemplateDeductionResult
|
||||
SpecializeCorrespondingLambdaCallOperatorAndInvoker(
|
||||
CXXConversionDecl *ConversionSpecialized,
|
||||
SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments,
|
||||
QualType ReturnTypeOfDestFunctionPtr,
|
||||
TemplateDeductionInfo &TDInfo,
|
||||
Sema &S) {
|
||||
|
||||
CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent();
|
||||
assert(LambdaClass && LambdaClass->isGenericLambda());
|
||||
|
||||
CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
|
||||
QualType CallOpResultType = CallOpGeneric->getReturnType();
|
||||
const bool GenericLambdaCallOperatorHasDeducedReturnType =
|
||||
CallOpResultType->getContainedAutoType();
|
||||
|
||||
FunctionTemplateDecl *CallOpTemplate =
|
||||
CallOpGeneric->getDescribedFunctionTemplate();
|
||||
|
||||
FunctionDecl *CallOpSpecialized = nullptr;
|
||||
// Use the deduced arguments of the conversion function, to specialize our
|
||||
// generic lambda's call operator.
|
||||
if (Sema::TemplateDeductionResult Result
|
||||
= S.FinishTemplateArgumentDeduction(CallOpTemplate,
|
||||
DeducedArguments,
|
||||
0, CallOpSpecialized, TDInfo))
|
||||
return Result;
|
||||
|
||||
// If we need to deduce the return type, do so (instantiates the callop).
|
||||
if (GenericLambdaCallOperatorHasDeducedReturnType &&
|
||||
CallOpSpecialized->getReturnType()->isUndeducedType())
|
||||
S.DeduceReturnType(CallOpSpecialized,
|
||||
CallOpSpecialized->getPointOfInstantiation(),
|
||||
/*Diagnose*/ true);
|
||||
|
||||
// Check to see if the return type of the destination ptr-to-function
|
||||
// matches the return type of the call operator.
|
||||
if (!S.Context.hasSameType(CallOpSpecialized->getReturnType(),
|
||||
ReturnTypeOfDestFunctionPtr))
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
// Since we have succeeded in matching the source and destination
|
||||
// ptr-to-functions (now including return type), and have successfully
|
||||
// specialized our corresponding call operator, we are ready to
|
||||
// specialize the static invoker with the deduced arguments of our
|
||||
// ptr-to-function.
|
||||
FunctionDecl *InvokerSpecialized = nullptr;
|
||||
FunctionTemplateDecl *InvokerTemplate = LambdaClass->
|
||||
getLambdaStaticInvoker()->getDescribedFunctionTemplate();
|
||||
|
||||
#ifndef NDEBUG
|
||||
Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result =
|
||||
#endif
|
||||
S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
|
||||
InvokerSpecialized, TDInfo);
|
||||
assert(Result == Sema::TDK_Success &&
|
||||
"If the call operator succeeded so should the invoker!");
|
||||
// Set the result type to match the corresponding call operator
|
||||
// specialization's result type.
|
||||
if (GenericLambdaCallOperatorHasDeducedReturnType &&
|
||||
InvokerSpecialized->getReturnType()->isUndeducedType()) {
|
||||
// Be sure to get the type to replace 'auto' with and not
|
||||
// the full result type of the call op specialization
|
||||
// to substitute into the 'auto' of the invoker and conversion
|
||||
// function.
|
||||
// For e.g.
|
||||
// int* (*fp)(int*) = [](auto* a) -> auto* { return a; };
|
||||
// We don't want to subst 'int*' into 'auto' to get int**.
|
||||
|
||||
QualType TypeToReplaceAutoWith = CallOpSpecialized->getReturnType()
|
||||
->getContainedAutoType()
|
||||
->getDeducedType();
|
||||
SubstAutoWithinFunctionReturnType(InvokerSpecialized,
|
||||
TypeToReplaceAutoWith, S);
|
||||
SubstAutoWithinFunctionReturnType(ConversionSpecialized,
|
||||
TypeToReplaceAutoWith, S);
|
||||
}
|
||||
|
||||
// Ensure that static invoker doesn't have a const qualifier.
|
||||
// FIXME: When creating the InvokerTemplate in SemaLambda.cpp
|
||||
// do not use the CallOperator's TypeSourceInfo which allows
|
||||
// the const qualifier to leak through.
|
||||
const FunctionProtoType *InvokerFPT = InvokerSpecialized->
|
||||
getType().getTypePtr()->castAs<FunctionProtoType>();
|
||||
FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
|
||||
EPI.TypeQuals = 0;
|
||||
InvokerSpecialized->setType(S.Context.getFunctionType(
|
||||
InvokerFPT->getReturnType(), InvokerFPT->getParamTypes(), EPI));
|
||||
return Sema::TDK_Success;
|
||||
}
|
||||
/// \brief Deduce template arguments for a templated conversion
|
||||
/// function (C++ [temp.deduct.conv]) and, if successful, produce a
|
||||
/// conversion function template specialization.
|
||||
@ -4158,35 +4047,6 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
|
||||
= FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
|
||||
ConversionSpecialized, Info);
|
||||
Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
|
||||
|
||||
// If the conversion operator is being invoked on a lambda closure to convert
|
||||
// to a ptr-to-function, use the deduced arguments from the conversion
|
||||
// function to specialize the corresponding call operator.
|
||||
// e.g., int (*fp)(int) = [](auto a) { return a; };
|
||||
if (Result == TDK_Success && isLambdaConversionOperator(ConversionGeneric)) {
|
||||
|
||||
// Get the return type of the destination ptr-to-function we are converting
|
||||
// to. This is necessary for matching the lambda call operator's return
|
||||
// type to that of the destination ptr-to-function's return type.
|
||||
assert(A->isPointerType() &&
|
||||
"Can only convert from lambda to ptr-to-function");
|
||||
const FunctionType *ToFunType =
|
||||
A->getPointeeType().getTypePtr()->getAs<FunctionType>();
|
||||
const QualType DestFunctionPtrReturnType = ToFunType->getReturnType();
|
||||
|
||||
// Create the corresponding specializations of the call operator and
|
||||
// the static-invoker; and if the return type is auto,
|
||||
// deduce the return type and check if it matches the
|
||||
// DestFunctionPtrReturnType.
|
||||
// For instance:
|
||||
// auto L = [](auto a) { return f(a); };
|
||||
// int (*fp)(int) = L;
|
||||
// char (*fp2)(int) = L; <-- Not OK.
|
||||
|
||||
Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker(
|
||||
Specialization, Deduced, DestFunctionPtrReturnType,
|
||||
Info, *this);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -4536,6 +4396,43 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
|
||||
bool Diagnose) {
|
||||
assert(FD->getReturnType()->isUndeducedType());
|
||||
|
||||
// For a lambda's conversion operator, deduce any 'auto' or 'decltype(auto)'
|
||||
// within the return type from the call operator's type.
|
||||
if (isLambdaConversionOperator(FD)) {
|
||||
CXXRecordDecl *Lambda = cast<CXXMethodDecl>(FD)->getParent();
|
||||
FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
|
||||
|
||||
// For a generic lambda, instantiate the call operator if needed.
|
||||
if (auto *Args = FD->getTemplateSpecializationArgs()) {
|
||||
CallOp = InstantiateFunctionDeclaration(
|
||||
CallOp->getDescribedFunctionTemplate(), Args, Loc);
|
||||
if (!CallOp || CallOp->isInvalidDecl())
|
||||
return true;
|
||||
|
||||
// We might need to deduce the return type by instantiating the definition
|
||||
// of the operator() function.
|
||||
if (CallOp->getReturnType()->isUndeducedType())
|
||||
InstantiateFunctionDefinition(Loc, CallOp);
|
||||
}
|
||||
|
||||
if (CallOp->isInvalidDecl())
|
||||
return true;
|
||||
assert(!CallOp->getReturnType()->isUndeducedType() &&
|
||||
"failed to deduce lambda return type");
|
||||
|
||||
// Build the new return type from scratch.
|
||||
QualType RetType = getLambdaConversionFunctionResultType(
|
||||
CallOp->getType()->castAs<FunctionProtoType>());
|
||||
if (FD->getReturnType()->getAs<PointerType>())
|
||||
RetType = Context.getPointerType(RetType);
|
||||
else {
|
||||
assert(FD->getReturnType()->getAs<BlockPointerType>());
|
||||
RetType = Context.getBlockPointerType(RetType);
|
||||
}
|
||||
Context.adjustDeducedFunctionResultType(FD, RetType);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FD->getTemplateInstantiationPattern())
|
||||
InstantiateFunctionDefinition(Loc, FD);
|
||||
|
||||
|
@ -3729,6 +3729,30 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Instantiate (or find existing instantiation of) a function template with a
|
||||
/// given set of template arguments.
|
||||
///
|
||||
/// Usually this should not be used, and template argument deduction should be
|
||||
/// used in its place.
|
||||
FunctionDecl *
|
||||
Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
|
||||
const TemplateArgumentList *Args,
|
||||
SourceLocation Loc) {
|
||||
FunctionDecl *FD = FTD->getTemplatedDecl();
|
||||
|
||||
sema::TemplateDeductionInfo Info(Loc);
|
||||
InstantiatingTemplate Inst(
|
||||
*this, Loc, FTD, Args->asArray(),
|
||||
CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info);
|
||||
if (Inst.isInvalid())
|
||||
return nullptr;
|
||||
|
||||
ContextRAII SavedContext(*this, FD);
|
||||
MultiLevelTemplateArgumentList MArgs(*Args);
|
||||
|
||||
return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
|
||||
}
|
||||
|
||||
/// In the MS ABI, we need to instantiate default arguments of dllexported
|
||||
/// default constructors along with the constructor definition. This allows IR
|
||||
/// gen to emit a constructor closure which calls the default constructor with
|
||||
@ -3812,7 +3836,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
PendingInstantiations.push_back(
|
||||
std::make_pair(Function, PointOfInstantiation));
|
||||
} else if (TSK == TSK_ImplicitInstantiation) {
|
||||
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
|
||||
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
|
||||
!getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
|
||||
Diag(PointOfInstantiation, diag::warn_func_template_missing)
|
||||
<< Function;
|
||||
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
|
||||
@ -4347,7 +4372,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
||||
std::make_pair(Var, PointOfInstantiation));
|
||||
} else if (TSK == TSK_ImplicitInstantiation) {
|
||||
// Warn about missing definition at the end of translation unit.
|
||||
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
|
||||
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
|
||||
!getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
|
||||
Diag(PointOfInstantiation, diag::warn_var_template_missing)
|
||||
<< Var;
|
||||
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
|
||||
|
@ -47,7 +47,7 @@ enum TypeDiagSelector {
|
||||
/// isOmittedBlockReturnType - Return true if this declarator is missing a
|
||||
/// return type because this is a omitted return type on a block literal.
|
||||
static bool isOmittedBlockReturnType(const Declarator &D) {
|
||||
if (D.getContext() != Declarator::BlockLiteralContext ||
|
||||
if (D.getContext() != DeclaratorContext::BlockLiteralContext ||
|
||||
D.getDeclSpec().hasTypeSpecifier())
|
||||
return false;
|
||||
|
||||
@ -1291,11 +1291,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
||||
// The declspec is always missing in a lambda expr context; it is either
|
||||
// specified with a trailing return type or inferred.
|
||||
if (S.getLangOpts().CPlusPlus14 &&
|
||||
declarator.getContext() == Declarator::LambdaExprContext) {
|
||||
declarator.getContext() == DeclaratorContext::LambdaExprContext) {
|
||||
// In C++1y, a lambda's implicit return type is 'auto'.
|
||||
Result = Context.getAutoDeductType();
|
||||
break;
|
||||
} else if (declarator.getContext() == Declarator::LambdaExprContext ||
|
||||
} else if (declarator.getContext() ==
|
||||
DeclaratorContext::LambdaExprContext ||
|
||||
checkOmittedBlockReturnType(S, declarator,
|
||||
Context.DependentTy)) {
|
||||
Result = Context.DependentTy;
|
||||
@ -1572,7 +1573,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
||||
|
||||
// Before we process any type attributes, synthesize a block literal
|
||||
// function declarator if necessary.
|
||||
if (declarator.getContext() == Declarator::BlockLiteralContext)
|
||||
if (declarator.getContext() == DeclaratorContext::BlockLiteralContext)
|
||||
maybeSynthesizeBlockSignature(state, Result);
|
||||
|
||||
// Apply any type attributes from the decl spec. This may cause the
|
||||
@ -2702,7 +2703,7 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
|
||||
// If the qualifiers come from a conversion function type, don't diagnose
|
||||
// them -- they're not necessarily redundant, since such a conversion
|
||||
// operator can be explicitly called as "x.operator const int()".
|
||||
if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId)
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
|
||||
return;
|
||||
|
||||
// Just parens all the way out to the decl specifiers. Diagnose any qualifiers
|
||||
@ -2728,11 +2729,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||
TagDecl *OwnedTagDecl = nullptr;
|
||||
|
||||
switch (D.getName().getKind()) {
|
||||
case UnqualifiedId::IK_ImplicitSelfParam:
|
||||
case UnqualifiedId::IK_OperatorFunctionId:
|
||||
case UnqualifiedId::IK_Identifier:
|
||||
case UnqualifiedId::IK_LiteralOperatorId:
|
||||
case UnqualifiedId::IK_TemplateId:
|
||||
case UnqualifiedIdKind::IK_ImplicitSelfParam:
|
||||
case UnqualifiedIdKind::IK_OperatorFunctionId:
|
||||
case UnqualifiedIdKind::IK_Identifier:
|
||||
case UnqualifiedIdKind::IK_LiteralOperatorId:
|
||||
case UnqualifiedIdKind::IK_TemplateId:
|
||||
T = ConvertDeclSpecToType(state);
|
||||
|
||||
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
|
||||
@ -2742,9 +2743,9 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||
}
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_ConstructorName:
|
||||
case UnqualifiedId::IK_ConstructorTemplateId:
|
||||
case UnqualifiedId::IK_DestructorName:
|
||||
case UnqualifiedIdKind::IK_ConstructorName:
|
||||
case UnqualifiedIdKind::IK_ConstructorTemplateId:
|
||||
case UnqualifiedIdKind::IK_DestructorName:
|
||||
// Constructors and destructors don't have return types. Use
|
||||
// "void" instead.
|
||||
T = SemaRef.Context.VoidTy;
|
||||
@ -2752,13 +2753,13 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||
D.getDeclSpec().getAttributes().getList());
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_DeductionGuideName:
|
||||
case UnqualifiedIdKind::IK_DeductionGuideName:
|
||||
// Deduction guides have a trailing return type and no type in their
|
||||
// decl-specifier sequence. Use a placeholder return type for now.
|
||||
T = SemaRef.Context.DependentTy;
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_ConversionFunctionId:
|
||||
case UnqualifiedIdKind::IK_ConversionFunctionId:
|
||||
// The result type of a conversion function is the type that it
|
||||
// converts to.
|
||||
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
|
||||
@ -2780,16 +2781,16 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||
(Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
|
||||
|
||||
switch (D.getContext()) {
|
||||
case Declarator::LambdaExprContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
// Declared return type of a lambda-declarator is implicit and is always
|
||||
// 'auto'.
|
||||
break;
|
||||
case Declarator::ObjCParameterContext:
|
||||
case Declarator::ObjCResultContext:
|
||||
case Declarator::PrototypeContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
Error = 0;
|
||||
break;
|
||||
case Declarator::LambdaExprParameterContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
// In C++14, generic lambdas allow 'auto' in their parameters.
|
||||
if (!SemaRef.getLangOpts().CPlusPlus14 ||
|
||||
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
|
||||
@ -2821,7 +2822,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||
T, QualType(CorrespondingTemplateParam->getTypeForDecl(), 0));
|
||||
}
|
||||
break;
|
||||
case Declarator::MemberContext: {
|
||||
case DeclaratorContext::MemberContext: {
|
||||
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
|
||||
D.isFunctionDeclarator())
|
||||
break;
|
||||
@ -2837,57 +2838,57 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||
Error = 20; // Friend type
|
||||
break;
|
||||
}
|
||||
case Declarator::CXXCatchContext:
|
||||
case Declarator::ObjCCatchContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
Error = 7; // Exception declaration
|
||||
break;
|
||||
case Declarator::TemplateParamContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
if (isa<DeducedTemplateSpecializationType>(Deduced))
|
||||
Error = 19; // Template parameter
|
||||
else if (!SemaRef.getLangOpts().CPlusPlus17)
|
||||
Error = 8; // Template parameter (until C++17)
|
||||
break;
|
||||
case Declarator::BlockLiteralContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
Error = 9; // Block literal
|
||||
break;
|
||||
case Declarator::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
Error = 10; // Template type argument
|
||||
break;
|
||||
case Declarator::AliasDeclContext:
|
||||
case Declarator::AliasTemplateContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
Error = 12; // Type alias
|
||||
break;
|
||||
case Declarator::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
|
||||
Error = 13; // Function return type
|
||||
break;
|
||||
case Declarator::ConversionIdContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
|
||||
Error = 14; // conversion-type-id
|
||||
break;
|
||||
case Declarator::FunctionalCastContext:
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
if (isa<DeducedTemplateSpecializationType>(Deduced))
|
||||
break;
|
||||
LLVM_FALLTHROUGH;
|
||||
case Declarator::TypeNameContext:
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
Error = 15; // Generic
|
||||
break;
|
||||
case Declarator::FileContext:
|
||||
case Declarator::BlockContext:
|
||||
case Declarator::ForContext:
|
||||
case Declarator::InitStmtContext:
|
||||
case Declarator::ConditionContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
// FIXME: P0091R3 (erroneously) does not permit class template argument
|
||||
// deduction in conditions, for-init-statements, and other declarations
|
||||
// that are not simple-declarations.
|
||||
break;
|
||||
case Declarator::CXXNewContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
// FIXME: P0091R3 does not permit class template argument deduction here,
|
||||
// but we follow GCC and allow it anyway.
|
||||
if (!IsCXXAutoType && !isa<DeducedTemplateSpecializationType>(Deduced))
|
||||
Error = 17; // 'new' type
|
||||
break;
|
||||
case Declarator::KNRTypeListContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
Error = 18; // K&R function parameter
|
||||
break;
|
||||
}
|
||||
@ -2916,7 +2917,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||
}
|
||||
|
||||
SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
|
||||
if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId)
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
|
||||
AutoRange = D.getName().getSourceRange();
|
||||
|
||||
if (Error != -1) {
|
||||
@ -2959,47 +2960,47 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||
// or enumeration in a type-specifier-seq.
|
||||
unsigned DiagID = 0;
|
||||
switch (D.getContext()) {
|
||||
case Declarator::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
// Class and enumeration definitions are syntactically not allowed in
|
||||
// trailing return types.
|
||||
llvm_unreachable("parser should not have allowed this");
|
||||
break;
|
||||
case Declarator::FileContext:
|
||||
case Declarator::MemberContext:
|
||||
case Declarator::BlockContext:
|
||||
case Declarator::ForContext:
|
||||
case Declarator::InitStmtContext:
|
||||
case Declarator::BlockLiteralContext:
|
||||
case Declarator::LambdaExprContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
// C++11 [dcl.type]p3:
|
||||
// A type-specifier-seq shall not define a class or enumeration unless
|
||||
// it appears in the type-id of an alias-declaration (7.1.3) that is not
|
||||
// the declaration of a template-declaration.
|
||||
case Declarator::AliasDeclContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
break;
|
||||
case Declarator::AliasTemplateContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
DiagID = diag::err_type_defined_in_alias_template;
|
||||
break;
|
||||
case Declarator::TypeNameContext:
|
||||
case Declarator::FunctionalCastContext:
|
||||
case Declarator::ConversionIdContext:
|
||||
case Declarator::TemplateParamContext:
|
||||
case Declarator::CXXNewContext:
|
||||
case Declarator::CXXCatchContext:
|
||||
case Declarator::ObjCCatchContext:
|
||||
case Declarator::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
DiagID = diag::err_type_defined_in_type_specifier;
|
||||
break;
|
||||
case Declarator::PrototypeContext:
|
||||
case Declarator::LambdaExprParameterContext:
|
||||
case Declarator::ObjCParameterContext:
|
||||
case Declarator::ObjCResultContext:
|
||||
case Declarator::KNRTypeListContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
// C++ [dcl.fct]p6:
|
||||
// Types shall not be defined in return or parameter types.
|
||||
DiagID = diag::err_type_defined_in_param_type;
|
||||
break;
|
||||
case Declarator::ConditionContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
// C++ 6.4p2:
|
||||
// The type-specifier-seq shall not contain typedef and shall not declare
|
||||
// a new class or enumeration.
|
||||
@ -3048,7 +3049,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
|
||||
|
||||
// Inside a condition, a direct initializer is not permitted. We allow one to
|
||||
// be parsed in order to give better diagnostics in condition parsing.
|
||||
if (D.getContext() == Declarator::ConditionContext)
|
||||
if (D.getContext() == DeclaratorContext::ConditionContext)
|
||||
return;
|
||||
|
||||
SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
|
||||
@ -3164,7 +3165,7 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
|
||||
|
||||
case DeclaratorChunk::Function:
|
||||
// In a new-type-id, function chunks require parentheses.
|
||||
if (D.getContext() == Declarator::CXXNewContext)
|
||||
if (D.getContext() == DeclaratorContext::CXXNewContext)
|
||||
return;
|
||||
// FIXME: "A(f())" deserves a vexing-parse warning, not just a
|
||||
// redundant-parens warning, but we don't know whether the function
|
||||
@ -3282,7 +3283,7 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
|
||||
// in a member pointer.
|
||||
IsCXXInstanceMethod =
|
||||
D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
|
||||
} else if (D.getContext() == Declarator::LambdaExprContext) {
|
||||
} else if (D.getContext() == DeclaratorContext::LambdaExprContext) {
|
||||
// This can only be a call operator for a lambda, which is an instance
|
||||
// method.
|
||||
IsCXXInstanceMethod = true;
|
||||
@ -3779,8 +3780,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// Does this declaration declare a typedef-name?
|
||||
bool IsTypedefName =
|
||||
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
|
||||
D.getContext() == Declarator::AliasDeclContext ||
|
||||
D.getContext() == Declarator::AliasTemplateContext;
|
||||
D.getContext() == DeclaratorContext::AliasDeclContext ||
|
||||
D.getContext() == DeclaratorContext::AliasTemplateContext;
|
||||
|
||||
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
|
||||
bool IsQualifiedFunction = T->isFunctionProtoType() &&
|
||||
@ -3909,14 +3910,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
} else {
|
||||
bool isFunctionOrMethod = false;
|
||||
switch (auto context = state.getDeclarator().getContext()) {
|
||||
case Declarator::ObjCParameterContext:
|
||||
case Declarator::ObjCResultContext:
|
||||
case Declarator::PrototypeContext:
|
||||
case Declarator::TrailingReturnContext:
|
||||
case DeclaratorContext::ObjCParameterContext:
|
||||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
isFunctionOrMethod = true;
|
||||
LLVM_FALLTHROUGH;
|
||||
|
||||
case Declarator::MemberContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
|
||||
complainAboutMissingNullability = CAMN_No;
|
||||
break;
|
||||
@ -3930,8 +3931,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
|
||||
LLVM_FALLTHROUGH;
|
||||
|
||||
case Declarator::FileContext:
|
||||
case Declarator::KNRTypeListContext: {
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::KNRTypeListContext: {
|
||||
complainAboutMissingNullability = CAMN_Yes;
|
||||
|
||||
// Nullability inference depends on the type and declarator.
|
||||
@ -3947,8 +3948,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
if (inAssumeNonNullRegion) {
|
||||
complainAboutInferringWithinChunk = wrappingKind;
|
||||
inferNullability = NullabilityKind::NonNull;
|
||||
inferNullabilityCS = (context == Declarator::ObjCParameterContext ||
|
||||
context == Declarator::ObjCResultContext);
|
||||
inferNullabilityCS =
|
||||
(context == DeclaratorContext::ObjCParameterContext ||
|
||||
context == DeclaratorContext::ObjCResultContext);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3988,26 +3990,26 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
break;
|
||||
}
|
||||
|
||||
case Declarator::ConversionIdContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
complainAboutMissingNullability = CAMN_Yes;
|
||||
break;
|
||||
|
||||
case Declarator::AliasDeclContext:
|
||||
case Declarator::AliasTemplateContext:
|
||||
case Declarator::BlockContext:
|
||||
case Declarator::BlockLiteralContext:
|
||||
case Declarator::ConditionContext:
|
||||
case Declarator::CXXCatchContext:
|
||||
case Declarator::CXXNewContext:
|
||||
case Declarator::ForContext:
|
||||
case Declarator::InitStmtContext:
|
||||
case Declarator::LambdaExprContext:
|
||||
case Declarator::LambdaExprParameterContext:
|
||||
case Declarator::ObjCCatchContext:
|
||||
case Declarator::TemplateParamContext:
|
||||
case Declarator::TemplateTypeArgContext:
|
||||
case Declarator::TypeNameContext:
|
||||
case Declarator::FunctionalCastContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
// Don't infer in these contexts.
|
||||
break;
|
||||
}
|
||||
@ -4243,7 +4245,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// array type, ...
|
||||
if (ASM == ArrayType::Static || ATI.TypeQuals) {
|
||||
if (!(D.isPrototypeContext() ||
|
||||
D.getContext() == Declarator::KNRTypeListContext)) {
|
||||
D.getContext() == DeclaratorContext::KNRTypeListContext)) {
|
||||
S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) <<
|
||||
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
|
||||
// Remove the 'static' and the type qualifiers.
|
||||
@ -4267,7 +4269,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
const AutoType *AT = T->getContainedAutoType();
|
||||
// Allow arrays of auto if we are a generic lambda parameter.
|
||||
// i.e. [](auto (&array)[5]) { return array[0]; }; OK
|
||||
if (AT && D.getContext() != Declarator::LambdaExprParameterContext) {
|
||||
if (AT &&
|
||||
D.getContext() != DeclaratorContext::LambdaExprParameterContext) {
|
||||
// We've already diagnosed this for decltype(auto).
|
||||
if (!AT->isDecltypeAuto())
|
||||
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
|
||||
@ -4319,14 +4322,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
<< T << D.getSourceRange();
|
||||
D.setInvalidType(true);
|
||||
} else if (D.getName().getKind() ==
|
||||
UnqualifiedId::IK_DeductionGuideName) {
|
||||
UnqualifiedIdKind::IK_DeductionGuideName) {
|
||||
if (T != Context.DependentTy) {
|
||||
S.Diag(D.getDeclSpec().getLocStart(),
|
||||
diag::err_deduction_guide_with_complex_decl)
|
||||
<< D.getSourceRange();
|
||||
D.setInvalidType(true);
|
||||
}
|
||||
} else if (D.getContext() != Declarator::LambdaExprContext &&
|
||||
} else if (D.getContext() != DeclaratorContext::LambdaExprContext &&
|
||||
(T.hasQualifiers() || !isa<AutoType>(T) ||
|
||||
cast<AutoType>(T)->getKeyword() !=
|
||||
AutoTypeKeyword::Auto)) {
|
||||
@ -4347,12 +4350,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// C99 6.7.5.3p1: The return type may not be a function or array type.
|
||||
// For conversion functions, we'll diagnose this particular error later.
|
||||
if (!D.isInvalidType() && (T->isArrayType() || T->isFunctionType()) &&
|
||||
(D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
|
||||
(D.getName().getKind() !=
|
||||
UnqualifiedIdKind::IK_ConversionFunctionId)) {
|
||||
unsigned diagID = diag::err_func_returning_array_function;
|
||||
// Last processing chunk in block context means this function chunk
|
||||
// represents the block.
|
||||
if (chunkIndex == 0 &&
|
||||
D.getContext() == Declarator::BlockLiteralContext)
|
||||
D.getContext() == DeclaratorContext::BlockLiteralContext)
|
||||
diagID = diag::err_block_returning_array_function;
|
||||
S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
|
||||
T = Context.IntTy;
|
||||
@ -4490,8 +4494,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus17)
|
||||
S.Diag(FTI.getExceptionSpecLocBeg(),
|
||||
diag::err_exception_spec_in_typedef)
|
||||
<< (D.getContext() == Declarator::AliasDeclContext ||
|
||||
D.getContext() == Declarator::AliasTemplateContext);
|
||||
<< (D.getContext() == DeclaratorContext::AliasDeclContext ||
|
||||
D.getContext() == DeclaratorContext::AliasTemplateContext);
|
||||
|
||||
// If we see "T var();" or "T var(T());" at block scope, it is probably
|
||||
// an attempt to initialize a variable, not a function declaration.
|
||||
@ -4763,7 +4767,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
break;
|
||||
case DeclaratorChunk::Function: {
|
||||
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
|
||||
if (FTI.NumParams == 0)
|
||||
if (FTI.NumParams == 0 && !FTI.isVariadic)
|
||||
S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
|
||||
<< IsBlock
|
||||
<< FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");
|
||||
@ -4791,11 +4795,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// Core issue 547 also allows cv-qualifiers on function types that are
|
||||
// top-level template type arguments.
|
||||
enum { NonMember, Member, DeductionGuide } Kind = NonMember;
|
||||
if (D.getName().getKind() == UnqualifiedId::IK_DeductionGuideName)
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName)
|
||||
Kind = DeductionGuide;
|
||||
else if (!D.getCXXScopeSpec().isSet()) {
|
||||
if ((D.getContext() == Declarator::MemberContext ||
|
||||
D.getContext() == Declarator::LambdaExprContext) &&
|
||||
if ((D.getContext() == DeclaratorContext::MemberContext ||
|
||||
D.getContext() == DeclaratorContext::LambdaExprContext) &&
|
||||
!D.getDeclSpec().isFriendSpecified())
|
||||
Kind = Member;
|
||||
} else {
|
||||
@ -4824,7 +4828,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
!(Kind == Member &&
|
||||
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
|
||||
!IsTypedefName &&
|
||||
D.getContext() != Declarator::TemplateTypeArgContext) {
|
||||
D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
|
||||
SourceLocation Loc = D.getLocStart();
|
||||
SourceRange RemovalRange;
|
||||
unsigned I;
|
||||
@ -4890,8 +4894,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// only be used in a parameter-declaration. Such a parameter-declaration
|
||||
// is a parameter pack (14.5.3). [...]
|
||||
switch (D.getContext()) {
|
||||
case Declarator::PrototypeContext:
|
||||
case Declarator::LambdaExprParameterContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::LambdaExprParameterContext:
|
||||
// C++0x [dcl.fct]p13:
|
||||
// [...] When it is part of a parameter-declaration-clause, the
|
||||
// parameter pack is a function parameter pack (14.5.3). The type T
|
||||
@ -4910,7 +4914,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
T = Context.getPackExpansionType(T, None);
|
||||
}
|
||||
break;
|
||||
case Declarator::TemplateParamContext:
|
||||
case DeclaratorContext::TemplateParamContext:
|
||||
// C++0x [temp.param]p15:
|
||||
// If a template-parameter is a [...] is a parameter-declaration that
|
||||
// declares a parameter pack (8.3.5), then the template-parameter is a
|
||||
@ -4928,27 +4932,29 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
: diag::ext_variadic_templates);
|
||||
break;
|
||||
|
||||
case Declarator::FileContext:
|
||||
case Declarator::KNRTypeListContext:
|
||||
case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
|
||||
case Declarator::ObjCResultContext: // FIXME: special diagnostic here?
|
||||
case Declarator::TypeNameContext:
|
||||
case Declarator::FunctionalCastContext:
|
||||
case Declarator::CXXNewContext:
|
||||
case Declarator::AliasDeclContext:
|
||||
case Declarator::AliasTemplateContext:
|
||||
case Declarator::MemberContext:
|
||||
case Declarator::BlockContext:
|
||||
case Declarator::ForContext:
|
||||
case Declarator::InitStmtContext:
|
||||
case Declarator::ConditionContext:
|
||||
case Declarator::CXXCatchContext:
|
||||
case Declarator::ObjCCatchContext:
|
||||
case Declarator::BlockLiteralContext:
|
||||
case Declarator::LambdaExprContext:
|
||||
case Declarator::ConversionIdContext:
|
||||
case Declarator::TrailingReturnContext:
|
||||
case Declarator::TemplateTypeArgContext:
|
||||
case DeclaratorContext::FileContext:
|
||||
case DeclaratorContext::KNRTypeListContext:
|
||||
case DeclaratorContext::ObjCParameterContext: // FIXME: special diagnostic
|
||||
// here?
|
||||
case DeclaratorContext::ObjCResultContext: // FIXME: special diagnostic
|
||||
// here?
|
||||
case DeclaratorContext::TypeNameContext:
|
||||
case DeclaratorContext::FunctionalCastContext:
|
||||
case DeclaratorContext::CXXNewContext:
|
||||
case DeclaratorContext::AliasDeclContext:
|
||||
case DeclaratorContext::AliasTemplateContext:
|
||||
case DeclaratorContext::MemberContext:
|
||||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::ConditionContext:
|
||||
case DeclaratorContext::CXXCatchContext:
|
||||
case DeclaratorContext::ObjCCatchContext:
|
||||
case DeclaratorContext::BlockLiteralContext:
|
||||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
// FIXME: We may want to allow parameter packs in block-literal contexts
|
||||
// in the future.
|
||||
S.Diag(D.getEllipsisLoc(),
|
||||
@ -5637,9 +5643,9 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
|
||||
// to apply them to the actual parameter declaration.
|
||||
// Likewise, we don't want to do this for alias declarations, because
|
||||
// we are actually going to build a declaration from this eventually.
|
||||
if (D.getContext() != Declarator::ObjCParameterContext &&
|
||||
D.getContext() != Declarator::AliasDeclContext &&
|
||||
D.getContext() != Declarator::AliasTemplateContext)
|
||||
if (D.getContext() != DeclaratorContext::ObjCParameterContext &&
|
||||
D.getContext() != DeclaratorContext::AliasDeclContext &&
|
||||
D.getContext() != DeclaratorContext::AliasTemplateContext)
|
||||
checkUnusedDeclAttributes(D);
|
||||
|
||||
if (getLangOpts().CPlusPlus) {
|
||||
@ -7066,7 +7072,7 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
|
||||
IsFuncReturnType || IsFuncType ||
|
||||
// Do not deduce addr space for member types of struct, except the pointee
|
||||
// type of a pointer member type.
|
||||
(D.getContext() == Declarator::MemberContext && !IsPointee) ||
|
||||
(D.getContext() == DeclaratorContext::MemberContext && !IsPointee) ||
|
||||
// Do not deduce addr space for types used to define a typedef and the
|
||||
// typedef itself, except the pointee type of a pointer type which is used
|
||||
// to define the typedef.
|
||||
@ -7098,7 +7104,7 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
|
||||
if (IsPointee) {
|
||||
ImpAddr = LangAS::opencl_generic;
|
||||
} else {
|
||||
if (D.getContext() == Declarator::FileContext) {
|
||||
if (D.getContext() == DeclaratorContext::FileContext) {
|
||||
ImpAddr = LangAS::opencl_global;
|
||||
} else {
|
||||
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
|
||||
|
@ -229,7 +229,6 @@ adjustCallLocations(PathPieces &Pieces,
|
||||
PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(I->get());
|
||||
|
||||
if (!Call) {
|
||||
assert((*I)->getLocation().asLocation().isValid());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s
|
||||
// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s
|
||||
// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s -o %t.report
|
||||
// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s -o %t.report
|
||||
|
||||
// We do NOT model libcxx03 implementation, but the analyzer should still
|
||||
// not crash.
|
||||
// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s
|
||||
// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s
|
||||
// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s -o %t.report
|
||||
// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s -o %t.report
|
||||
// RUN: rm -rf %t.report
|
||||
|
||||
void clang_analyzer_eval(bool);
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
template<typename T> T &lvalue();
|
||||
template<typename T> T &&xvalue();
|
||||
@ -20,6 +19,18 @@ struct X0 {
|
||||
|
||||
void g();
|
||||
|
||||
void c() const; // expected-note {{'c' declared here}}
|
||||
void v() volatile; // expected-note {{'v' declared here}}
|
||||
void r() __restrict__; // expected-note {{'r' declared here}}
|
||||
void cr() const __restrict__; // expected-note {{'cr' declared here}}
|
||||
void cv() const volatile;
|
||||
void vr() volatile __restrict__; // expected-note {{'vr' declared here}}
|
||||
void cvr() const volatile __restrict__;
|
||||
|
||||
void lvalue() &; // expected-note 2 {{'lvalue' declared here}}
|
||||
void const_lvalue() const&;
|
||||
void rvalue() &&; // expected-note {{'rvalue' declared here}}
|
||||
|
||||
int &operator+(const X0&) &;
|
||||
float &operator+(const X0&) &&;
|
||||
|
||||
@ -32,7 +43,7 @@ struct X0 {
|
||||
float &h2() const&&;
|
||||
};
|
||||
|
||||
void X0::g() {
|
||||
void X0::g() { // expected-note {{'g' declared here}}
|
||||
int &ir1 = f();
|
||||
int &ir2 = X0::f();
|
||||
}
|
||||
@ -69,3 +80,26 @@ void test_ref_qualifier_overloading() {
|
||||
float &fr3 = xvalue<X0>().h2();
|
||||
float &fr4 = prvalue<X0>().h2();
|
||||
}
|
||||
|
||||
void test_diagnostics(const volatile X0 &__restrict__ cvr) {
|
||||
cvr.g(); // expected-error {{'this' argument to member function 'g' has type 'const volatile X0', but function is not marked const or volatile}}
|
||||
cvr.c(); // expected-error {{not marked volatile}}
|
||||
cvr.v(); // expected-error {{not marked const}}
|
||||
cvr.r(); // expected-error {{not marked const or volatile}}
|
||||
cvr.cr(); // expected-error {{not marked volatile}}
|
||||
cvr.cv();
|
||||
cvr.vr(); // expected-error {{not marked const}}
|
||||
cvr.cvr();
|
||||
|
||||
lvalue<X0>().lvalue();
|
||||
lvalue<X0>().const_lvalue();
|
||||
lvalue<X0>().rvalue(); // expected-error {{'this' argument to member function 'rvalue' is an lvalue, but function has rvalue ref-qualifier}}
|
||||
|
||||
xvalue<X0>().lvalue(); // expected-error {{'this' argument to member function 'lvalue' is an rvalue, but function has non-const lvalue ref-qualifier}}
|
||||
xvalue<X0>().const_lvalue();
|
||||
xvalue<X0>().rvalue();
|
||||
|
||||
prvalue<X0>().lvalue(); // expected-error {{'this' argument to member function 'lvalue' is an rvalue, but function has non-const lvalue ref-qualifier}}
|
||||
prvalue<X0>().const_lvalue();
|
||||
prvalue<X0>().rvalue();
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ template void h<A(&)[13], int>(A(&)[13]); // expected-note {{requested here}}
|
||||
template<typename T>
|
||||
void i(T t) {
|
||||
for (auto u : t) { // expected-error {{invalid range expression of type 'X::A *'; no viable 'begin' function available}} \
|
||||
expected-error {{member function 'begin' not viable}} \
|
||||
expected-error {{'this' argument to member function 'begin' has type 'const X::A', but function is not marked const}} \
|
||||
expected-note {{when looking up 'begin' function}}
|
||||
|
||||
}
|
||||
|
6
test/Driver/Inputs/config-1.cfg
Normal file
6
test/Driver/Inputs/config-1.cfg
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
# Empty lines and line started with # are ignored
|
||||
-Werror
|
||||
|
||||
# Language
|
||||
-std=c99
|
2
test/Driver/Inputs/config-2.cfg
Normal file
2
test/Driver/Inputs/config-2.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
# nested inclusion
|
||||
@config-3.cfg
|
2
test/Driver/Inputs/config-2a.cfg
Normal file
2
test/Driver/Inputs/config-2a.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
# nested inclusion
|
||||
@config/config-4.cfg
|
1
test/Driver/Inputs/config-3.cfg
Normal file
1
test/Driver/Inputs/config-3.cfg
Normal file
@ -0,0 +1 @@
|
||||
-Wundefined-func-template
|
2
test/Driver/Inputs/config-4.cfg
Normal file
2
test/Driver/Inputs/config-4.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
-L/usr/local/lib
|
||||
-stdlib=libc++
|
2
test/Driver/Inputs/config-5.cfg
Normal file
2
test/Driver/Inputs/config-5.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
--serialize-diagnostics diag.ser
|
||||
-target
|
1
test/Driver/Inputs/config-6.cfg
Normal file
1
test/Driver/Inputs/config-6.cfg
Normal file
@ -0,0 +1 @@
|
||||
--config config-5
|
1
test/Driver/Inputs/config/config-4.cfg
Normal file
1
test/Driver/Inputs/config/config-4.cfg
Normal file
@ -0,0 +1 @@
|
||||
-isysroot /opt/data
|
1
test/Driver/Inputs/config/i386-qqq.cfg
Normal file
1
test/Driver/Inputs/config/i386-qqq.cfg
Normal file
@ -0,0 +1 @@
|
||||
-target i386
|
1
test/Driver/Inputs/config/i386-qqq3.cfg
Normal file
1
test/Driver/Inputs/config/i386-qqq3.cfg
Normal file
@ -0,0 +1 @@
|
||||
-target i383
|
1
test/Driver/Inputs/config/x86_64-qqq.cfg
Normal file
1
test/Driver/Inputs/config/x86_64-qqq.cfg
Normal file
@ -0,0 +1 @@
|
||||
-target x86_64
|
1
test/Driver/Inputs/config/x86_64-qqq2.cfg
Normal file
1
test/Driver/Inputs/config/x86_64-qqq2.cfg
Normal file
@ -0,0 +1 @@
|
||||
-target x86_64
|
1
test/Driver/Inputs/config/x86_64.cfg
Normal file
1
test/Driver/Inputs/config/x86_64.cfg
Normal file
@ -0,0 +1 @@
|
||||
-target x86_64
|
1
test/Driver/Inputs/config2/config-4.cfg
Normal file
1
test/Driver/Inputs/config2/config-4.cfg
Normal file
@ -0,0 +1 @@
|
||||
-Wall
|
1
test/Driver/Inputs/config2/i386.cfg
Normal file
1
test/Driver/Inputs/config2/i386.cfg
Normal file
@ -0,0 +1 @@
|
||||
-target i386
|
54
test/Driver/config-file-errs.c
Normal file
54
test/Driver/config-file-errs.c
Normal file
@ -0,0 +1,54 @@
|
||||
//--- No more than one '--config' may be specified.
|
||||
//
|
||||
// RUN: not %clang --config 1.cfg --config 2.cfg 2>&1 | FileCheck %s -check-prefix CHECK-DUPLICATE
|
||||
// CHECK-DUPLICATE: no more than one option '--config' is allowed
|
||||
|
||||
|
||||
//--- '--config' must be followed by config file name.
|
||||
//
|
||||
// RUN: not %clang --config 2>&1 | FileCheck %s -check-prefix CHECK-MISSING-FILE
|
||||
// CHECK-MISSING-FILE: argument to '--config' is missing (expected 1 value)
|
||||
|
||||
|
||||
//--- '--config' must not be found in config files.
|
||||
//
|
||||
// RUN: not %clang --config %S/Inputs/config-6.cfg 2>&1 | FileCheck %s -check-prefix CHECK-NESTED
|
||||
// CHECK-NESTED: option '--config' is not allowed inside configuration file
|
||||
|
||||
|
||||
//--- Argument of '--config' must be existing file, if it is specified by path.
|
||||
//
|
||||
// RUN: not %clang --config somewhere/nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NONEXISTENT
|
||||
// CHECK-NONEXISTENT: configuration file '{{.*}}somewhere/nonexistent-config-file' does not exist
|
||||
|
||||
|
||||
//--- Argument of '--config' must exist somewhere in well-known directories, if it is specified by bare name.
|
||||
//
|
||||
// RUN: not %clang --config-system-dir= --config-user-dir= --config nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NOTFOUND0
|
||||
// CHECK-NOTFOUND0: configuration file 'nonexistent-config-file.cfg' cannot be found
|
||||
// CHECK-NOTFOUND0-NEXT: was searched for in the directory:
|
||||
// CHECK-NOTFOUND0-NOT: was searched for in the directory:
|
||||
//
|
||||
// RUN: not %clang --config-system-dir= --config-user-dir=%S/Inputs/config2 --config nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NOTFOUND1
|
||||
// CHECK-NOTFOUND1: configuration file 'nonexistent-config-file.cfg' cannot be found
|
||||
// CHECK-NOTFOUND1-NEXT: was searched for in the directory: {{.*}}/Inputs/config2
|
||||
// CHECK-NOTFOUND1-NEXT: was searched for in the directory:
|
||||
// CHECK-NOTFOUND1-NOT: was searched for in the directory:
|
||||
//
|
||||
// RUN: not %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NOTFOUND2
|
||||
// CHECK-NOTFOUND2: configuration file 'nonexistent-config-file.cfg' cannot be found
|
||||
// CHECK-NOTFOUND2-NEXT: was searched for in the directory: {{.*}}/Inputs/config
|
||||
// CHECK-NOTFOUND2-NEXT: was searched for in the directory:
|
||||
// CHECK-NOTFOUND2-NOT: was searched for in the directory:
|
||||
//
|
||||
// RUN: not %clang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 --config nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NOTFOUND3
|
||||
// CHECK-NOTFOUND3: configuration file 'nonexistent-config-file.cfg' cannot be found
|
||||
// CHECK-NOTFOUND3-NEXT: was searched for in the directory: {{.*}}/Inputs/config2
|
||||
// CHECK-NOTFOUND3-NEXT: was searched for in the directory: {{.*}}/Inputs/config
|
||||
// CHECK-NOTFOUND3-NEXT: was searched for in the directory:
|
||||
|
||||
|
||||
//--- Argument in config file cannot cross the file boundary
|
||||
//
|
||||
// RUN: not %clang --config %S/Inputs/config-5.cfg x86_64-unknown-linux-gnu -c %s 2>&1 | FileCheck %s -check-prefix CHECK-CROSS
|
||||
// CHECK-CROSS: error: argument to '-target' is missing
|
72
test/Driver/config-file.c
Normal file
72
test/Driver/config-file.c
Normal file
@ -0,0 +1,72 @@
|
||||
//--- Config file search directories
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-DIRS
|
||||
// CHECK-DIRS: System configuration file directory: {{.*}}/Inputs/config
|
||||
// CHECK-DIRS: User configuration file directory: {{.*}}/Inputs/config2
|
||||
|
||||
|
||||
//--- Config file (full path) in output of -###
|
||||
//
|
||||
// RUN: %clang --config %S/Inputs/config-1.cfg -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-HHH
|
||||
// CHECK-HHH: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
|
||||
// CHECK-HHH: -Werror
|
||||
// CHECK-HHH: -std=c99
|
||||
|
||||
|
||||
//--- Config file (full path) in output of -v
|
||||
//
|
||||
// RUN: %clang --config %S/Inputs/config-1.cfg -c %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-V
|
||||
// CHECK-V: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
|
||||
// CHECK-V: -Werror
|
||||
// CHECK-V: -std=c99
|
||||
|
||||
|
||||
//--- Config file in output of -###
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-1.cfg -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-HHH2
|
||||
// CHECK-HHH2: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
|
||||
// CHECK-HHH2: -Werror
|
||||
// CHECK-HHH2: -std=c99
|
||||
|
||||
|
||||
//--- Config file in output of -v
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-1.cfg -c %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-V2
|
||||
// CHECK-V2: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
|
||||
// CHECK-V2: -Werror
|
||||
// CHECK-V2: -std=c99
|
||||
|
||||
|
||||
//--- Nested config files
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-2.cfg -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED
|
||||
// CHECK-NESTED: Configuration file: {{.*}}Inputs{{.}}config-2.cfg
|
||||
// CHECK-NESTED: -Wundefined-func-template
|
||||
|
||||
// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-2.cfg -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED2
|
||||
// CHECK-NESTED2: Configuration file: {{.*}}Inputs{{.}}config-2.cfg
|
||||
// CHECK-NESTED2: -Wundefined-func-template
|
||||
|
||||
|
||||
// RUN: %clang --config %S/Inputs/config-2a.cfg -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTEDa
|
||||
// CHECK-NESTEDa: Configuration file: {{.*}}Inputs{{.}}config-2a.cfg
|
||||
// CHECK-NESTEDa: -isysroot
|
||||
// CHECK-NESTEDa-SAME: /opt/data
|
||||
|
||||
// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-2a.cfg -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED2a
|
||||
// CHECK-NESTED2a: Configuration file: {{.*}}Inputs{{.}}config-2a.cfg
|
||||
// CHECK-NESTED2a: -isysroot
|
||||
// CHECK-NESTED2a-SAME: /opt/data
|
||||
|
||||
|
||||
//--- Unused options in config file do not produce warnings
|
||||
//
|
||||
// RUN: %clang --config %S/Inputs/config-4.cfg -c %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-UNUSED
|
||||
// CHECK-UNUSED-NOT: argument unused during compilation:
|
||||
|
||||
|
||||
//--- User directory is searched first.
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 --config config-4 -c %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-PRECEDENCE
|
||||
// CHECK-PRECEDENCE: Configuration file: {{.*}}Inputs{{.}}config2{{.}}config-4.cfg
|
||||
// CHECK-PRECEDENCE: -Wall
|
51
test/Driver/config-file2.c
Normal file
51
test/Driver/config-file2.c
Normal file
@ -0,0 +1,51 @@
|
||||
// REQUIRES: x86-registered-target
|
||||
|
||||
//--- Invocation `clang --config x86_64-qqq -m32` loads `i386-qqq.cfg` if the latter exists.
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq -m32 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD
|
||||
// CHECK-RELOAD: Target: i386
|
||||
// CHECK-RELOAD: Configuration file: {{.*}}Inputs{{.}}config{{.}}i386-qqq.cfg
|
||||
|
||||
|
||||
//--- Invocation `clang --config x86_64-qqq2 -m32` loads `i386.cfg` if the latter exists in another search directory.
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 --config x86_64-qqq2 -m32 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1
|
||||
// CHECK-RELOAD1: Target: i386
|
||||
// CHECK-RELOAD1: Configuration file: {{.*}}Inputs{{.}}config2{{.}}i386.cfg
|
||||
|
||||
|
||||
//--- Invocation `clang --config x86_64-qqq2 -m32` loads `x86_64-qqq2.cfg` if `i386-qqq2.cfg` and `i386.cfg` do not exist.
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq2 -m32 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD2
|
||||
// note: target is overriden due to -m32
|
||||
// CHECK-RELOAD2: Target: i386
|
||||
// CHECK-RELOAD2: Configuration file: {{.*}}Inputs{{.}}config{{.}}x86_64-qqq2.cfg
|
||||
|
||||
|
||||
//--- Invocation `clang --config i386-qqq3 -m64` loads `x86_64.cfg` if `x86_64-qqq3.cfg` does not exist.
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config i386-qqq3 -m64 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD3
|
||||
// CHECK-RELOAD3: Target: x86_64
|
||||
// CHECK-RELOAD3: Configuration file: {{.*}}Inputs{{.}}config{{.}}x86_64.cfg
|
||||
|
||||
|
||||
//--- Invocation `clang --config x86_64-qqq -target i386` loads `i386-qqq.cfg` if the latter exists.
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq -target i386 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD4
|
||||
// CHECK-RELOAD4: Target: i386
|
||||
// CHECK-RELOAD4: Configuration file: {{.*}}Inputs{{.}}config{{.}}i386-qqq.cfg
|
||||
|
||||
|
||||
//--- Invocation `clang --config x86_64-qqq2 -target i386` loads `x86_64-qqq2.cfg` if `i386-qqq2.cfg` and `i386.cfg` do not exist.
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq2 -target i386 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD5
|
||||
// note: target is overriden due to -target i386
|
||||
// CHECK-RELOAD5: Target: i386
|
||||
// CHECK-RELOAD5: Configuration file: {{.*}}Inputs{{.}}config{{.}}x86_64-qqq2.cfg
|
||||
|
||||
|
||||
//--- Invocation `clang --config x86_64-qqq -target i386 -m64` loads `x86_64-qqq.cfg`.
|
||||
//
|
||||
// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq -target i386 -m64 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD6
|
||||
// CHECK-RELOAD6: Target: x86_64
|
||||
// CHECK-RELOAD6: Configuration file: {{.*}}Inputs{{.}}config{{.}}x86_64-qqq.cfg
|
98
test/Driver/config-file3.c
Normal file
98
test/Driver/config-file3.c
Normal file
@ -0,0 +1,98 @@
|
||||
// REQUIRES: shell
|
||||
// REQUIRES: x86-registered-target
|
||||
|
||||
//--- If config file is specified by relative path (workdir/cfg-s2), it is searched for by that path.
|
||||
//
|
||||
// RUN: mkdir -p %T/workdir
|
||||
// RUN: echo "@subdir/cfg-s2" > %T/workdir/cfg-1
|
||||
// RUN: mkdir -p %T/workdir/subdir
|
||||
// RUN: echo "-Wundefined-var-template" > %T/workdir/subdir/cfg-s2
|
||||
//
|
||||
// RUN: ( cd %T && %clang --config workdir/cfg-1 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-REL )
|
||||
//
|
||||
// CHECK-REL: Configuration file: {{.*}}/workdir/cfg-1
|
||||
// CHECK-REL: -Wundefined-var-template
|
||||
|
||||
|
||||
//--- Invocation qqq-clang-g++ tries to find config file qqq-clang-g++.cfg first.
|
||||
//
|
||||
// RUN: mkdir -p %T/testdmode
|
||||
// RUN: [ ! -s %T/testdmode/qqq-clang-g++ ] || rm %T/testdmode/qqq-clang-g++
|
||||
// RUN: ln -s %clang %T/testdmode/qqq-clang-g++
|
||||
// RUN: echo "-Wundefined-func-template" > %T/testdmode/qqq-clang-g++.cfg
|
||||
// RUN: echo "-Werror" > %T/testdmode/qqq.cfg
|
||||
// RUN: %T/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir= -c -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix FULL-NAME
|
||||
//
|
||||
// FULL-NAME: Configuration file: {{.*}}/testdmode/qqq-clang-g++.cfg
|
||||
// FULL-NAME: -Wundefined-func-template
|
||||
// FULL-NAME-NOT: -Werror
|
||||
//
|
||||
//--- File specified by --config overrides config inferred from clang executable.
|
||||
//
|
||||
// RUN: %T/testdmode/qqq-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --config i386-qqq -c -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-EXPLICIT
|
||||
//
|
||||
// CHECK-EXPLICIT: Configuration file: {{.*}}/Inputs/config/i386-qqq.cfg
|
||||
//
|
||||
//--- Invocation qqq-clang-g++ tries to find config file qqq.cfg if qqq-clang-g++.cfg is not found.
|
||||
//
|
||||
// RUN: rm %T/testdmode/qqq-clang-g++.cfg
|
||||
// RUN: %T/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir= -c -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix SHORT-NAME
|
||||
//
|
||||
// SHORT-NAME: Configuration file: {{.*}}/testdmode/qqq.cfg
|
||||
// SHORT-NAME: -Werror
|
||||
// SHORT-NAME-NOT: -Wundefined-func-template
|
||||
|
||||
|
||||
//--- Config files are searched for in binary directory as well.
|
||||
//
|
||||
// RUN: mkdir -p %T/testbin
|
||||
// RUN: [ ! -s %T/testbin/clang ] || rm %T/testbin/clang
|
||||
// RUN: ln -s %clang %T/testbin/clang
|
||||
// RUN: echo "-Werror" > %T/testbin/aaa.cfg
|
||||
// RUN: %T/testbin/clang --config-system-dir= --config-user-dir= --config aaa.cfg -c -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-BIN
|
||||
//
|
||||
// CHECK-BIN: Configuration file: {{.*}}/testbin/aaa.cfg
|
||||
// CHECK-BIN: -Werror
|
||||
|
||||
|
||||
//--- If command line contains options that change triple (for instance, -m32), clang tries
|
||||
// reloading config file.
|
||||
|
||||
//--- When reloading config file, x86_64-clang-g++ tries to find config i386-clang-g++.cfg first.
|
||||
//
|
||||
// RUN: mkdir -p %T/testreload
|
||||
// RUN: [ ! -s %T/testreload/x86_64-clang-g++ ] || rm %T/testreload/x86_64-clang-g++
|
||||
// RUN: ln -s %clang %T/testreload/x86_64-clang-g++
|
||||
// RUN: echo "-Wundefined-func-template" > %T/testreload/i386-clang-g++.cfg
|
||||
// RUN: echo "-Werror" > %T/testreload/i386.cfg
|
||||
// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -m32 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD
|
||||
//
|
||||
// CHECK-RELOAD: Configuration file: {{.*}}/testreload/i386-clang-g++.cfg
|
||||
// CHECK-RELOAD: -Wundefined-func-template
|
||||
// CHECK-RELOAD-NOT: -Werror
|
||||
|
||||
//--- If config file is specified by --config and its name does not start with architecture, it is used without reloading.
|
||||
//
|
||||
// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir=%S/Inputs --config-user-dir= --config config-3 -c -m32 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1a
|
||||
//
|
||||
// CHECK-RELOAD1a: Configuration file: {{.*}}/Inputs/config-3.cfg
|
||||
//
|
||||
// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir=%S/Inputs --config-user-dir= --config config-3 -c -target i386 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1b
|
||||
//
|
||||
// CHECK-RELOAD1b: Configuration file: {{.*}}/Inputs/config-3.cfg
|
||||
|
||||
//--- If config file is specified by --config and its name starts with architecture, it is reloaded.
|
||||
//
|
||||
// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq -c -m32 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1c
|
||||
//
|
||||
// CHECK-RELOAD1c: Configuration file: {{.*}}/Inputs/config/i386-qqq.cfg
|
||||
|
||||
//--- x86_64-clang-g++ tries to find config i386.cfg if i386-clang-g++.cfg is not found.
|
||||
//
|
||||
// RUN: rm %T/testreload/i386-clang-g++.cfg
|
||||
// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -m32 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1d
|
||||
//
|
||||
// CHECK-RELOAD1d: Configuration file: {{.*}}/testreload/i386.cfg
|
||||
// CHECK-RELOAD1d: -Werror
|
||||
// CHECK-RELOAD1d-NOT: -Wundefined-func-template
|
||||
|
@ -205,7 +205,8 @@
|
||||
|
||||
// RUN: %clang -target x86_64-apple-ios -miphonesimulator-version-min=10.0 -c %s -### 2>&1 | \
|
||||
// RUN: FileCheck --check-prefix=CHECK-VERSION-TNO-OSV3 %s
|
||||
// CHECK-VERSION-TNO-OSV3: overriding '-mios-simulator-version-min=10.0' option with '--target=x86_64-apple-ios'
|
||||
// CHECK-VERSION-TNO-OSV3: "x86_64-apple-ios10.0.0-simulator"
|
||||
// CHECK-VERSION-TNO-OSV3-NOT: overriding '-mios-simulator-version-min
|
||||
// CHECK-VERSION-TNO-OSV3-NOT: argument unused during compilation
|
||||
|
||||
// RUN: %clang -target arm64-apple-ios10.1.0 -miphoneos-version-min=10.1.0.1 -c %s -### 2>&1 | \
|
||||
@ -235,6 +236,24 @@
|
||||
// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-OSV4 %s
|
||||
// CHECK-VERSION-TIGNORE-OSV4: "thumbv7k-apple-watchos3.0.0"
|
||||
|
||||
// Target without OS version inlcudes the OS given by -m<os>-version-min arguments:
|
||||
|
||||
// RUN: %clang -target x86_64-apple-macos -mmacos-version-min=10.11 -c %s -### 2>&1 | \
|
||||
// RUN: FileCheck --check-prefix=CHECK-VERSION-USE-OS-ARG1 %s
|
||||
// CHECK-VERSION-USE-OS-ARG1: "x86_64-apple-macosx10.11.0"
|
||||
|
||||
// RUN: %clang -target arm64-apple-ios -mios-version-min=9.0 -c %s -### 2>&1 | \
|
||||
// RUN: FileCheck --check-prefix=CHECK-VERSION-USE-OS-ARG2 %s
|
||||
// CHECK-VERSION-USE-OS-ARG2: "arm64-apple-ios9.0.0"
|
||||
|
||||
// RUN: %clang -target arm64-apple-tvos -mtvos-version-min=10.0 -c %s -### 2>&1 | \
|
||||
// RUN: FileCheck --check-prefix=CHECK-VERSION-USE-OS-ARG3 %s
|
||||
// CHECK-VERSION-USE-OS-ARG3: "arm64-apple-tvos10.0.0"
|
||||
|
||||
// RUN: %clang -target armv7k-apple-watchos -mwatchos-version-min=4 -c %s -### 2>&1 | \
|
||||
// RUN: FileCheck --check-prefix=CHECK-VERSION-USE-OS-ARG4 %s
|
||||
// CHECK-VERSION-USE-OS-ARG4: "thumbv7k-apple-watchos4.0.0"
|
||||
|
||||
// Target with OS version is not overriden by environment variables:
|
||||
|
||||
// RUN: env MACOSX_DEPLOYMENT_TARGET=10.1 \
|
||||
|
@ -37,7 +37,9 @@ class C {
|
||||
~C();
|
||||
};
|
||||
|
||||
// RUN: c-index-test -test-annotate-tokens=%s:1:1:38:1 %s -fno-delayed-template-parsing | FileCheck %s
|
||||
auto test5(X) -> X;
|
||||
|
||||
// RUN: c-index-test -test-annotate-tokens=%s:1:1:41:1 %s -std=c++14 -fno-delayed-template-parsing | FileCheck %s
|
||||
// CHECK: Keyword: "struct" [1:1 - 1:7] StructDecl=bonk:1:8 (Definition)
|
||||
// CHECK: Identifier: "bonk" [1:8 - 1:12] StructDecl=bonk:1:8 (Definition)
|
||||
// CHECK: Punctuation: "{" [1:13 - 1:14] StructDecl=bonk:1:8 (Definition)
|
||||
@ -184,6 +186,14 @@ class C {
|
||||
// CHECK: Punctuation: "}" [29:22 - 29:23] CompoundStmt=
|
||||
// CHECK: Punctuation: "~" [37:3 - 37:4] CXXDestructor=~C:37:3
|
||||
// CHECK: Identifier: "C" [37:4 - 37:5] CXXDestructor=~C:37:3
|
||||
// CHECK: Keyword: "auto" [40:1 - 40:5] FunctionDecl=test5:40:6
|
||||
// CHECK: Identifier: "test5" [40:6 - 40:11] FunctionDecl=test5:40:6
|
||||
// CHECK: Punctuation: "(" [40:11 - 40:12] FunctionDecl=test5:40:6
|
||||
// CHECK: Identifier: "X" [40:12 - 40:13] TypeRef=struct X:7:8
|
||||
// CHECK: Punctuation: ")" [40:13 - 40:14] FunctionDecl=test5:40:6
|
||||
// CHECK: Punctuation: "->" [40:15 - 40:17] FunctionDecl=test5:40:6
|
||||
// CHECK: Identifier: "X" [40:18 - 40:19] TypeRef=struct X:7:8
|
||||
// CHECK: Punctuation: ";" [40:19 - 40:20]
|
||||
|
||||
// RUN: env LIBCLANG_DISABLE_CRASH_RECOVERY=1 c-index-test -test-annotate-tokens=%s:32:1:32:13 %s | FileCheck %s -check-prefix=CHECK2
|
||||
// CHECK2: Keyword: "if" [32:3 - 32:5] IfStmt=
|
||||
|
@ -1,6 +1,10 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
|
@ -1,6 +1,11 @@
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
@ -2,6 +2,12 @@
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++98 %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++11 %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
|
||||
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++98 %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++11 %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
|
||||
int a;
|
||||
|
@ -1,5 +1,7 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
|
||||
|
||||
int foo() {
|
||||
L1:
|
||||
foo();
|
||||
|
@ -1,5 +1,7 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
|
||||
|
||||
int foo() {
|
||||
L1:
|
||||
foo();
|
||||
|
@ -1,6 +1,11 @@
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
// REQUIRES: x86-registered-target
|
||||
#ifndef HEADER
|
||||
|
@ -1,6 +1,11 @@
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
@ -1,6 +1,11 @@
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
// REQUIRES: x86-registered-target
|
||||
#ifndef HEADER
|
||||
|
@ -1,6 +1,10 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
|
@ -1,6 +1,11 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
@ -1,5 +1,7 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
|
||||
|
||||
template <class T>
|
||||
T tmain(T argc) {
|
||||
#pragma omp barrier
|
||||
|
@ -1,6 +1,10 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
|
@ -1,6 +1,11 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple x86_64-apple-darwin13.4.0 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple x86_64-apple-darwin13.4.0 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
@ -1,5 +1,8 @@
|
||||
// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-version=45 -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-version=45 -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
|
||||
//CHECK: call i32 @__kmpc_cancel
|
||||
//CHECK: br {{.*}}label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
|
||||
//CHECK: [[EXIT]]:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user