Vendor import of clang trunk r306325:

https://llvm.org/svn/llvm-project/cfe/trunk@306325
This commit is contained in:
Dimitry Andric 2017-06-26 20:33:12 +00:00
parent 325377b573
commit ef915aab0a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=320376
svn path=/vendor/clang/clang-trunk-r306325/; revision=320377; tag=vendor/clang/clang-trunk-r306325
201 changed files with 7907 additions and 2168 deletions

View File

@ -856,15 +856,15 @@ mentioned above, call:
.. code-block:: c
_Block_object_assign(&dst->target, src->target, BLOCK_FIELD_<appropo>);
_Block_object_assign(&dst->target, src->target, BLOCK_FIELD_<apropos>);
in the copy helper and:
.. code-block:: c
_Block_object_dispose(->target, BLOCK_FIELD_<appropo>);
_Block_object_dispose(->target, BLOCK_FIELD_<apropos>);
in the dispose helper where ``<appropo>`` is:
in the dispose helper where ``<apropos>`` is:
.. code-block:: c
@ -888,7 +888,7 @@ and functions are generated in the same manner.
Under ObjC we allow ``__weak`` as an attribute on ``__block`` variables, and
this causes the addition of ``BLOCK_FIELD_IS_WEAK`` orred onto the
``BLOCK_FIELD_IS_BYREF`` flag when copying the ``block_byref`` structure in the
``Block`` copy helper, and onto the ``BLOCK_FIELD_<appropo>`` field within the
``Block`` copy helper, and onto the ``BLOCK_FIELD_<apropos>`` field within the
``block_byref`` copy/dispose helper calls.
The prototypes, and summary, of the helper functions are:

View File

@ -120,6 +120,18 @@ entity.
It operates on the current, potentially unsaved buffer and does not create
or save any files. To revert a formatting, just undo.
An alternative option is to format changes when saving a file and thus to
have a zero-effort integration into the coding workflow. To do this, add this to
your `.vimrc`:
.. code-block:: vim
function! Formatonsave()
let l:formatdiff = 1
pyf ~/llvm/tools/clang/tools/clang-format/clang-format.py
endfunction
autocmd BufWritePre *.h,*.cc,*.cpp call Formatonsave()
Emacs Integration
=================

View File

@ -309,12 +309,28 @@ the configuration (without a prefix: ``Auto``).
* ``SFS_None`` (in configuration: ``None``)
Never merge functions into a single line.
* ``SFS_InlineOnly`` (in configuration: ``InlineOnly``)
Only merge functions defined inside a class. Same as "inline",
except it does not implies "empty": i.e. top level empty functions
are not merged either.
.. code-block:: c++
class Foo {
void f() { foo(); }
};
void f() {
foo();
}
void f() {
}
* ``SFS_Empty`` (in configuration: ``Empty``)
Only merge empty functions.
.. code-block:: c++
void f() { bar(); }
void f() {}
void f2() {
bar2();
}
@ -327,6 +343,10 @@ the configuration (without a prefix: ``Auto``).
class Foo {
void f() { foo(); }
};
void f() {
foo();
}
void f() {}
* ``SFS_All`` (in configuration: ``All``)
Merge all functions fitting on a single line.
@ -518,147 +538,159 @@ the configuration (without a prefix: ``Auto``).
* ``bool AfterClass`` Wrap class definitions.
.. code-block:: c++
.. code-block:: c++
true:
class foo
{};
true:
class foo {};
false:
class foo {};
false:
class foo
{};
* ``bool AfterControlStatement`` Wrap control statements (``if``/``for``/``while``/``switch``/..).
.. code-block:: c++
.. code-block:: c++
true:
if (foo())
{
} else
{}
for (int i = 0; i < 10; ++i)
{}
true:
if (foo())
{
} else
{}
for (int i = 0; i < 10; ++i)
{}
false:
if (foo()) {
} else {
}
for (int i = 0; i < 10; ++i) {
}
false:
if (foo()) {
} else {
}
for (int i = 0; i < 10; ++i) {
}
* ``bool AfterEnum`` Wrap enum definitions.
.. code-block:: c++
.. code-block:: c++
true:
enum X : int
{
B
};
true:
enum X : int
{
B
};
false:
enum X : int { B };
false:
enum X : int { B };
* ``bool AfterFunction`` Wrap function definitions.
.. code-block:: c++
.. code-block:: c++
true:
void foo()
{
bar();
bar2();
}
true:
void foo()
{
bar();
bar2();
}
false:
void foo() {
bar();
bar2();
}
false:
void foo() {
bar();
bar2();
}
* ``bool AfterNamespace`` Wrap namespace definitions.
.. code-block:: c++
.. code-block:: c++
true:
namespace
{
int foo();
int bar();
}
true:
namespace
{
int foo();
int bar();
}
false:
namespace {
int foo();
int bar();
}
false:
namespace {
int foo();
int bar();
}
* ``bool AfterObjCDeclaration`` Wrap ObjC definitions (``@autoreleasepool``, interfaces, ..).
* ``bool AfterStruct`` Wrap struct definitions.
.. code-block:: c++
.. code-block:: c++
true:
struct foo
{
int x;
};
true:
struct foo
{
int x;
};
false:
struct foo {
int x;
};
false:
struct foo {
int x;
};
* ``bool AfterUnion`` Wrap union definitions.
.. code-block:: c++
.. code-block:: c++
true:
union foo
{
int x;
}
true:
union foo
{
int x;
}
false:
union foo {
int x;
}
false:
union foo {
int x;
}
* ``bool BeforeCatch`` Wrap before ``catch``.
.. code-block:: c++
.. code-block:: c++
true:
try {
foo();
}
catch () {
}
true:
try {
foo();
}
catch () {
}
false:
try {
foo();
} catch () {
}
false:
try {
foo();
} catch () {
}
* ``bool BeforeElse`` Wrap before ``else``.
.. code-block:: c++
.. code-block:: c++
true:
if (foo()) {
}
else {
}
true:
if (foo()) {
}
else {
}
false:
if (foo()) {
} else {
}
false:
if (foo()) {
} else {
}
* ``bool IndentBraces`` Indent the wrapped braces themselves.
* ``bool SplitEmptyFunctionBody`` If ``false``, empty function body can be put on a single line.
This option is used only if the opening brace of the function has
already been wrapped, i.e. the `AfterFunction` brace wrapping mode is
set, and the function could/should not be put on a single line (as per
`AllowShortFunctionsOnASingleLine` and constructor formatting options).
.. code-block:: c++
int f() vs. inf f()
{} {
}
**BreakAfterJavaFieldAnnotations** (``bool``)
Break after each annotation on a field in Java files.
@ -899,17 +931,40 @@ the configuration (without a prefix: ``Auto``).
firstValue :
SecondValueVeryVeryVeryVeryLong;
**BreakConstructorInitializersBeforeComma** (``bool``)
Always break constructor initializers before commas and align
the commas with the colon.
**BreakConstructorInitializers** (``BreakConstructorInitializersStyle``)
The constructor initializers style to use.
Possible values:
* ``BCIS_BeforeColon`` (in configuration: ``BeforeColon``)
Break constructor initializers before the colon and after the commas.
.. code-block:: c++
Constructor()
: initializer1(),
initializer2()
* ``BCIS_BeforeComma`` (in configuration: ``BeforeComma``)
Break constructor initializers before the colon and commas, and align
the commas with the colon.
.. code-block:: c++
Constructor()
: initializer1()
, initializer2()
* ``BCIS_AfterColon`` (in configuration: ``AfterColon``)
Break constructor initializers after the colon and commas.
.. code-block:: c++
Constructor() :
initializer1(),
initializer2()
.. code-block:: c++
true: false:
SomeClass::Constructor() vs. SomeClass::Constructor() : a(a),
: a(a) b(b),
, b(b) c(c) {}
, c(c) {}
**BreakStringLiterals** (``bool``)
Allow breaking string literals when formatting.
@ -931,6 +986,31 @@ the configuration (without a prefix: ``Auto``).
// Will leave the following line unaffected
#include <vector> // FOOBAR pragma: keep
**CompactNamespaces** (``bool``)
If ``true``, consecutive namespace declarations will be on the same
line. If ``false``, each namespace is declared on a new line.
.. code-block:: c++
true:
namespace Foo { namespace Bar {
}}
false:
namespace Foo {
namespace Bar {
}
}
If it does not fit on a single line, the overflowing namespaces get
wrapped:
.. code-block:: c++
namespace Foo { namespace Bar {
namespace Extra {
}}}
**ConstructorInitializerAllOnOneLineOrOnePerLine** (``bool``)
If the constructor initializers don't fit on a line, put each
initializer on its own line.
@ -1321,6 +1401,9 @@ the configuration (without a prefix: ``Auto``).
Add a space in front of an Objective-C protocol list, i.e. use
``Foo <Protocol>`` instead of ``Foo<Protocol>``.
**PenaltyBreakAssignment** (``unsigned``)
The penalty for breaking around an assignment operator.
**PenaltyBreakBeforeFirstCallParameter** (``unsigned``)
The penalty for breaking a function call after ``call(``.
@ -1392,6 +1475,15 @@ the configuration (without a prefix: ``Auto``).
#include "b.h" vs. #include "a.h"
#include "a.h" #include "b.h"
**SortUsingDeclarations** (``bool``)
If ``true``, clang-format will sort using declarations.
.. code-block:: c++
false: true:
using std::cout; vs. using std::cin;
using std::cin; using std::cout;
**SpaceAfterCStyleCast** (``bool``)
If ``true``, a space is inserted after C style casts.

View File

@ -28,7 +28,9 @@ The core routine of LibFormat is ``reformat()``:
This reads a token stream out of the lexer ``Lex`` and reformats all the code
ranges in ``Ranges``. The ``FormatStyle`` controls basic decisions made during
formatting. A list of options can be found under :ref:`style-options`.
formatting. A list of options can be found under :ref:`style-options`.
The style options are described in :doc:`ClangFormatStyleOptions`.
.. _style-options:

View File

@ -27,7 +27,7 @@ executable, so make sure to use ``clang`` (not ``ld``) for the final
link step. When linking shared libraries, the MemorySanitizer run-time
is not linked, so ``-Wl,-z,defs`` may cause link errors (don't use it
with MemorySanitizer). To get a reasonable performance add ``-O1`` or
higher. To get meaninful stack traces in error messages add
higher. To get meaningful stack traces in error messages add
``-fno-omit-frame-pointer``. To get perfect stack traces you may need
to disable inlining (just use ``-O1``) and tail call elimination
(``-fno-optimize-sibling-calls``).

View File

@ -274,6 +274,11 @@ To specify an alternate directory for raw profiles, use
Drawbacks and limitations
=========================
* Prior to version 2.26, the GNU binutils BFD linker is not able link programs
compiled with ``-fcoverage-mapping`` in its ``--gc-sections`` mode. Possible
workarounds include disabling ``--gc-sections``, upgrading to a newer version
of BFD, or using the Gold linker.
* Code coverage does not handle unpredictable changes in control flow or stack
unwinding in the presence of exceptions precisely. Consider the following
function:

View File

@ -126,6 +126,50 @@ which currently must be enabled through a linker option.
- lld (as of LLVM r296702):
``-Wl,--thinlto-cache-dir=/path/to/cache``
Cache Pruning
-------------
To help keep the size of the cache under control, ThinLTO supports cache
pruning. Cache pruning is supported with ld64 and ELF lld, but currently only
ELF lld allows you to control the policy with a policy string. The cache
policy must be specified with a linker option.
- ELF lld (as of LLVM r298036):
``-Wl,--thinlto-cache-policy,POLICY``
A policy string is a series of key-value pairs separated by ``:`` characters.
Possible key-value pairs are:
- ``cache_size=X%``: The maximum size for the cache directory is ``X`` percent
of the available space on the the disk. Set to 100 to indicate no limit,
50 to indicate that the cache size will not be left over half the available
disk space. A value over 100 is invalid. A value of 0 disables the percentage
size-based pruning. The default is 75%.
- ``cache_size_bytes=X``, ``cache_size_bytes=Xk``, ``cache_size_bytes=Xm``,
``cache_size_bytes=Xg``:
Sets the maximum size for the cache directory to ``X`` bytes (or KB, MB,
GB respectively). A value over the amount of available space on the disk
will be reduced to the amount of available space. A value of 0 disables
the byte size-based pruning. The default is no byte size-based pruning.
Note that ThinLTO will apply both size-based pruning policies simultaneously,
and changing one does not affect the other. For example, a policy of
``cache_size_bytes=1g`` on its own will cause both the 1GB and default 75%
policies to be applied unless the default ``cache_size`` is overridden.
- ``prune_after=Xs``, ``prune_after=Xm``, ``prune_after=Xh``: Sets the
expiration time for cache files to ``X`` seconds (or minutes, hours
respectively). When a file hasn't been accessed for ``prune_after`` seconds,
it is removed from the cache. A value of 0 disables the expiration-based
pruning. The default is 1 week.
- ``prune_interval=Xs``, ``prune_interval=Xm``, ``prune_interval=Xh``:
Sets the pruning interval to ``X`` seconds (or minutes, hours
respectively). This is intended to be used to avoid scanning the directory
too often. It does not impact the decision of which files to prune. A
value of 0 forces the scan to occur. The default is every 20 minutes.
Clang Bootstrap
---------------

View File

@ -24,10 +24,10 @@ def doxygen2rst(text):
text = re.sub(r'\\\w+ ', '', text)
return text
def indent(text, columns):
def indent(text, columns, indent_first_line=True):
indent = ' ' * columns
s = re.sub(r'\n([^\n])', '\n' + indent + '\\1', text, flags=re.S)
if s.startswith('\n'):
if not indent_first_line or s.startswith('\n'):
return s
return indent + s
@ -64,7 +64,9 @@ def __init__(self, name, comment):
self.comment = comment.strip()
def __str__(self):
return '\n* ``%s`` %s' % (self.name, doxygen2rst(self.comment))
return '\n* ``%s`` %s' % (
self.name,
doxygen2rst(indent(self.comment, 2, indent_first_line=False)))
class Enum:
def __init__(self, name, comment):
@ -179,7 +181,7 @@ class State:
if enums.has_key(option.type):
option.enum = enums[option.type]
elif nested_structs.has_key(option.type):
option.nested_struct = nested_structs[option.type];
option.nested_struct = nested_structs[option.type]
else:
raise Exception('Unknown type: %s' % option.type)
return options
@ -195,4 +197,3 @@ class State:
with open(DOC_FILE, 'wb') as output:
output.write(contents)

View File

@ -7,7 +7,7 @@
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header provides a public inferface to use CompilationDatabase without *|
|* This header provides a public interface to use CompilationDatabase without *|
|* the full Clang C++ API. *|
|* *|
\*===----------------------------------------------------------------------===*/

View File

@ -7,7 +7,7 @@
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header provides a public inferface to a Clang library for extracting *|
|* This header provides a public interface to a Clang library for extracting *|
|* high-level symbol information from source files without exposing the full *|
|* Clang C++ API. *|
|* *|

View File

@ -1656,6 +1656,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
unsigned HasImplicitReturnZero : 1;
unsigned IsLateTemplateParsed : 1;
unsigned IsConstexpr : 1;
unsigned InstantiationIsPending:1;
/// \brief Indicates if the function uses __try.
unsigned UsesSEHTry : 1;
@ -1751,6 +1752,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
IsDeleted(false), IsTrivial(false), IsDefaulted(false),
IsExplicitlyDefaulted(false), HasImplicitReturnZero(false),
IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified),
InstantiationIsPending(false),
UsesSEHTry(false), HasSkippedBody(false), WillHaveBody(false),
EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(),
DNLoc(NameInfo.getInfo()) {}
@ -1872,7 +1874,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
///
bool isThisDeclarationADefinition() const {
return IsDeleted || IsDefaulted || Body || IsLateTemplateParsed ||
hasDefiningAttr();
WillHaveBody || hasDefiningAttr();
}
/// doesThisDeclarationHaveABody - Returns whether this specific
@ -1943,6 +1945,15 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
bool isConstexpr() const { return IsConstexpr; }
void setConstexpr(bool IC) { IsConstexpr = IC; }
/// \brief Whether the instantiation of this function is pending.
/// This bit is set when the decision to instantiate this function is made
/// and unset if and when the function body is created. That leaves out
/// cases where instantiation did not happen because the template definition
/// was not seen in this TU. This bit remains set in those cases, under the
/// assumption that the instantiation will happen in some other TU.
bool instantiationIsPending() const { return InstantiationIsPending; }
void setInstantiationIsPending(bool IC) { InstantiationIsPending = IC; }
/// \brief Indicates the function uses __try.
bool usesSEHTry() const { return UsesSEHTry; }
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }

View File

@ -202,26 +202,33 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
OBJC_TQ_CSNullability = 0x40
};
protected:
// Enumeration values used in the bits stored in NextInContextAndBits.
enum {
/// \brief Whether this declaration is a top-level declaration (function,
/// global variable, etc.) that is lexically inside an objc container
/// definition.
TopLevelDeclInObjCContainerFlag = 0x01,
/// \brief Whether this declaration is private to the module in which it was
/// defined.
ModulePrivateFlag = 0x02
/// The kind of ownership a declaration has, for visibility purposes.
/// This enumeration is designed such that higher values represent higher
/// levels of name hiding.
enum class ModuleOwnershipKind : unsigned {
/// This declaration is not owned by a module.
Unowned,
/// This declaration has an owning module, but is globally visible
/// (typically because its owning module is visible and we know that
/// modules cannot later become hidden in this compilation).
/// After serialization and deserialization, this will be converted
/// to VisibleWhenImported.
Visible,
/// This declaration has an owning module, and is visible when that
/// module is imported.
VisibleWhenImported,
/// This declaration has an owning module, but is only visible to
/// lookups that occur within that module.
ModulePrivate
};
protected:
/// \brief The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is
/// traversed via DeclContext's decls_begin()/decls_end().
///
/// The extra two bits are used for the TopLevelDeclInObjCContainer and
/// ModulePrivate bits.
llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits;
/// The extra two bits are used for the ModuleOwnershipKind.
llvm::PointerIntPair<Decl *, 2, ModuleOwnershipKind> NextInContextAndBits;
private:
friend class DeclContext;
@ -282,6 +289,11 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
/// are regarded as "referenced" but not "used".
unsigned Referenced : 1;
/// \brief Whether this declaration is a top-level declaration (function,
/// global variable, etc.) that is lexically inside an objc container
/// definition.
unsigned TopLevelDeclInObjCContainer : 1;
/// \brief Whether statistic collection is enabled.
static bool StatisticsEnabled;
@ -294,11 +306,6 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
/// \brief Whether this declaration was loaded from an AST file.
unsigned FromASTFile : 1;
/// \brief Whether this declaration is hidden from normal name lookup, e.g.,
/// because it is was loaded from an AST file is either module-private or
/// because its submodule has not been made visible.
unsigned Hidden : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 13;
@ -332,26 +339,38 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
private:
bool AccessDeclContextSanity() const;
/// Get the module ownership kind to use for a local lexical child of \p DC,
/// which may be either a local or (rarely) an imported declaration.
static ModuleOwnershipKind getModuleOwnershipKindForChildOf(DeclContext *DC) {
if (DC) {
auto *D = cast<Decl>(DC);
auto MOK = D->getModuleOwnershipKind();
if (MOK != ModuleOwnershipKind::Unowned &&
(!D->isFromASTFile() || D->hasLocalOwningModuleStorage()))
return MOK;
// If D is not local and we have no local module storage, then we don't
// need to track module ownership at all.
}
return ModuleOwnershipKind::Unowned;
}
protected:
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextInContextAndBits(), DeclCtx(DC), Loc(L), DeclKind(DK),
InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false),
Referenced(false), Access(AS_none), FromASTFile(0),
Hidden(DC && cast<Decl>(DC)->Hidden &&
(!cast<Decl>(DC)->isFromASTFile() ||
hasLocalOwningModuleStorage())),
: NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)),
DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false),
Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0) {
if (StatisticsEnabled) add(DK);
}
Decl(Kind DK, EmptyShell Empty)
: NextInContextAndBits(), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0)
{
: NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), HasAttrs(false),
Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0) {
if (StatisticsEnabled) add(DK);
}
@ -551,16 +570,11 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
/// global variable, etc.) that is lexically inside an objc container
/// definition.
bool isTopLevelDeclInObjCContainer() const {
return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag;
return TopLevelDeclInObjCContainer;
}
void setTopLevelDeclInObjCContainer(bool V = true) {
unsigned Bits = NextInContextAndBits.getInt();
if (V)
Bits |= TopLevelDeclInObjCContainerFlag;
else
Bits &= ~TopLevelDeclInObjCContainerFlag;
NextInContextAndBits.setInt(Bits);
TopLevelDeclInObjCContainer = V;
}
/// \brief Looks on this and related declarations for an applicable
@ -570,7 +584,7 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
/// \brief Whether this declaration was marked as being private to the
/// module in which it was defined.
bool isModulePrivate() const {
return NextInContextAndBits.getInt() & ModulePrivateFlag;
return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate;
}
/// \brief Whether this declaration is exported (by virtue of being lexically
@ -585,15 +599,14 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
const Attr *getDefiningAttr() const;
protected:
/// \brief Specify whether this declaration was marked as being private
/// \brief Specify that this declaration was marked as being private
/// to the module in which it was defined.
void setModulePrivate(bool MP = true) {
unsigned Bits = NextInContextAndBits.getInt();
if (MP)
Bits |= ModulePrivateFlag;
else
Bits &= ~ModulePrivateFlag;
NextInContextAndBits.setInt(Bits);
void setModulePrivate() {
// The module-private specifier has no effect on unowned declarations.
// FIXME: We should track this in some way for source fidelity.
if (getModuleOwnershipKind() == ModuleOwnershipKind::Unowned)
return;
setModuleOwnershipKind(ModuleOwnershipKind::ModulePrivate);
}
/// \brief Set the owning module ID.
@ -692,7 +705,7 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
/// \brief Get the imported owning module, if this decl is from an imported
/// (non-local) module.
Module *getImportedOwningModule() const {
if (!isFromASTFile())
if (!isFromASTFile() || !hasOwningModule())
return nullptr;
return getOwningModuleSlow();
@ -701,31 +714,57 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
/// \brief Get the local owning module, if known. Returns nullptr if owner is
/// not yet known or declaration is not from a module.
Module *getLocalOwningModule() const {
if (isFromASTFile() || !Hidden)
if (isFromASTFile() || !hasOwningModule())
return nullptr;
assert(hasLocalOwningModuleStorage() &&
"hidden local decl but no local module storage");
"owned local decl but no local module storage");
return reinterpret_cast<Module *const *>(this)[-1];
}
void setLocalOwningModule(Module *M) {
assert(!isFromASTFile() && Hidden && hasLocalOwningModuleStorage() &&
assert(!isFromASTFile() && hasOwningModule() &&
hasLocalOwningModuleStorage() &&
"should not have a cached owning module");
reinterpret_cast<Module **>(this)[-1] = M;
}
/// Is this declaration owned by some module?
bool hasOwningModule() const {
return getModuleOwnershipKind() != ModuleOwnershipKind::Unowned;
}
/// Get the module that owns this declaration.
Module *getOwningModule() const {
return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule();
}
/// \brief Determine whether this declaration is hidden from name lookup.
bool isHidden() const { return Hidden; }
/// \brief Determine whether this declaration might be hidden from name
/// lookup. Note that the declaration might be visible even if this returns
/// \c false, if the owning module is visible within the query context.
// FIXME: Rename this to make it clearer what it does.
bool isHidden() const {
return (int)getModuleOwnershipKind() > (int)ModuleOwnershipKind::Visible;
}
/// Set that this declaration is globally visible, even if it came from a
/// module that is not visible.
void setVisibleDespiteOwningModule() {
if (hasOwningModule())
setModuleOwnershipKind(ModuleOwnershipKind::Visible);
}
/// \brief Get the kind of module ownership for this declaration.
ModuleOwnershipKind getModuleOwnershipKind() const {
return NextInContextAndBits.getInt();
}
/// \brief Set whether this declaration is hidden from name lookup.
void setHidden(bool Hide) {
assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) &&
"declaration with no owning module can't be hidden");
Hidden = Hide;
void setModuleOwnershipKind(ModuleOwnershipKind MOK) {
assert(!(getModuleOwnershipKind() == ModuleOwnershipKind::Unowned &&
MOK != ModuleOwnershipKind::Unowned && !isFromASTFile() &&
!hasLocalOwningModuleStorage()) &&
"no storage available for owning module for this declaration");
NextInContextAndBits.setInt(MOK);
}
unsigned getIdentifierNamespace() const {

View File

@ -17,6 +17,8 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Regex.h"
#include <vector>
namespace clang {
@ -319,6 +321,26 @@ struct OnlyLargestCloneConstraint {
void constrain(std::vector<CloneDetector::CloneGroup> &Result);
};
struct FilenamePatternConstraint {
StringRef IgnoredFilesPattern;
std::shared_ptr<llvm::Regex> IgnoredFilesRegex;
FilenamePatternConstraint(StringRef IgnoredFilesPattern)
: IgnoredFilesPattern(IgnoredFilesPattern) {
IgnoredFilesRegex = std::make_shared<llvm::Regex>("^(" +
IgnoredFilesPattern.str() + "$)");
}
bool isAutoGenerated(const CloneDetector::CloneGroup &Group);
void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
CloneConstraint::filterGroups(
CloneGroups, [this](const CloneDetector::CloneGroup &Group) {
return isAutoGenerated(Group);
});
}
};
/// Analyzes the pattern of the referenced variables in a statement.
class VariablePattern {

View File

@ -52,6 +52,7 @@
// LL -> long long
// LLL -> __int128_t (e.g. LLLi)
// W -> int64_t
// N -> 'int' size if target is LP64, 'L' otherwise.
// S -> signed
// U -> unsigned
// I -> Required to constant fold to an integer constant expression.
@ -718,11 +719,11 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ulong, "ULiULi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_uint64, "ULLiULLi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_code, "ULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_code, "ULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_code, "UNi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_code, "UNi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
@ -730,33 +731,33 @@ LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange8, "ccD*cc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange16, "ssD*ss", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange, "NiNiD*NiNi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange64, "LLiLLiD*LLiLLi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement16, "ssD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement, "NiNiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeSub8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeSub16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeSub, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeSub, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedIncrement16, "ssD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedIncrement, "NiNiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedOr8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedOr16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedOr, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedOr, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedXor, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_interlockedbittestandset, "UcLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedXor, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES)
@ -765,12 +766,12 @@ LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl8, "UcUcUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl16, "UsUsUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl, "UiUii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotl, "ULiULii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotl, "UNiUNii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr8, "UcUcUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr16, "UsUsUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr, "UiUii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotr, "ULiULii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotr, "UNiUNii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
LANGBUILTIN(__fastfail, "vUi", "nr", ALL_MS_LANGUAGES)

View File

@ -215,10 +215,10 @@ LANGBUILTIN(_MoveFromCoprocessor2, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveToCoprocessor, "vUiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveToCoprocessor2, "vUiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
TARGET_HEADER_BUILTIN(_BitScanForward, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")

View File

@ -1822,8 +1822,8 @@ TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "", "mwaitx")
TARGET_BUILTIN(__builtin_ia32_clzero, "vv*", "", "clzero")
// MSVC
TARGET_HEADER_BUILTIN(_BitScanForward, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_ReadBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@ -1838,15 +1838,15 @@ TARGET_HEADER_BUILTIN(__stosb, "vUc*Ucz", "nh", "intrin.h", ALL_MS_LANGUAGES, ""
TARGET_HEADER_BUILTIN(__int2c, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__ud2, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsbyte, "UcULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsword, "UsULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsdword, "ULiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsqword, "ULLiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsbyte, "UcUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsword, "UsUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsdword, "UNiUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsqword, "ULLiUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsbyte, "UcULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsword, "UsULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsdword, "ULiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsqword, "ULLiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsbyte, "UcUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsword, "UsUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsdword, "UNiUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsqword, "ULLiUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
#undef BUILTIN
#undef TARGET_BUILTIN

View File

@ -22,8 +22,8 @@
# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS)
#endif
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__mulh, "LLiLLiLLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "")

View File

@ -226,6 +226,9 @@ def warn_drv_enabling_rtti_with_exceptions : Warning<
def warn_drv_disabling_vptr_no_rtti_default : Warning<
"implicitly disabling vptr sanitizer because rtti wasn't enabled">,
InGroup<DiagGroup<"auto-disable-vptr-sanitizer">>;
def warn_drv_object_size_disabled_O0 : Warning<
"the object size sanitizer has no effect at -O0, but is explicitly enabled: %0">,
InGroup<InvalidCommandLineArgument>;
def note_drv_command_failed_diag_msg : Note<
"diagnostic msg: %0">;

View File

@ -98,7 +98,9 @@ def CXX11CompatDeprecatedWritableStr :
def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
def UnguardedAvailability : DiagGroup<"unguarded-availability">;
def UnguardedAvailabilityNew : DiagGroup<"unguarded-availability-new">;
def UnguardedAvailability : DiagGroup<"unguarded-availability",
[UnguardedAvailabilityNew]>;
// partial-availability is an alias of unguarded-availability.
def : DiagGroup<"partial-availability", [UnguardedAvailability]>;
def DeprecatedDynamicExceptionSpec
@ -149,6 +151,7 @@ def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">;
def GNUFoldingConstant : DiagGroup<"gnu-folding-constant">;
def FormatExtraArgs : DiagGroup<"format-extra-args">;
def FormatZeroLength : DiagGroup<"format-zero-length">;
def CXX1zCompatMangling : DiagGroup<"c++1z-compat-mangling">;
// Warnings for C++1y code which is not compatible with prior C++ standards.
def CXXPre14Compat : DiagGroup<"c++98-c++11-compat">;
@ -211,7 +214,8 @@ def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
[CXXPre1zCompatPedantic]>;
def CXX1zCompat : DiagGroup<"c++1z-compat", [DeprecatedRegister,
DeprecatedIncrementBool]>;
DeprecatedIncrementBool,
CXX1zCompatMangling]>;
def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;

View File

@ -507,7 +507,7 @@ def warn_deprecated_copy_operation : Warning<
InGroup<Deprecated>, DefaultIgnore;
def warn_cxx1z_compat_exception_spec_in_signature : Warning<
"mangled name of %0 will change in C++17 due to non-throwing exception "
"specification in function signature">, InGroup<CXX1zCompat>;
"specification in function signature">, InGroup<CXX1zCompatMangling>;
def warn_global_constructor : Warning<
"declaration requires a global constructor">,
@ -2870,8 +2870,13 @@ def note_protocol_method : Note<
def warn_unguarded_availability :
Warning<"%0 is only available on %1 %2 or newer">,
InGroup<UnguardedAvailability>, DefaultIgnore;
def warn_unguarded_availability_new :
Warning<warn_unguarded_availability.Text>,
InGroup<UnguardedAvailabilityNew>;
def warn_partial_availability : Warning<"%0 is only available conditionally">,
InGroup<UnguardedAvailability>, DefaultIgnore;
def warn_partial_availability_new : Warning<warn_partial_availability.Text>,
InGroup<UnguardedAvailabilityNew>;
def note_partial_availability_silence : Note<
"explicitly redeclare %0 to silence this warning">;
def note_unguarded_available_silence : Note<
@ -2879,9 +2884,14 @@ def note_unguarded_available_silence : Note<
" this warning">;
def warn_partial_message : Warning<"%0 is partial: %1">,
InGroup<UnguardedAvailability>, DefaultIgnore;
def warn_partial_message_new : Warning<warn_partial_message.Text>,
InGroup<UnguardedAvailabilityNew>;
def warn_partial_fwdclass_message : Warning<
"%0 may be partial because the receiver type is unknown">,
InGroup<UnguardedAvailability>, DefaultIgnore;
def warn_partial_fwdclass_message_new :
Warning<warn_partial_fwdclass_message.Text>,
InGroup<UnguardedAvailabilityNew>;
def warn_at_available_unchecked_use : Warning<
"%select{@available|__builtin_available}0 does not guard availability here; "
"use if (%select{@available|__builtin_available}0) instead">,
@ -6341,6 +6351,15 @@ def err_exceptions_disabled : Error<
"cannot use '%0' with exceptions disabled">;
def err_objc_exceptions_disabled : Error<
"cannot use '%0' with Objective-C exceptions disabled">;
def warn_throw_in_noexcept_func
: Warning<"%0 has a non-throwing exception specification but can still "
"throw, resulting in unexpected program termination">,
InGroup<Exceptions>;
def note_throw_in_dtor
: Note<"destructor or deallocator has a (possibly implicit) non-throwing "
"excepton specification">;
def note_throw_in_function
: Note<"non-throwing function declare here">;
def err_seh_try_outside_functions : Error<
"cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">;
def err_mixing_cxx_try_seh_try : Error<
@ -8311,6 +8330,9 @@ def err_opencl_ext_vector_component_invalid_length : Error<
"vector component access has invalid length %0. Supported: 1,2,3,4,8,16.">;
def err_opencl_function_variable : Error<
"%select{non-kernel function|function scope}0 variable cannot be declared in %1 address space">;
def err_opencl_addrspace_scope : Error<
"variables in the %0 address space can only be declared in the outermost "
"scope of a kernel function">;
def err_static_function_scope : Error<
"variables in function scope cannot be declared static">;
def err_opencl_bitfields : Error<

View File

@ -112,8 +112,13 @@ def note_module_odr_violation_possible_decl : Note<
def err_module_odr_violation_different_definitions : Error<
"%q0 has different definitions in different modules; "
"%select{definition in module '%2' is here|defined here}1">;
def note_first_module_difference : Note<
"in first definition, possible difference is here">;
def note_module_odr_violation_different_definitions : Note<
"definition in module '%0' is here">;
def note_second_module_difference : Note<
"in second definition, possible difference is here">;
def err_module_odr_violation_different_instantiations : Error<
"instantiation of %q0 is different in different modules">;

View File

@ -393,7 +393,9 @@ class Module {
/// \brief Retrieve the full name of this module, including the path from
/// its top-level module.
std::string getFullModuleName() const;
/// \param AllowStringLiterals If \c true, components that might not be
/// lexically valid as identifiers will be emitted as string literals.
std::string getFullModuleName(bool AllowStringLiterals = false) const;
/// \brief Whether the full name of this module is equal to joining
/// \p nameParts with "."s.

View File

@ -227,6 +227,7 @@ def OP_UNAVAILABLE : Operation {
// u: unsigned integer (int/float args)
// f: float (int args)
// F: double (int args)
// H: half (int args)
// d: default
// g: default, ignore 'Q' size modifier.
// j: default, force 'Q' size modifier.
@ -345,6 +346,7 @@ def OP_MLSLHi : Op<(call "vmlsl", $p0, (call "vget_high", $p1),
(call "vget_high", $p2))>;
def OP_MLSLHi_N : Op<(call "vmlsl_n", $p0, (call "vget_high", $p1), $p2)>;
def OP_MUL_N : Op<(op "*", $p0, (dup $p1))>;
def OP_MULX_N : Op<(call "vmulx", $p0, (dup $p1))>;
def OP_MLA_N : Op<(op "+", $p0, (op "*", $p1, (dup $p2)))>;
def OP_MLS_N : Op<(op "-", $p0, (op "*", $p1, (dup $p2)))>;
def OP_FMLA_N : Op<(call "vfma", $p0, $p1, (dup $p2))>;
@ -1661,3 +1663,186 @@ def SCALAR_SQRDMLSH_LANEQ : SOpInst<"vqrdmlsh_laneq", "sssji", "SsSi", OP_SCALAR
def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
}
// ARMv8.2-A FP16 intrinsics.
let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarch64__)" in {
// ARMv8.2-A FP16 one-operand vector intrinsics.
// Comparison
def CMEQH : SInst<"vceqz", "ud", "hQh">;
def CMGEH : SInst<"vcgez", "ud", "hQh">;
def CMGTH : SInst<"vcgtz", "ud", "hQh">;
def CMLEH : SInst<"vclez", "ud", "hQh">;
def CMLTH : SInst<"vcltz", "ud", "hQh">;
// Vector conversion
def VCVT_F16 : SInst<"vcvt_f16", "Hd", "sUsQsQUs">;
def VCVT_S16 : SInst<"vcvt_s16", "xd", "hQh">;
def VCVT_U16 : SInst<"vcvt_u16", "ud", "hQh">;
def VCVTA_S16 : SInst<"vcvta_s16", "xd", "hQh">;
def VCVTA_U16 : SInst<"vcvta_u16", "ud", "hQh">;
def VCVTM_S16 : SInst<"vcvtm_s16", "xd", "hQh">;
def VCVTM_U16 : SInst<"vcvtm_u16", "ud", "hQh">;
def VCVTN_S16 : SInst<"vcvtn_s16", "xd", "hQh">;
def VCVTN_U16 : SInst<"vcvtn_u16", "ud", "hQh">;
def VCVTP_S16 : SInst<"vcvtp_s16", "xd", "hQh">;
def VCVTP_U16 : SInst<"vcvtp_u16", "ud", "hQh">;
// Vector rounding
def FRINTZH : SInst<"vrnd", "dd", "hQh">;
def FRINTNH : SInst<"vrndn", "dd", "hQh">;
def FRINTAH : SInst<"vrnda", "dd", "hQh">;
def FRINTPH : SInst<"vrndp", "dd", "hQh">;
def FRINTMH : SInst<"vrndm", "dd", "hQh">;
def FRINTXH : SInst<"vrndx", "dd", "hQh">;
def FRINTIH : SInst<"vrndi", "dd", "hQh">;
// Misc.
def VABSH : SInst<"vabs", "dd", "hQh">;
def VNEGH : SOpInst<"vneg", "dd", "hQh", OP_NEG>;
def VRECPEH : SInst<"vrecpe", "dd", "hQh">;
def FRSQRTEH : SInst<"vrsqrte", "dd", "hQh">;
def FSQRTH : SInst<"vsqrt", "dd", "hQh">;
// ARMv8.2-A FP16 two-operands vector intrinsics.
// Misc.
def VADDH : SOpInst<"vadd", "ddd", "hQh", OP_ADD>;
def VABDH : SInst<"vabd", "ddd", "hQh">;
def VSUBH : SOpInst<"vsub", "ddd", "hQh", OP_SUB>;
// Comparison
let InstName = "vacge" in {
def VCAGEH : SInst<"vcage", "udd", "hQh">;
def VCALEH : SInst<"vcale", "udd", "hQh">;
}
let InstName = "vacgt" in {
def VCAGTH : SInst<"vcagt", "udd", "hQh">;
def VCALTH : SInst<"vcalt", "udd", "hQh">;
}
def VCEQH : SOpInst<"vceq", "udd", "hQh", OP_EQ>;
def VCGEH : SOpInst<"vcge", "udd", "hQh", OP_GE>;
def VCGTH : SOpInst<"vcgt", "udd", "hQh", OP_GT>;
let InstName = "vcge" in
def VCLEH : SOpInst<"vcle", "udd", "hQh", OP_LE>;
let InstName = "vcgt" in
def VCLTH : SOpInst<"vclt", "udd", "hQh", OP_LT>;
// Vector conversion
let isVCVT_N = 1 in {
def VCVT_N_F16 : SInst<"vcvt_n_f16", "Hdi", "sUsQsQUs">;
def VCVT_N_S16 : SInst<"vcvt_n_s16", "xdi", "hQh">;
def VCVT_N_U16 : SInst<"vcvt_n_u16", "udi", "hQh">;
}
// Max/Min
def VMAXH : SInst<"vmax", "ddd", "hQh">;
def VMINH : SInst<"vmin", "ddd", "hQh">;
def FMAXNMH : SInst<"vmaxnm", "ddd", "hQh">;
def FMINNMH : SInst<"vminnm", "ddd", "hQh">;
// Multiplication/Division
def VMULH : SOpInst<"vmul", "ddd", "hQh", OP_MUL>;
def MULXH : SInst<"vmulx", "ddd", "hQh">;
def FDIVH : IOpInst<"vdiv", "ddd", "hQh", OP_DIV>;
// Pairwise addition
def VPADDH : SInst<"vpadd", "ddd", "hQh">;
// Pairwise Max/Min
def VPMAXH : SInst<"vpmax", "ddd", "hQh">;
def VPMINH : SInst<"vpmin", "ddd", "hQh">;
// Pairwise MaxNum/MinNum
def FMAXNMPH : SInst<"vpmaxnm", "ddd", "hQh">;
def FMINNMPH : SInst<"vpminnm", "ddd", "hQh">;
// Reciprocal/Sqrt
def VRECPSH : SInst<"vrecps", "ddd", "hQh">;
def VRSQRTSH : SInst<"vrsqrts", "ddd", "hQh">;
// ARMv8.2-A FP16 three-operands vector intrinsics.
// Vector fused multiply-add operations
def VFMAH : SInst<"vfma", "dddd", "hQh">;
def VFMSH : SOpInst<"vfms", "dddd", "hQh", OP_FMLS>;
// ARMv8.2-A FP16 lane vector intrinsics.
// FMA lane
def VFMA_LANEH : IInst<"vfma_lane", "dddgi", "hQh">;
def VFMA_LANEQH : IInst<"vfma_laneq", "dddji", "hQh">;
// FMA lane with scalar argument
def FMLA_NH : SOpInst<"vfma_n", "ddds", "hQh", OP_FMLA_N>;
// Scalar floating point fused multiply-add (scalar, by element)
def SCALAR_FMLA_LANEH : IInst<"vfma_lane", "sssdi", "Sh">;
def SCALAR_FMLA_LANEQH : IInst<"vfma_laneq", "sssji", "Sh">;
// FMS lane
def VFMS_LANEH : IOpInst<"vfms_lane", "dddgi", "hQh", OP_FMS_LN>;
def VFMS_LANEQH : IOpInst<"vfms_laneq", "dddji", "hQh", OP_FMS_LNQ>;
// FMS lane with scalar argument
def FMLS_NH : SOpInst<"vfms_n", "ddds", "hQh", OP_FMLS_N>;
// Scalar floating foint fused multiply-subtract (scalar, by element)
def SCALAR_FMLS_LANEH : IOpInst<"vfms_lane", "sssdi", "Sh", OP_FMS_LN>;
def SCALAR_FMLS_LANEQH : IOpInst<"vfms_laneq", "sssji", "Sh", OP_FMS_LNQ>;
// Mul lane
def VMUL_LANEH : IOpInst<"vmul_lane", "ddgi", "hQh", OP_MUL_LN>;
def VMUL_LANEQH : IOpInst<"vmul_laneq", "ddji", "hQh", OP_MUL_LN>;
def VMUL_NH : IOpInst<"vmul_n", "dds", "hQh", OP_MUL_N>;
// Scalar floating point multiply (scalar, by element)
def SCALAR_FMUL_LANEH : IOpInst<"vmul_lane", "ssdi", "Sh", OP_SCALAR_MUL_LN>;
def SCALAR_FMUL_LANEQH : IOpInst<"vmul_laneq", "ssji", "Sh", OP_SCALAR_MUL_LN>;
// Mulx lane
def VMULX_LANEH : IOpInst<"vmulx_lane", "ddgi", "hQh", OP_MULX_LN>;
def VMULX_LANEQH : IOpInst<"vmulx_laneq", "ddji", "hQh", OP_MULX_LN>;
def VMULX_NH : IOpInst<"vmulx_n", "dds", "hQh", OP_MULX_N>;
// TODO: Scalar floating point multiply extended (scalar, by element)
// Below ones are commented out because they need vmulx_f16(float16_t, float16_t)
// which will be implemented later with fp16 scalar intrinsic (arm_fp16.h)
//def SCALAR_FMULX_LANEH : IOpInst<"vmulx_lane", "ssdi", "Sh", OP_SCALAR_MUL_LN>;
//def SCALAR_FMULX_LANEQH : IOpInst<"vmulx_laneq", "ssji", "Sh", OP_SCALAR_MUL_LN>;
// ARMv8.2-A FP16 reduction vector intrinsics.
def VMAXVH : SInst<"vmaxv", "sd", "hQh">;
def VMINVH : SInst<"vminv", "sd", "hQh">;
def FMAXNMVH : SInst<"vmaxnmv", "sd", "hQh">;
def FMINNMVH : SInst<"vminnmv", "sd", "hQh">;
// Data processing intrinsics - section 5
// Logical operations
let isHiddenLInst = 1 in
def VBSLH : SInst<"vbsl", "dudd", "hQh">;
// Transposition operations
def VZIPH : WInst<"vzip", "2dd", "hQh">;
def VUZPH : WInst<"vuzp", "2dd", "hQh">;
def VTRNH : WInst<"vtrn", "2dd", "hQh">;
// Set all lanes to same value.
/* Already implemented prior to ARMv8.2-A.
def VMOV_NH : WOpInst<"vmov_n", "ds", "hQh", OP_DUP>;
def VDUP_NH : WOpInst<"vdup_n", "ds", "hQh", OP_DUP>;
def VDUP_LANE1H : WOpInst<"vdup_lane", "dgi", "hQh", OP_DUP_LN>;*/
// Vector Extract
def VEXTH : WInst<"vext", "dddi", "hQh">;
// Reverse vector elements
def VREV64H : WOpInst<"vrev64", "dd", "hQh", OP_REV64>;
// Permutation
def VTRN1H : SOpInst<"vtrn1", "ddd", "hQh", OP_TRN1>;
def VZIP1H : SOpInst<"vzip1", "ddd", "hQh", OP_ZIP1>;
def VUZP1H : SOpInst<"vuzp1", "ddd", "hQh", OP_UZP1>;
def VTRN2H : SOpInst<"vtrn2", "ddd", "hQh", OP_TRN2>;
def VZIP2H : SOpInst<"vzip2", "ddd", "hQh", OP_ZIP2>;
def VUZP2H : SOpInst<"vuzp2", "ddd", "hQh", OP_UZP2>;
def SCALAR_VDUP_LANEH : IInst<"vdup_lane", "sdi", "Sh">;
def SCALAR_VDUP_LANEQH : IInst<"vdup_laneq", "sji", "Sh">;
}

View File

@ -134,7 +134,6 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">,
//===----------------------------------------------------------------------===//
let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
def debug_info_macro : Flag<["-"], "debug-info-macro">,
HelpText<"Emit macro debug information">;
@ -144,20 +143,22 @@ def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
HelpText<"The compilation directory to embed in the debug info.">;
def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
HelpText<"The string to embed in the Dwarf debug flags record.">;
def compress_debug_sections : Flag<["-", "--"], "compress-debug-sections">,
HelpText<"DWARF debug sections compression">;
def compress_debug_sections_EQ : Flag<["-"], "compress-debug-sections=">,
HelpText<"DWARF debug sections compression type">;
def mno_exec_stack : Flag<["-"], "mnoexecstack">,
HelpText<"Mark the file as not needing an executable stack">;
def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">,
HelpText<"Make assembler warnings fatal">;
def mrelax_relocations : Flag<["--"], "mrelax-relocations">,
HelpText<"Use relaxable elf relocations">;
def compress_debug_sections : Flag<["-"], "compress-debug-sections">,
HelpText<"Compress DWARF debug sections using zlib">;
def msave_temp_labels : Flag<["-"], "msave-temp-labels">,
HelpText<"Save temporary labels in the symbol table. "
"Note this may change .s semantics and shouldn't generally be used "
"on compiler-generated code.">;
def mrelocation_model : Separate<["-"], "mrelocation-model">,
HelpText<"The relocation model to use">;
HelpText<"The relocation model to use">, Values<"static,pic,ropi,rwpi,ropi-rwpi,dynamic-no-pic">;
def fno_math_builtin : Flag<["-"], "fno-math-builtin">,
HelpText<"Disable implicit builtin knowledge of math functions">;
}
@ -228,7 +229,7 @@ def no_struct_path_tbaa : Flag<["-"], "no-struct-path-tbaa">,
def masm_verbose : Flag<["-"], "masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<["-"], "mcode-model">,
HelpText<"The code model to use">;
HelpText<"The code model to use">, Values<"small,kernel,medium,large">;
def mdebug_pass : Separate<["-"], "mdebug-pass">,
HelpText<"Enable additional debug output">;
def mdisable_fp_elim : Flag<["-"], "mdisable-fp-elim">,
@ -307,7 +308,7 @@ def fsanitize_coverage_no_prune
HelpText<"Disable coverage pruning (i.e. instrument all blocks/edges)">;
def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">,
HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, "
"or none">;
"or none">, Values<"none,clang,llvm">;
def fprofile_instrument_path_EQ : Joined<["-"], "fprofile-instrument-path=">,
HelpText<"Generate instrumented code to collect execution counts into "
"<file> (overridden by LLVM_PROFILE_FILE env var)">;
@ -347,9 +348,9 @@ def diagnostic_serialized_file : Separate<["-"], "serialize-diagnostic-file">,
HelpText<"File for serializing diagnostics in a binary format">;
def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">,
HelpText<"Change diagnostic formatting to match IDE and command line tools">;
HelpText<"Change diagnostic formatting to match IDE and command line tools">, Values<"clang,msvc,msvc-fallback,vi">;
def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">,
HelpText<"Print diagnostic category">;
HelpText<"Print diagnostic category">, Values<"none,id,name">;
def fno_diagnostics_use_presumed_location : Flag<["-"], "fno-diagnostics-use-presumed-location">,
HelpText<"Ignore #line directives when displaying diagnostic locations">;
def ftabstop : Separate<["-"], "ftabstop">, MetaVarName<"<N>">,
@ -594,11 +595,11 @@ def fconstant_string_class : Separate<["-"], "fconstant-string-class">,
MetaVarName<"<class name>">,
HelpText<"Specify the class to use for constant Objective-C string objects.">;
def fobjc_arc_cxxlib_EQ : Joined<["-"], "fobjc-arc-cxxlib=">,
HelpText<"Objective-C++ Automatic Reference Counting standard library kind">;
HelpText<"Objective-C++ Automatic Reference Counting standard library kind">, Values<"libc++,libstdc++,none">;
def fobjc_runtime_has_weak : Flag<["-"], "fobjc-runtime-has-weak">,
HelpText<"The target Objective-C runtime supports ARC weak operations">;
def fobjc_dispatch_method_EQ : Joined<["-"], "fobjc-dispatch-method=">,
HelpText<"Objective-C dispatch method to use">;
HelpText<"Objective-C dispatch method to use">, Values<"legacy,non-legacy,mixed">;
def disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-default-synthesize-properties">,
HelpText<"disable the default synthesis of Objective-C properties">;
def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">,
@ -672,7 +673,7 @@ def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and
def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
HelpText<"Allow function arguments and returns of type half">;
def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
HelpText<"Set default MS calling convention">;
HelpText<"Set default MS calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall">;
def finclude_default_header : Flag<["-"], "finclude-default-header">,
HelpText<"Include the default header file for OpenCL">;
def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">,

View File

@ -39,8 +39,9 @@ enum ClangFlags {
enum ID {
OPT_INVALID = 0, // This is not an option ID.
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR) OPT_##ID,
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES) \
OPT_##ID,
#include "clang/Driver/Options.inc"
LastOption
#undef OPTION

View File

@ -493,7 +493,7 @@ def cl_mad_enable : Flag<["-"], "cl-mad-enable">, Group<opencl_Group>, Flags<[CC
def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow use of less precise no signed zeros computations in the generated binary.">;
def cl_std_EQ : Joined<["-"], "cl-std=">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL language standard to compile for.">;
HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0">;
def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow denormals to be flushed to zero.">;
def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">, Group<opencl_Group>, Flags<[CC1Option]>,
@ -804,7 +804,7 @@ def fno_sanitize_coverage
: CommaJoined<["-"], "fno-sanitize-coverage=">,
Group<f_clang_Group>, Flags<[CoreOption, DriverOption]>,
HelpText<"Disable specified features of coverage instrumentation for "
"Sanitizers">;
"Sanitizers">, Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep,8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters">;
def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">,
Group<f_clang_Group>,
HelpText<"Enable origins tracking in MemorySanitizer">;
@ -923,7 +923,7 @@ def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>, Flags<[CC1Op
def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>, Flags<[CC1Option]>;
def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
" | on (according to FP_CONTRACT pragma, default) | off (never fuse)">;
" | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, Values<"fast,on,off">;
def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
@ -1000,7 +1000,7 @@ def flat__namespace : Flag<["-"], "flat_namespace">;
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
HelpText<"Set LTO mode to either 'full' or 'thin'">;
HelpText<"Set LTO mode to either 'full' or 'thin'">, Values<"thin,full">;
def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
HelpText<"Enable LTO in 'full' mode">;
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>,
@ -1158,7 +1158,7 @@ def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-m
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Disables an experimental new pass manager in LLVM.">;
def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use the given vector functions library">;
HelpText<"Use the given vector functions library">, Values<"Accelerate,SVML,none">;
def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
@ -1342,7 +1342,7 @@ def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, Flags<[CC1
HelpText<"Force wchar_t to be an unsigned int">;
def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Which overload candidates to show when overload resolution fails: "
"best|all; defaults to all">;
"best|all; defaults to all">, Values<"best,all">;
def fshow_column : Flag<["-"], "fshow-column">, Group<f_Group>, Flags<[CC1Option]>;
def fshow_source_location : Flag<["-"], "fshow-source-location">, Group<f_Group>;
def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>;
@ -1456,7 +1456,7 @@ def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1
def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group<clang_ignored_f_Group>;
def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
HelpText<"Set the default symbol visibility for all global declarations">;
HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">;
def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>,
HelpText<"Give inline C++ member functions default visibility by default">,
Flags<[CC1Option]>;
@ -1563,6 +1563,10 @@ def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>;
def gmodules : Flag <["-"], "gmodules">, Group<gN_Group>,
HelpText<"Generate debug info with external references to clang modules"
" or precompiled headers">;
def gz : Flag<["-"], "gz">, Group<g_flags_Group>,
HelpText<"DWARF debug sections compression type">;
def gz_EQ : Joined<["-"], "gz=">, Group<g_flags_Group>,
HelpText<"DWARF debug sections compression type">;
def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption]>,
HelpText<"Display available options">;
@ -1677,7 +1681,7 @@ def minline_all_stringops : Flag<["-"], "minline-all-stringops">, Group<clang_ig
def mno_inline_all_stringops : Flag<["-"], "mno-inline-all-stringops">, Group<clang_ignored_m_Group>;
def malign_double : Flag<["-"], "malign-double">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Align doubles to two words in structs (x86 only)">;
def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>;
def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>, Values<"soft,softfp,hard">;
def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>;
def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>;
@ -1709,9 +1713,9 @@ def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags
def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the stack probe size">;
def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"The thread model to use, e.g. posix, single (posix by default)">;
HelpText<"The thread model to use, e.g. posix, single (posix by default)">, Values<"posix,single">;
def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">;
HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">, Values<"default,4,5,gnu">;
def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>;
def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>;
@ -2205,7 +2209,7 @@ def std_default_EQ : Joined<["-"], "std-default=">;
def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>,
Group<CompileOnly_Group>, HelpText<"Language standard to compile for">;
def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>,
HelpText<"C++ standard library to use">;
HelpText<"C++ standard library to use">, Values<"libc++,libstdc++,platform">;
def sub__library : JoinedOrSeparate<["-"], "sub_library">;
def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">;
def system_header_prefix : Joined<["--"], "system-header-prefix=">,

View File

@ -17,6 +17,7 @@
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Allocator.h"
#include <map>
#include <tuple>
namespace clang {
class LangOptions;
@ -41,10 +42,20 @@ class EditedSource {
typedef std::map<FileOffset, FileEdit> FileEditsTy;
FileEditsTy FileEdits;
// Location of argument use inside the macro body
typedef std::pair<IdentifierInfo*, SourceLocation> MacroArgUse;
llvm::DenseMap<unsigned, SmallVector<MacroArgUse, 2>>
ExpansionToArgMap;
struct MacroArgUse {
IdentifierInfo *Identifier;
SourceLocation ImmediateExpansionLoc;
// Location of argument use inside the top-level macro
SourceLocation UseLoc;
bool operator==(const MacroArgUse &Other) const {
return std::tie(Identifier, ImmediateExpansionLoc, UseLoc) ==
std::tie(Other.Identifier, Other.ImmediateExpansionLoc,
Other.UseLoc);
}
};
llvm::DenseMap<unsigned, SmallVector<MacroArgUse, 2>> ExpansionToArgMap;
SmallVector<std::pair<SourceLocation, MacroArgUse>, 2>
CurrCommitMacroArgExps;

View File

@ -184,9 +184,23 @@ struct FormatStyle {
enum ShortFunctionStyle {
/// \brief Never merge functions into a single line.
SFS_None,
/// \brief Only merge functions defined inside a class. Same as "inline",
/// except it does not implies "empty": i.e. top level empty functions
/// are not merged either.
/// \code
/// class Foo {
/// void f() { foo(); }
/// };
/// void f() {
/// foo();
/// }
/// void f() {
/// }
/// \endcode
SFS_InlineOnly,
/// \brief Only merge empty functions.
/// \code
/// void f() { bar(); }
/// void f() {}
/// void f2() {
/// bar2();
/// }
@ -197,6 +211,10 @@ struct FormatStyle {
/// class Foo {
/// void f() { foo(); }
/// };
/// void f() {
/// foo();
/// }
/// void f() {}
/// \endcode
SFS_Inline,
/// \brief Merge all functions fitting on a single line.
@ -634,12 +652,12 @@ struct FormatStyle {
/// struct foo
/// {
/// int x;
/// }
/// };
///
/// false:
/// struct foo {
/// int x;
/// }
/// };
/// \endcode
bool AfterStruct;
/// \brief Wrap union definitions.
@ -715,7 +733,7 @@ struct FormatStyle {
/// ? firstValue
/// : SecondValueVeryVeryVeryVeryLong;
///
/// true:
/// false:
/// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription ?
/// firstValue :
/// SecondValueVeryVeryVeryVeryLong;
@ -723,8 +741,7 @@ struct FormatStyle {
bool BreakBeforeTernaryOperators;
/// \brief Different ways to break initializers.
enum BreakConstructorInitializersStyle
{
enum BreakConstructorInitializersStyle {
/// Break constructor initializers before the colon and after the commas.
/// \code
/// Constructor()
@ -749,7 +766,7 @@ struct FormatStyle {
BCIS_AfterColon
};
/// \brief The constructor initializers style to use..
/// \brief The constructor initializers style to use.
BreakConstructorInitializersStyle BreakConstructorInitializers;
/// \brief Break after each annotation on a field in Java files.
@ -1253,6 +1270,14 @@ struct FormatStyle {
/// \endcode
bool SortIncludes;
/// \brief If ``true``, clang-format will sort using declarations.
/// \code
/// false: true:
/// using std::cout; vs. using std::cin;
/// using std::cin; using std::cout;
/// \endcode
bool SortUsingDeclarations;
/// \brief If ``true``, a space is inserted after C style casts.
/// \code
/// true: false:
@ -1641,6 +1666,16 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
ArrayRef<tooling::Range> Ranges,
StringRef FileName = "<stdin>");
/// \brief Sort consecutive using declarations in the given \p Ranges in
/// \p Code.
///
/// Returns the ``Replacements`` that sort the using declarations in all
/// \p Ranges in \p Code.
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName = "<stdin>");
/// \brief Returns the ``LangOpts`` that the formatter expects you to set.
///
/// \param Style determines specific settings for lexing mode.

View File

@ -25,6 +25,7 @@
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Frontend/PrecompiledPreamble.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
@ -199,103 +200,15 @@ class ASTUnit {
/// of that loading. It must be cleared when preamble is recreated.
llvm::StringMap<SourceLocation> PreambleSrcLocCache;
public:
class PreambleData {
const FileEntry *File;
std::vector<char> Buffer;
mutable unsigned NumLines;
public:
PreambleData() : File(nullptr), NumLines(0) { }
void assign(const FileEntry *F, const char *begin, const char *end) {
File = F;
Buffer.assign(begin, end);
NumLines = 0;
}
void clear() { Buffer.clear(); File = nullptr; NumLines = 0; }
size_t size() const { return Buffer.size(); }
bool empty() const { return Buffer.empty(); }
const char *getBufferStart() const { return &Buffer[0]; }
unsigned getNumLines() const {
if (NumLines)
return NumLines;
countLines();
return NumLines;
}
SourceRange getSourceRange(const SourceManager &SM) const {
SourceLocation FileLoc = SM.getLocForStartOfFile(SM.getPreambleFileID());
return SourceRange(FileLoc, FileLoc.getLocWithOffset(size()-1));
}
private:
void countLines() const;
};
const PreambleData &getPreambleData() const {
return Preamble;
}
/// Data used to determine if a file used in the preamble has been changed.
struct PreambleFileHash {
/// All files have size set.
off_t Size;
/// Modification time is set for files that are on disk. For memory
/// buffers it is zero.
time_t ModTime;
/// Memory buffers have MD5 instead of modification time. We don't
/// compute MD5 for on-disk files because we hope that modification time is
/// enough to tell if the file was changed.
llvm::MD5::MD5Result MD5;
static PreambleFileHash createForFile(off_t Size, time_t ModTime);
static PreambleFileHash
createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
friend bool operator==(const PreambleFileHash &LHS,
const PreambleFileHash &RHS);
friend bool operator!=(const PreambleFileHash &LHS,
const PreambleFileHash &RHS) {
return !(LHS == RHS);
}
};
private:
/// \brief The contents of the preamble that has been precompiled to
/// \c PreambleFile.
PreambleData Preamble;
/// \brief Whether the preamble ends at the start of a new line.
///
/// Used to inform the lexer as to whether it's starting at the beginning of
/// a line after skipping the preamble.
bool PreambleEndsAtStartOfLine;
/// \brief Keeps track of the files that were used when computing the
/// preamble, with both their buffer size and their modification time.
///
/// If any of the files have changed from one compile to the next,
/// the preamble must be thrown away.
llvm::StringMap<PreambleFileHash> FilesInPreamble;
/// The contents of the preamble.
llvm::Optional<PrecompiledPreamble> Preamble;
/// \brief When non-NULL, this is the buffer used to store the contents of
/// the main file when it has been padded for use with the precompiled
/// preamble.
std::unique_ptr<llvm::MemoryBuffer> SavedMainFileBuffer;
/// \brief When non-NULL, this is the buffer used to store the
/// contents of the preamble when it has been padded to build the
/// precompiled preamble.
std::unique_ptr<llvm::MemoryBuffer> PreambleBuffer;
/// \brief The number of warnings that occurred while parsing the preamble.
///
/// This value will be used to restore the state of the \c DiagnosticsEngine
@ -438,21 +351,6 @@ class ASTUnit {
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
struct ComputedPreamble {
llvm::MemoryBuffer *Buffer;
std::unique_ptr<llvm::MemoryBuffer> Owner;
unsigned Size;
bool PreambleEndsAtStartOfLine;
ComputedPreamble(llvm::MemoryBuffer *Buffer,
std::unique_ptr<llvm::MemoryBuffer> Owner, unsigned Size,
bool PreambleEndsAtStartOfLine)
: Buffer(Buffer), Owner(std::move(Owner)), Size(Size),
PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
};
ComputedPreamble ComputePreamble(CompilerInvocation &Invocation,
unsigned MaxLines,
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const CompilerInvocation &PreambleInvocationIn,
@ -607,12 +505,6 @@ class ASTUnit {
void findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
SmallVectorImpl<Decl *> &Decls);
/// \brief Add a new top-level declaration, identified by its ID in
/// the precompiled preamble.
void addTopLevelDeclFromPreamble(serialization::DeclID D) {
TopLevelDeclsInPreamble.push_back(D);
}
/// \brief Retrieve a reference to the current top-level name hash value.
///
/// Note: This is used internally by the top-level tracking action

View File

@ -0,0 +1,248 @@
//===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Helper class to build precompiled preamble.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
#define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/MD5.h"
#include <memory>
#include <system_error>
#include <type_traits>
namespace llvm {
class MemoryBuffer;
}
namespace clang {
namespace vfs {
class FileSystem;
}
class CompilerInstance;
class CompilerInvocation;
class DeclGroupRef;
class PCHContainerOperations;
/// A size of the preamble and a flag required by
/// PreprocessorOptions::PrecompiledPreambleBytes.
struct PreambleBounds {
PreambleBounds(unsigned Size, bool PreambleEndsAtStartOfLine)
: Size(Size), PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
/// \brief Size of the preamble in bytes.
unsigned Size;
/// \brief Whether the preamble ends at the start of a new line.
///
/// Used to inform the lexer as to whether it's starting at the beginning of
/// a line after skipping the preamble.
bool PreambleEndsAtStartOfLine;
};
/// \brief Runs lexer to compute suggested preamble bounds.
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
llvm::MemoryBuffer *Buffer,
unsigned MaxLines);
class PreambleCallbacks;
/// A class holding a PCH and all information to check whether it is valid to
/// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and
/// CanReusePreamble + AddImplicitPreamble to make use of it.
class PrecompiledPreamble {
class TempPCHFile;
struct PreambleFileHash;
public:
/// \brief Try to build PrecompiledPreamble for \p Invocation. See
/// BuildPreambleError for possible error codes.
///
/// \param Invocation Original CompilerInvocation with options to compile the
/// file.
///
/// \param MainFileBuffer Buffer with the contents of the main file.
///
/// \param Bounds Bounds of the preamble, result of calling
/// ComputePreambleBounds.
///
/// \param Diagnostics Diagnostics engine to be used while building the
/// preamble.
///
/// \param VFS An instance of vfs::FileSystem to be used for file
/// accesses.
///
/// \param PCHContainerOps An instance of PCHContainerOperations.
///
/// \param Callbacks A set of callbacks to be executed when building
/// the preamble.
static llvm::ErrorOr<PrecompiledPreamble>
Build(const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
PreambleCallbacks &Callbacks);
PrecompiledPreamble(PrecompiledPreamble &&) = default;
PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
/// PreambleBounds used to build the preamble
PreambleBounds getBounds() const;
/// Check whether PrecompiledPreamble can be reused for the new contents(\p
/// MainFileBuffer) of the main file.
bool CanReuse(const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
vfs::FileSystem *VFS) const;
/// Changes options inside \p CI to use PCH from this preamble. Also remaps
/// main file to \p MainFileBuffer.
void AddImplicitPreamble(CompilerInvocation &CI,
llvm::MemoryBuffer *MainFileBuffer) const;
private:
PrecompiledPreamble(TempPCHFile PCHFile, std::vector<char> PreambleBytes,
bool PreambleEndsAtStartOfLine,
llvm::StringMap<PreambleFileHash> FilesInPreamble);
/// A temp file that would be deleted on destructor call. If destructor is not
/// called for any reason, the file will be deleted at static objects'
/// destruction.
/// An assertion will fire if two TempPCHFiles are created with the same name,
/// so it's not intended to be used outside preamble-handling.
class TempPCHFile {
public:
// A main method used to construct TempPCHFile.
static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
/// Call llvm::sys::fs::createTemporaryFile to create a new temporary file.
static llvm::ErrorOr<TempPCHFile> createInSystemTempDir(const Twine &Prefix,
StringRef Suffix);
/// Create a new instance of TemporaryFile for file at \p Path. Use with
/// extreme caution, there's an assertion checking that there's only a
/// single instance of TempPCHFile alive for each path.
static llvm::ErrorOr<TempPCHFile> createFromCustomPath(const Twine &Path);
private:
TempPCHFile(std::string FilePath);
public:
TempPCHFile(TempPCHFile &&Other);
TempPCHFile &operator=(TempPCHFile &&Other);
TempPCHFile(const TempPCHFile &) = delete;
~TempPCHFile();
/// A path where temporary file is stored.
llvm::StringRef getFilePath() const;
private:
void RemoveFileIfPresent();
private:
llvm::Optional<std::string> FilePath;
};
/// Data used to determine if a file used in the preamble has been changed.
struct PreambleFileHash {
/// All files have size set.
off_t Size = 0;
/// Modification time is set for files that are on disk. For memory
/// buffers it is zero.
time_t ModTime = 0;
/// Memory buffers have MD5 instead of modification time. We don't
/// compute MD5 for on-disk files because we hope that modification time is
/// enough to tell if the file was changed.
llvm::MD5::MD5Result MD5 = {};
static PreambleFileHash createForFile(off_t Size, time_t ModTime);
static PreambleFileHash
createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
friend bool operator==(const PreambleFileHash &LHS,
const PreambleFileHash &RHS) {
return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
LHS.MD5 == RHS.MD5;
}
friend bool operator!=(const PreambleFileHash &LHS,
const PreambleFileHash &RHS) {
return !(LHS == RHS);
}
};
/// Manages the lifetime of temporary file that stores a PCH.
TempPCHFile PCHFile;
/// Keeps track of the files that were used when computing the
/// preamble, with both their buffer size and their modification time.
///
/// If any of the files have changed from one compile to the next,
/// the preamble must be thrown away.
llvm::StringMap<PreambleFileHash> FilesInPreamble;
/// The contents of the file that was used to precompile the preamble. Only
/// contains first PreambleBounds::Size bytes. Used to compare if the relevant
/// part of the file has not changed, so that preamble can be reused.
std::vector<char> PreambleBytes;
/// See PreambleBounds::PreambleEndsAtStartOfLine
bool PreambleEndsAtStartOfLine;
};
/// A set of callbacks to gather useful information while building a preamble.
class PreambleCallbacks {
public:
virtual ~PreambleCallbacks() = default;
/// Called after FrontendAction::Execute(), but before
/// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
/// various CompilerInstance fields before they are destroyed.
virtual void AfterExecute(CompilerInstance &CI);
/// Called after PCH has been emitted. \p Writer may be used to retrieve
/// information about AST, serialized in PCH.
virtual void AfterPCHEmitted(ASTWriter &Writer);
/// Called for each TopLevelDecl.
/// NOTE: To allow more flexibility a custom ASTConsumer could probably be
/// used instead, but having only this method allows a simpler API.
virtual void HandleTopLevelDecl(DeclGroupRef DG);
/// Called for each macro defined in the Preamble.
/// NOTE: To allow more flexibility a custom PPCallbacks could probably be
/// used instead, but having only this method allows a simpler API.
virtual void HandleMacroDefined(const Token &MacroNameTok,
const MacroDirective *MD);
};
enum class BuildPreambleError {
PreambleIsEmpty = 1,
CouldntCreateTempFile,
CouldntCreateTargetInfo,
CouldntCreateVFSOverlay,
BeginSourceFileFailed,
CouldntEmitPCH
};
class BuildPreambleErrorCategory final : public std::error_category {
public:
const char *name() const noexcept override;
std::string message(int condition) const override;
};
std::error_code make_error_code(BuildPreambleError Error);
} // namespace clang
namespace std {
template <>
struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
} // namespace std
#endif

View File

@ -1835,11 +1835,20 @@ class Preprocessor {
/// \brief A fast PTH version of SkipExcludedConditionalBlock.
void PTHSkipExcludedConditionalBlock();
/// Information about the result for evaluating an expression for a
/// preprocessor directive.
struct DirectiveEvalResult {
/// Whether the expression was evaluated as true or not.
bool Conditional;
/// True if the expression contained identifiers that were undefined.
bool IncludedUndefinedIds;
};
/// \brief Evaluate an integer constant expression that may occur after a
/// \#if or \#elif directive and return it as a bool.
/// \#if or \#elif directive and return a \p DirectiveEvalResult object.
///
/// If the expression is equivalent to "!defined(X)" return X in IfNDefMacro.
bool EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro);
DirectiveEvalResult EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro);
/// \brief Install the standard preprocessor pragmas:
/// \#pragma GCC poison/system_header/dependency and \#pragma once.

View File

@ -96,8 +96,15 @@ class PreprocessorOptions {
std::string TokenCache;
/// When enabled, preprocessor is in a mode for parsing a single file only.
///
/// Disables #includes of other files and if there are unresolved identifiers
/// in preprocessor directive conditions it causes all blocks to be parsed so
/// that the client can get the maximum amount of information from the parser.
bool SingleFileParseMode = false;
/// When enabled, the preprocessor will construct editor placeholder tokens.
bool LexEditorPlaceholders = true;
/// \brief True if the SourceManager should report the original file name for
/// contents of files that were remapped to other files. Defaults to true.
bool RemappedFilesKeepOriginalName;
@ -185,6 +192,7 @@ class PreprocessorOptions {
ImplicitPTHInclude.clear();
TokenCache.clear();
SingleFileParseMode = false;
LexEditorPlaceholders = true;
RetainRemappedFileBuffers = true;
PrecompiledPreambleBytes.first = 0;
PrecompiledPreambleBytes.second = 0;

View File

@ -604,7 +604,7 @@ class Parser : public CodeCompletionHandler {
}
/// getTypeAnnotation - Read a parsed type out of an annotation token.
static ParsedType getTypeAnnotation(Token &Tok) {
static ParsedType getTypeAnnotation(const Token &Tok) {
return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
}
@ -615,7 +615,7 @@ class Parser : public CodeCompletionHandler {
/// \brief Read an already-translated primary expression out of an annotation
/// token.
static ExprResult getExprAnnotation(Token &Tok) {
static ExprResult getExprAnnotation(const Token &Tok) {
return ExprResult::getFromOpaquePointer(Tok.getAnnotationValue());
}
@ -1852,6 +1852,7 @@ class Parser : public CodeCompletionHandler {
DSC_trailing, // C++11 trailing-type-specifier in a trailing return type
DSC_alias_declaration, // C++11 type-specifier-seq in an alias-declaration
DSC_top_level, // top-level/namespace declaration context
DSC_template_param, // template parameter context
DSC_template_type_arg, // template type argument context
DSC_objc_method_result, // ObjC method result context, enables 'instancetype'
DSC_condition // condition declaration context
@ -1862,6 +1863,7 @@ class Parser : public CodeCompletionHandler {
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:
@ -1882,6 +1884,7 @@ class Parser : public CodeCompletionHandler {
static bool isClassTemplateDeductionContext(DeclSpecContext DSC) {
switch (DSC) {
case DSC_normal:
case DSC_template_param:
case DSC_class:
case DSC_top_level:
case DSC_condition:

View File

@ -2153,7 +2153,8 @@ class Sema {
bool &OwnedDecl, bool &IsDependent,
SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
bool IsTypeSpecifier, SkipBodyInfo *SkipBody = nullptr);
bool IsTypeSpecifier, bool IsTemplateParamOrArg,
SkipBodyInfo *SkipBody = nullptr);
Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,

View File

@ -180,6 +180,11 @@ class BasicValueFactory {
return getValue(X);
}
inline const llvm::APSInt& getZeroWithTypeSize(QualType T) {
assert(T->isScalarType());
return getValue(0, Ctx.getTypeSize(T), true);
}
inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) {
return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
}

View File

@ -315,6 +315,13 @@ class SValBuilder {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
}
/// Create NULL pointer, with proper pointer bit-width for given address
/// space.
/// \param type pointer type.
Loc makeNullWithType(QualType type) {
return loc::ConcreteInt(BasicVals.getZeroWithTypeSize(type));
}
Loc makeNull() {
return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
}

View File

@ -894,7 +894,7 @@ void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
if (getLangOpts().ModulesLocalVisibility)
MergedDefModules[ND].push_back(M);
else
ND->setHidden(false);
ND->setVisibleDespiteOwningModule();
}
void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {
@ -8513,7 +8513,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
RequiresICE = false;
// Read the prefixed modifiers first.
bool Done = false;
bool Done = false, IsSpecialLong = false;
while (!Done) {
switch (*Str++) {
default: Done = true; --Str; break;
@ -8531,12 +8531,24 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
Unsigned = true;
break;
case 'L':
assert(!IsSpecialLong && "Can't use 'L' with 'W' or 'N' modifiers");
assert(HowLong <= 2 && "Can't have LLLL modifier");
++HowLong;
break;
case 'N': {
// 'N' behaves like 'L' for all non LP64 targets and 'int' otherwise.
assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!");
assert(HowLong == 0 && "Can't use both 'L' and 'N' modifiers!");
IsSpecialLong = true;
if (Context.getTargetInfo().getLongWidth() == 32)
++HowLong;
break;
}
case 'W':
// This modifier represents int64 type.
assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!");
assert(HowLong == 0 && "Can't use both 'L' and 'W' modifiers!");
IsSpecialLong = true;
switch (Context.getTargetInfo().getInt64Type()) {
default:
llvm_unreachable("Unexpected integer type");

View File

@ -1184,6 +1184,31 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
I != E; ++I)
dumpCXXCtorInitializer(*I);
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D))
if (MD->size_overridden_methods() != 0) {
auto dumpOverride =
[=](const CXXMethodDecl *D) {
SplitQualType T_split = D->getType().split();
OS << D << " " << D->getParent()->getName() << "::";
if (isa<CXXDestructorDecl>(D))
OS << "~" << D->getParent()->getName();
else
OS << D->getName();
OS << " '" << QualType::getAsString(T_split) << "'";
};
dumpChild([=] {
auto FirstOverrideItr = MD->begin_overridden_methods();
OS << "Overrides: [ ";
dumpOverride(*FirstOverrideItr);
for (const auto *Override :
llvm::make_range(FirstOverrideItr + 1,
MD->end_overridden_methods()))
dumpOverride(Override);
OS << " ]";
});
}
if (D->doesThisDeclarationHaveABody())
dumpStmt(D->getBody());
}

View File

@ -319,6 +319,9 @@ namespace clang {
bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin);
}
// Importing overrides.
void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod);
};
}
@ -2025,6 +2028,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Add this function to the lexical context.
LexicalDC->addDeclInternal(ToFunction);
if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod);
return ToFunction;
}
@ -5499,6 +5505,14 @@ Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
Replacement);
}
void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
CXXMethodDecl *FromMethod) {
for (auto *FromOverriddenMethod : FromMethod->overridden_methods())
ToMethod->addOverriddenMethod(
cast<CXXMethodDecl>(Importer.Import(const_cast<CXXMethodDecl*>(
FromOverriddenMethod))));
}
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport)

View File

@ -278,12 +278,12 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
// FIXME: We shouldn't be changing the lexical context of declarations
// imported from AST files.
if (!isFromASTFile()) {
Hidden = cast<Decl>(DC)->Hidden && hasLocalOwningModuleStorage();
if (Hidden)
setModuleOwnershipKind(getModuleOwnershipKindForChildOf(DC));
if (hasOwningModule())
setLocalOwningModule(cast<Decl>(DC)->getOwningModule());
}
assert((!Hidden || getOwningModule()) &&
assert((!hasOwningModule() || getOwningModule()) &&
"hidden declaration has no owning module");
}
@ -1352,7 +1352,7 @@ void DeclContext::removeDecl(Decl *D) {
// Remove only decls that have a name
if (!ND->getDeclName()) return;
auto *DC = this;
auto *DC = D->getDeclContext();
do {
StoredDeclsMap *Map = DC->getPrimaryContext()->LookupPtr;
if (Map) {

View File

@ -41,6 +41,7 @@ class LazyASTImporter : public ASTImporter {
Decl *Imported(Decl *From, Decl *To) override {
if (auto ToTag = dyn_cast<TagDecl>(To)) {
ToTag->setHasExternalLexicalStorage();
ToTag->setMustBuildLookupTable();
} else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
ToNamespace->setHasExternalVisibleStorage();
}

View File

@ -18,9 +18,9 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Path.h"
using namespace clang;
@ -366,6 +366,23 @@ void OnlyLargestCloneConstraint::constrain(
}
}
bool FilenamePatternConstraint::isAutoGenerated(const CloneDetector::CloneGroup &Group) {
std::string Error;
if (IgnoredFilesPattern.empty() || Group.empty() ||
!IgnoredFilesRegex->isValid(Error))
return false;
for (const StmtSequence &S : Group) {
const SourceManager &SM = S.getASTContext().getSourceManager();
StringRef Filename = llvm::sys::path::filename(SM.getFilename(
S.getContainingDecl()->getLocation()));
if (IgnoredFilesRegex->match(Filename))
return true;
}
return false;
}
static size_t createHash(llvm::MD5 &Hash) {
size_t HashCode;
@ -618,8 +635,7 @@ void CloneConstraint::splitCloneGroups(
if (Indexes[j])
continue;
// If a following StmtSequence belongs to our CloneGroup, we add it to
// it.
// If a following StmtSequence belongs to our CloneGroup, we add it.
const StmtSequence &Candidate = HashGroup[j];
if (!Compare(Prototype, Candidate))

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/Module.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
@ -125,7 +126,36 @@ const Module *Module::getTopLevelModule() const {
return Result;
}
std::string Module::getFullModuleName() const {
static StringRef getModuleNameFromComponent(
const std::pair<std::string, SourceLocation> &IdComponent) {
return IdComponent.first;
}
static StringRef getModuleNameFromComponent(StringRef R) { return R; }
template<typename InputIter>
static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End,
bool AllowStringLiterals = true) {
for (InputIter It = Begin; It != End; ++It) {
if (It != Begin)
OS << ".";
StringRef Name = getModuleNameFromComponent(*It);
if (!AllowStringLiterals || isValidIdentifier(Name))
OS << Name;
else {
OS << '"';
OS.write_escaped(Name);
OS << '"';
}
}
}
template<typename Container>
static void printModuleId(raw_ostream &OS, const Container &C) {
return printModuleId(OS, C.begin(), C.end());
}
std::string Module::getFullModuleName(bool AllowStringLiterals) const {
SmallVector<StringRef, 2> Names;
// Build up the set of module names (from innermost to outermost).
@ -133,15 +163,11 @@ std::string Module::getFullModuleName() const {
Names.push_back(M->Name);
std::string Result;
for (SmallVectorImpl<StringRef>::reverse_iterator I = Names.rbegin(),
IEnd = Names.rend();
I != IEnd; ++I) {
if (!Result.empty())
Result += '.';
Result += *I;
}
llvm::raw_string_ostream Out(Result);
printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals);
Out.flush();
return Result;
}
@ -240,14 +266,6 @@ Module *Module::findSubmodule(StringRef Name) const {
return SubModules[Pos->getValue()];
}
static void printModuleId(raw_ostream &OS, const ModuleId &Id) {
for (unsigned I = 0, N = Id.size(); I != N; ++I) {
if (I)
OS << ".";
OS << Id[I].first;
}
}
void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
// All non-explicit submodules are exported.
for (std::vector<Module *>::const_iterator I = SubModules.begin(),
@ -334,7 +352,8 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS << "framework ";
if (IsExplicit)
OS << "explicit ";
OS << "module " << Name;
OS << "module ";
printModuleId(OS, &Name, &Name + 1);
if (IsSystem || IsExternC) {
OS.indent(Indent + 2);
@ -434,7 +453,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS.indent(Indent + 2);
OS << "export ";
if (Module *Restriction = Exports[I].getPointer()) {
OS << Restriction->getFullModuleName();
OS << Restriction->getFullModuleName(true);
if (Exports[I].getInt())
OS << ".*";
} else {
@ -455,7 +474,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {
OS.indent(Indent + 2);
OS << "use ";
OS << DirectUses[I]->getFullModuleName();
OS << DirectUses[I]->getFullModuleName(true);
OS << "\n";
}
@ -488,7 +507,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) {
OS.indent(Indent + 2);
OS << "conflict ";
OS << Conflicts[I].Other->getFullModuleName();
OS << Conflicts[I].Other->getFullModuleName(true);
OS << ", \"";
OS.write_escaped(Conflicts[I].Message);
OS << "\"\n";

View File

@ -359,15 +359,6 @@ void SourceManager::initializeForReplay(const SourceManager &Old) {
return Clone;
};
// Set up our main file ID as a copy of the old source manager's main file.
const SLocEntry &OldMainFile = Old.getSLocEntry(Old.getMainFileID());
assert(OldMainFile.isFile() && "main file is macro expansion?");
auto *MainCC = CloneContentCache(OldMainFile.getFile().getContentCache());
MemBufferInfos.push_back(MainCC);
setMainFileID(createFileID(MainCC, SourceLocation(),
OldMainFile.getFile().getFileCharacteristic(),
0, 0));
// Ensure all SLocEntries are loaded from the external source.
for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
if (!Old.SLocEntryLoaded[I])

View File

@ -507,6 +507,11 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
case '?': // Disparage slightly code.
case '!': // Disparage severely.
case '*': // Ignore for choosing register preferences.
case 'i': // Ignore i,n,E,F as output constraints (match from the other
// chars)
case 'n':
case 'E':
case 'F':
break; // Pass them.
}

View File

@ -111,6 +111,21 @@ class CloudABITargetInfo : public OSTargetInfo<Target> {
: OSTargetInfo<Target>(Triple, Opts) {}
};
// Ananas target
template<typename Target>
class AnanasTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// Ananas defines
Builder.defineMacro("__Ananas__");
Builder.defineMacro("__ELF__");
}
public:
AnanasTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {}
};
static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
const llvm::Triple &Triple,
StringRef &PlatformName,
@ -6172,6 +6187,8 @@ class AArch64TargetInfo : public TargetInfo {
unsigned Crypto;
unsigned Unaligned;
unsigned V8_1A;
unsigned V8_2A;
unsigned HasFullFP16;
static const Builtin::Info BuiltinInfo[];
@ -6303,6 +6320,8 @@ class AArch64TargetInfo : public TargetInfo {
if (V8_1A)
Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
if (V8_2A && FPU == NeonMode && HasFullFP16)
Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
// All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
@ -6330,6 +6349,8 @@ class AArch64TargetInfo : public TargetInfo {
Crypto = 0;
Unaligned = 1;
V8_1A = 0;
V8_2A = 0;
HasFullFP16 = 0;
for (const auto &Feature : Features) {
if (Feature == "+neon")
@ -6342,6 +6363,10 @@ class AArch64TargetInfo : public TargetInfo {
Unaligned = 0;
if (Feature == "+v8.1a")
V8_1A = 1;
if (Feature == "+v8.2a")
V8_2A = 1;
if (Feature == "+fullfp16")
HasFullFP16 = 1;
}
setDataLayout();
@ -7493,7 +7518,7 @@ class MSP430TargetInfo : public TargetInfo {
IntPtrType = SignedInt;
PtrDiffType = SignedInt;
SigAtomicType = SignedLong;
resetDataLayout("e-m:e-p:16:16-i32:16:32-a:16-n8:16");
resetDataLayout("e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16");
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@ -9520,6 +9545,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new DarwinI386TargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::Ananas:
return new AnanasTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::CloudABI:
return new CloudABITargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::Linux: {
@ -9575,6 +9602,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new DarwinX86_64TargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::Ananas:
return new AnanasTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::CloudABI:
return new CloudABITargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Linux: {

View File

@ -2956,8 +2956,9 @@ static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
return llvm::VectorType::get(CGF->Int8Ty, V1Ty ? 1 : (8 << IsQuad));
case NeonTypeFlags::Int16:
case NeonTypeFlags::Poly16:
case NeonTypeFlags::Float16:
return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
case NeonTypeFlags::Float16:
return llvm::VectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad));
case NeonTypeFlags::Int32:
return llvm::VectorType::get(CGF->Int32Ty, V1Ty ? 1 : (2 << IsQuad));
case NeonTypeFlags::Int64:
@ -2980,6 +2981,8 @@ static llvm::VectorType *GetFloatNeonType(CodeGenFunction *CGF,
NeonTypeFlags IntTypeFlags) {
int IsQuad = IntTypeFlags.isQuad();
switch (IntTypeFlags.getEltType()) {
case NeonTypeFlags::Int16:
return llvm::VectorType::get(CGF->HalfTy, (4 << IsQuad));
case NeonTypeFlags::Int32:
return llvm::VectorType::get(CGF->FloatTy, (2 << IsQuad));
case NeonTypeFlags::Int64:
@ -3127,55 +3130,80 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP1(vcvt_f16_f32, arm_neon_vcvtfp2hf, 0),
NEONMAP1(vcvt_f32_f16, arm_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
NEONMAP2(vcvt_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvt_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
NEONMAP1(vcvt_n_s16_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_s32_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_s64_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_u16_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvt_n_u32_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvt_n_u64_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP0(vcvt_s16_v),
NEONMAP0(vcvt_s32_v),
NEONMAP0(vcvt_s64_v),
NEONMAP0(vcvt_u16_v),
NEONMAP0(vcvt_u32_v),
NEONMAP0(vcvt_u64_v),
NEONMAP1(vcvta_s16_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvta_s32_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvta_s64_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvta_u32_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvta_u64_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvtaq_s16_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvtaq_s32_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvtaq_s64_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvtaq_u16_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvtaq_u32_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvtaq_u64_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvtm_s16_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtm_s32_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtm_s64_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtm_u16_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtm_u32_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtm_u64_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtmq_s16_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtmq_s32_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtmq_s64_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtmq_u16_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtmq_u32_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtmq_u64_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtn_s16_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtn_s32_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtn_s64_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtn_u16_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtn_u32_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtn_u64_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtnq_s16_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtnq_s32_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtnq_s64_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtnq_u16_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtnq_u32_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtnq_u64_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtp_s16_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtp_s32_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtp_s64_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtp_u16_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtp_u32_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtp_u64_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtpq_s16_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtpq_s32_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtpq_s64_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtpq_u16_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtpq_u32_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtpq_u64_v, arm_neon_vcvtpu, 0),
NEONMAP0(vcvtq_f32_v),
NEONMAP2(vcvtq_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvtq_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
NEONMAP1(vcvtq_n_s16_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_s32_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_s64_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_u16_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u32_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u64_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP0(vcvtq_s16_v),
NEONMAP0(vcvtq_s32_v),
NEONMAP0(vcvtq_s64_v),
NEONMAP0(vcvtq_u16_v),
NEONMAP0(vcvtq_u32_v),
NEONMAP0(vcvtq_u64_v),
NEONMAP0(vext_v),
@ -3338,19 +3366,27 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
NEONMAP1(vcntq_v, ctpop, Add1ArgType),
NEONMAP1(vcvt_f16_f32, aarch64_neon_vcvtfp2hf, 0),
NEONMAP0(vcvt_f16_v),
NEONMAP1(vcvt_f32_f16, aarch64_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
NEONMAP2(vcvt_n_f16_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvt_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvt_n_f64_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP1(vcvt_n_s16_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_s32_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_s64_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_u16_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvt_n_u32_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvt_n_u64_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP0(vcvtq_f16_v),
NEONMAP0(vcvtq_f32_v),
NEONMAP2(vcvtq_n_f16_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvtq_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvtq_n_f64_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP1(vcvtq_n_s16_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_s32_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_s64_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_u16_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u32_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u64_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtx_f32_v, aarch64_neon_fcvtxn, AddRetType | Add1ArgType),
@ -3819,9 +3855,20 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcageq_v:
case NEON::BI__builtin_neon_vcagt_v:
case NEON::BI__builtin_neon_vcagtq_v: {
llvm::Type *VecFlt = llvm::VectorType::get(
VTy->getScalarSizeInBits() == 32 ? FloatTy : DoubleTy,
VTy->getNumElements());
llvm::Type *Ty;
switch (VTy->getScalarSizeInBits()) {
default: llvm_unreachable("unexpected type");
case 32:
Ty = FloatTy;
break;
case 64:
Ty = DoubleTy;
break;
case 16:
Ty = HalfTy;
break;
}
llvm::Type *VecFlt = llvm::VectorType::get(Ty, VTy->getNumElements());
llvm::Type *Tys[] = { VTy, VecFlt };
Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
return EmitNeonCall(F, Ops, NameHint);
@ -3838,8 +3885,16 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad));
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_f16_v:
case NEON::BI__builtin_neon_vcvtq_f16_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad));
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_n_f16_v:
case NEON::BI__builtin_neon_vcvt_n_f32_v:
case NEON::BI__builtin_neon_vcvt_n_f64_v:
case NEON::BI__builtin_neon_vcvtq_n_f16_v:
case NEON::BI__builtin_neon_vcvtq_n_f32_v:
case NEON::BI__builtin_neon_vcvtq_n_f64_v: {
llvm::Type *Tys[2] = { GetFloatNeonType(this, Type), Ty };
@ -3847,11 +3902,15 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Function *F = CGM.getIntrinsic(Int, Tys);
return EmitNeonCall(F, Ops, "vcvt_n");
}
case NEON::BI__builtin_neon_vcvt_n_s16_v:
case NEON::BI__builtin_neon_vcvt_n_s32_v:
case NEON::BI__builtin_neon_vcvt_n_u16_v:
case NEON::BI__builtin_neon_vcvt_n_u32_v:
case NEON::BI__builtin_neon_vcvt_n_s64_v:
case NEON::BI__builtin_neon_vcvt_n_u64_v:
case NEON::BI__builtin_neon_vcvtq_n_s16_v:
case NEON::BI__builtin_neon_vcvtq_n_s32_v:
case NEON::BI__builtin_neon_vcvtq_n_u16_v:
case NEON::BI__builtin_neon_vcvtq_n_u32_v:
case NEON::BI__builtin_neon_vcvtq_n_s64_v:
case NEON::BI__builtin_neon_vcvtq_n_u64_v: {
@ -3863,44 +3922,63 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvt_u32_v:
case NEON::BI__builtin_neon_vcvt_s64_v:
case NEON::BI__builtin_neon_vcvt_u64_v:
case NEON::BI__builtin_neon_vcvt_s16_v:
case NEON::BI__builtin_neon_vcvt_u16_v:
case NEON::BI__builtin_neon_vcvtq_s32_v:
case NEON::BI__builtin_neon_vcvtq_u32_v:
case NEON::BI__builtin_neon_vcvtq_s64_v:
case NEON::BI__builtin_neon_vcvtq_u64_v: {
case NEON::BI__builtin_neon_vcvtq_u64_v:
case NEON::BI__builtin_neon_vcvtq_s16_v:
case NEON::BI__builtin_neon_vcvtq_u16_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type));
return Usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt")
: Builder.CreateFPToSI(Ops[0], Ty, "vcvt");
}
case NEON::BI__builtin_neon_vcvta_s16_v:
case NEON::BI__builtin_neon_vcvta_s32_v:
case NEON::BI__builtin_neon_vcvta_s64_v:
case NEON::BI__builtin_neon_vcvta_u32_v:
case NEON::BI__builtin_neon_vcvta_u64_v:
case NEON::BI__builtin_neon_vcvtaq_s16_v:
case NEON::BI__builtin_neon_vcvtaq_s32_v:
case NEON::BI__builtin_neon_vcvtaq_s64_v:
case NEON::BI__builtin_neon_vcvtaq_u16_v:
case NEON::BI__builtin_neon_vcvtaq_u32_v:
case NEON::BI__builtin_neon_vcvtaq_u64_v:
case NEON::BI__builtin_neon_vcvtn_s16_v:
case NEON::BI__builtin_neon_vcvtn_s32_v:
case NEON::BI__builtin_neon_vcvtn_s64_v:
case NEON::BI__builtin_neon_vcvtn_u16_v:
case NEON::BI__builtin_neon_vcvtn_u32_v:
case NEON::BI__builtin_neon_vcvtn_u64_v:
case NEON::BI__builtin_neon_vcvtnq_s16_v:
case NEON::BI__builtin_neon_vcvtnq_s32_v:
case NEON::BI__builtin_neon_vcvtnq_s64_v:
case NEON::BI__builtin_neon_vcvtnq_u16_v:
case NEON::BI__builtin_neon_vcvtnq_u32_v:
case NEON::BI__builtin_neon_vcvtnq_u64_v:
case NEON::BI__builtin_neon_vcvtp_s16_v:
case NEON::BI__builtin_neon_vcvtp_s32_v:
case NEON::BI__builtin_neon_vcvtp_s64_v:
case NEON::BI__builtin_neon_vcvtp_u16_v:
case NEON::BI__builtin_neon_vcvtp_u32_v:
case NEON::BI__builtin_neon_vcvtp_u64_v:
case NEON::BI__builtin_neon_vcvtpq_s16_v:
case NEON::BI__builtin_neon_vcvtpq_s32_v:
case NEON::BI__builtin_neon_vcvtpq_s64_v:
case NEON::BI__builtin_neon_vcvtpq_u16_v:
case NEON::BI__builtin_neon_vcvtpq_u32_v:
case NEON::BI__builtin_neon_vcvtpq_u64_v:
case NEON::BI__builtin_neon_vcvtm_s16_v:
case NEON::BI__builtin_neon_vcvtm_s32_v:
case NEON::BI__builtin_neon_vcvtm_s64_v:
case NEON::BI__builtin_neon_vcvtm_u16_v:
case NEON::BI__builtin_neon_vcvtm_u32_v:
case NEON::BI__builtin_neon_vcvtm_u64_v:
case NEON::BI__builtin_neon_vcvtmq_s16_v:
case NEON::BI__builtin_neon_vcvtmq_s32_v:
case NEON::BI__builtin_neon_vcvtmq_s64_v:
case NEON::BI__builtin_neon_vcvtmq_u16_v:
case NEON::BI__builtin_neon_vcvtmq_u32_v:
case NEON::BI__builtin_neon_vcvtmq_u64_v: {
llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
@ -6110,7 +6188,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]));
return Builder.CreateCall(F, {Ops[2], Ops[1], Ops[0]});
}
case NEON::BI__builtin_neon_vfmah_lane_f16:
case NEON::BI__builtin_neon_vfmas_lane_f32:
case NEON::BI__builtin_neon_vfmah_laneq_f16:
case NEON::BI__builtin_neon_vfmas_laneq_f32:
case NEON::BI__builtin_neon_vfmad_lane_f64:
case NEON::BI__builtin_neon_vfmad_laneq_f64: {
@ -6285,18 +6365,25 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvt_u32_v:
case NEON::BI__builtin_neon_vcvt_s64_v:
case NEON::BI__builtin_neon_vcvt_u64_v:
case NEON::BI__builtin_neon_vcvt_s16_v:
case NEON::BI__builtin_neon_vcvt_u16_v:
case NEON::BI__builtin_neon_vcvtq_s32_v:
case NEON::BI__builtin_neon_vcvtq_u32_v:
case NEON::BI__builtin_neon_vcvtq_s64_v:
case NEON::BI__builtin_neon_vcvtq_u64_v: {
case NEON::BI__builtin_neon_vcvtq_u64_v:
case NEON::BI__builtin_neon_vcvtq_s16_v:
case NEON::BI__builtin_neon_vcvtq_u16_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type));
if (usgn)
return Builder.CreateFPToUI(Ops[0], Ty);
return Builder.CreateFPToSI(Ops[0], Ty);
}
case NEON::BI__builtin_neon_vcvta_s16_v:
case NEON::BI__builtin_neon_vcvta_s32_v:
case NEON::BI__builtin_neon_vcvtaq_s16_v:
case NEON::BI__builtin_neon_vcvtaq_s32_v:
case NEON::BI__builtin_neon_vcvta_u32_v:
case NEON::BI__builtin_neon_vcvtaq_u16_v:
case NEON::BI__builtin_neon_vcvtaq_u32_v:
case NEON::BI__builtin_neon_vcvta_s64_v:
case NEON::BI__builtin_neon_vcvtaq_s64_v:
@ -6306,9 +6393,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvta");
}
case NEON::BI__builtin_neon_vcvtm_s16_v:
case NEON::BI__builtin_neon_vcvtm_s32_v:
case NEON::BI__builtin_neon_vcvtmq_s16_v:
case NEON::BI__builtin_neon_vcvtmq_s32_v:
case NEON::BI__builtin_neon_vcvtm_u16_v:
case NEON::BI__builtin_neon_vcvtm_u32_v:
case NEON::BI__builtin_neon_vcvtmq_u16_v:
case NEON::BI__builtin_neon_vcvtmq_u32_v:
case NEON::BI__builtin_neon_vcvtm_s64_v:
case NEON::BI__builtin_neon_vcvtmq_s64_v:
@ -6318,9 +6409,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtm");
}
case NEON::BI__builtin_neon_vcvtn_s16_v:
case NEON::BI__builtin_neon_vcvtn_s32_v:
case NEON::BI__builtin_neon_vcvtnq_s16_v:
case NEON::BI__builtin_neon_vcvtnq_s32_v:
case NEON::BI__builtin_neon_vcvtn_u16_v:
case NEON::BI__builtin_neon_vcvtn_u32_v:
case NEON::BI__builtin_neon_vcvtnq_u16_v:
case NEON::BI__builtin_neon_vcvtnq_u32_v:
case NEON::BI__builtin_neon_vcvtn_s64_v:
case NEON::BI__builtin_neon_vcvtnq_s64_v:
@ -6330,9 +6425,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtn");
}
case NEON::BI__builtin_neon_vcvtp_s16_v:
case NEON::BI__builtin_neon_vcvtp_s32_v:
case NEON::BI__builtin_neon_vcvtpq_s16_v:
case NEON::BI__builtin_neon_vcvtpq_s32_v:
case NEON::BI__builtin_neon_vcvtp_u16_v:
case NEON::BI__builtin_neon_vcvtp_u32_v:
case NEON::BI__builtin_neon_vcvtpq_u16_v:
case NEON::BI__builtin_neon_vcvtpq_u32_v:
case NEON::BI__builtin_neon_vcvtp_s64_v:
case NEON::BI__builtin_neon_vcvtpq_s64_v:
@ -6505,6 +6604,24 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vmaxv_f16: {
Int = Intrinsic::aarch64_neon_fmaxv;
Ty = HalfTy;
VTy = llvm::VectorType::get(HalfTy, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
return Builder.CreateTrunc(Ops[0], HalfTy);
}
case NEON::BI__builtin_neon_vmaxvq_f16: {
Int = Intrinsic::aarch64_neon_fmaxv;
Ty = HalfTy;
VTy = llvm::VectorType::get(HalfTy, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
return Builder.CreateTrunc(Ops[0], HalfTy);
}
case NEON::BI__builtin_neon_vminv_u8: {
Int = Intrinsic::aarch64_neon_uminv;
Ty = Int32Ty;
@ -6577,6 +6694,60 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vminv_f16: {
Int = Intrinsic::aarch64_neon_fminv;
Ty = HalfTy;
VTy = llvm::VectorType::get(HalfTy, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
return Builder.CreateTrunc(Ops[0], HalfTy);
}
case NEON::BI__builtin_neon_vminvq_f16: {
Int = Intrinsic::aarch64_neon_fminv;
Ty = HalfTy;
VTy = llvm::VectorType::get(HalfTy, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
return Builder.CreateTrunc(Ops[0], HalfTy);
}
case NEON::BI__builtin_neon_vmaxnmv_f16: {
Int = Intrinsic::aarch64_neon_fmaxnmv;
Ty = HalfTy;
VTy = llvm::VectorType::get(HalfTy, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxnmv");
return Builder.CreateTrunc(Ops[0], HalfTy);
}
case NEON::BI__builtin_neon_vmaxnmvq_f16: {
Int = Intrinsic::aarch64_neon_fmaxnmv;
Ty = HalfTy;
VTy = llvm::VectorType::get(HalfTy, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxnmv");
return Builder.CreateTrunc(Ops[0], HalfTy);
}
case NEON::BI__builtin_neon_vminnmv_f16: {
Int = Intrinsic::aarch64_neon_fminnmv;
Ty = HalfTy;
VTy = llvm::VectorType::get(HalfTy, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminnmv");
return Builder.CreateTrunc(Ops[0], HalfTy);
}
case NEON::BI__builtin_neon_vminnmvq_f16: {
Int = Intrinsic::aarch64_neon_fminnmv;
Ty = HalfTy;
VTy = llvm::VectorType::get(HalfTy, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminnmv");
return Builder.CreateTrunc(Ops[0], HalfTy);
}
case NEON::BI__builtin_neon_vmul_n_f64: {
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
Value *RHS = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)), DoubleTy);

View File

@ -2906,7 +2906,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
llvm::Instruction *Ret;
if (RV) {
EmitReturnValueCheck(RV, EndLoc);
EmitReturnValueCheck(RV);
Ret = Builder.CreateRet(RV);
} else {
Ret = Builder.CreateRetVoid();
@ -2916,8 +2916,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
Ret->setDebugLoc(std::move(RetDbgLoc));
}
void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV,
SourceLocation EndLoc) {
void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
// A current decl may not be available when emitting vtable thunks.
if (!CurCodeDecl)
return;
@ -2950,27 +2949,30 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV,
SanitizerScope SanScope(this);
llvm::BasicBlock *Check = nullptr;
llvm::BasicBlock *NoCheck = nullptr;
if (requiresReturnValueNullabilityCheck()) {
// Before doing the nullability check, make sure that the preconditions for
// the check are met.
Check = createBasicBlock("nullcheck");
NoCheck = createBasicBlock("no.nullcheck");
Builder.CreateCondBr(RetValNullabilityPrecondition, Check, NoCheck);
EmitBlock(Check);
}
// Now do the null check. If the returns_nonnull attribute is present, this
// is done unconditionally.
llvm::Value *Cond = Builder.CreateIsNotNull(RV);
llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(EndLoc), EmitCheckSourceLocation(AttrLoc),
};
EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None);
// Make sure the "return" source location is valid. If we're checking a
// nullability annotation, make sure the preconditions for the check are met.
llvm::BasicBlock *Check = createBasicBlock("nullcheck");
llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck");
llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load");
llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr);
if (requiresReturnValueNullabilityCheck())
EmitBlock(NoCheck);
CanNullCheck =
Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition);
Builder.CreateCondBr(CanNullCheck, Check, NoCheck);
EmitBlock(Check);
// Now do the null check.
llvm::Value *Cond = Builder.CreateIsNotNull(RV);
llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)};
llvm::Value *DynamicData[] = {SLocPtr};
EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData);
EmitBlock(NoCheck);
#ifndef NDEBUG
// The return location should not be used after the check has been emitted.
ReturnLocation = Address::invalid();
#endif
}
static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) {
@ -3813,7 +3815,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(NumIRArgs == 1);
if (RV.isScalar() || RV.isComplex()) {
// Make a temporary alloca to pass the argument.
Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign());
Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
"indirect-arg-temp", false);
IRCallArgs[FirstIRArg] = Addr.getPointer();
LValue argLV = MakeAddrLValue(Addr, I->Ty);
@ -3842,7 +3845,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
< Align.getQuantity()) ||
(ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) {
// Create an aligned temporary, and copy to it.
Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign());
Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
"byval-temp", false);
IRCallArgs[FirstIRArg] = AI.getPointer();
EmitAggregateCopy(AI, Addr, I->Ty, RV.isVolatileQualified());
} else {

View File

@ -2770,10 +2770,19 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
// We can devirtualize calls on an object accessed by a class member access
// expression, since by C++11 [basic.life]p6 we know that it can't refer to
// a derived class object constructed in the same location.
// a derived class object constructed in the same location. However, we avoid
// devirtualizing a call to a template function that we could instantiate
// implicitly, but have not decided to do so. This is needed because if this
// function does not get instantiated, the devirtualization will create a
// direct call to a function whose body may not exist. In contrast, calls to
// template functions that are not defined in this TU are allowed to be
// devirtualized under assumption that it is user responsibility to
// instantiate them in some other TU.
if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base))
if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl()))
return VD->getType()->isRecordType();
return VD->getType()->isRecordType() &&
(MD->instantiationIsPending() || MD->isDefined() ||
!MD->isImplicitlyInstantiable());
// Likewise for calls on an object accessed by a (non-reference) pointer to
// member access.

View File

@ -954,6 +954,7 @@ void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
CodeGenFunction::AutoVarEmission
CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
QualType Ty = D.getType();
assert(Ty.getAddressSpace() == LangAS::Default);
AutoVarEmission emission(D);
@ -1046,8 +1047,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Create the alloca. Note that we set the name separately from
// building the instruction so that it's there even in no-asserts
// builds.
address = CreateTempAlloca(allocaTy, allocaAlignment);
address.getPointer()->setName(D.getName());
address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName());
// Don't emit lifetime markers for MSVC catch parameters. The lifetime of
// the catch parameter starts in the catchpad instruction, and we can't
@ -1107,27 +1107,9 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
llvm::Type *llvmTy = ConvertTypeForMem(elementType);
// Allocate memory for the array.
llvm::AllocaInst *vla = Builder.CreateAlloca(llvmTy, elementCount, "vla");
vla->setAlignment(alignment.getQuantity());
address = Address(vla, alignment);
address = CreateTempAlloca(llvmTy, alignment, "vla", elementCount);
}
// Alloca always returns a pointer in alloca address space, which may
// be different from the type defined by the language. For example,
// in C++ the auto variables are in the default address space. Therefore
// cast alloca to the expected address space when necessary.
auto T = D.getType();
assert(T.getAddressSpace() == LangAS::Default);
if (getASTAllocaAddressSpace() != LangAS::Default) {
auto *Addr = getTargetHooks().performAddrSpaceCast(
*this, address.getPointer(), getASTAllocaAddressSpace(),
T.getAddressSpace(),
address.getElementType()->getPointerTo(
getContext().getTargetAddressSpace(T.getAddressSpace())),
/*non-null*/ true);
address = Address(Addr, address.getAlignment());
}
setAddrOfLocalVar(&D, address);
emission.Addr = address;

View File

@ -61,18 +61,36 @@ llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) {
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,
const Twine &Name) {
auto Alloca = CreateTempAlloca(Ty, Name);
const Twine &Name,
llvm::Value *ArraySize,
bool CastToDefaultAddrSpace) {
auto Alloca = CreateTempAlloca(Ty, Name, ArraySize);
Alloca->setAlignment(Align.getQuantity());
return Address(Alloca, Align);
llvm::Value *V = Alloca;
// Alloca always returns a pointer in alloca address space, which may
// be different from the type defined by the language. For example,
// in C++ the auto variables are in the default address space. Therefore
// cast alloca to the default address space when necessary.
if (CastToDefaultAddrSpace && getASTAllocaAddressSpace() != LangAS::Default) {
auto DestAddrSpace = getContext().getTargetAddressSpace(LangAS::Default);
V = getTargetHooks().performAddrSpaceCast(
*this, V, getASTAllocaAddressSpace(), LangAS::Default,
Ty->getPointerTo(DestAddrSpace), /*non-null*/ true);
}
return Address(V, Align);
}
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
/// CreateTempAlloca - This creates an alloca and inserts it into the entry
/// block if \p ArraySize is nullptr, otherwise inserts it at the current
/// insertion point of the builder.
llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty,
const Twine &Name) {
const Twine &Name,
llvm::Value *ArraySize) {
if (ArraySize)
return Builder.CreateAlloca(Ty, ArraySize, Name);
return new llvm::AllocaInst(Ty, CGM.getDataLayout().getAllocaAddrSpace(),
nullptr, Name, AllocaInsertPt);
ArraySize, Name, AllocaInsertPt);
}
/// CreateDefaultAlignTempAlloca - This creates an alloca with the
@ -99,14 +117,18 @@ Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) {
return CreateTempAlloca(ConvertType(Ty), Align, Name);
}
Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name) {
Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name,
bool CastToDefaultAddrSpace) {
// FIXME: Should we prefer the preferred type alignment here?
return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name);
return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name,
CastToDefaultAddrSpace);
}
Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
const Twine &Name) {
return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name);
const Twine &Name,
bool CastToDefaultAddrSpace) {
return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, nullptr,
CastToDefaultAddrSpace);
}
/// EvaluateExprAsBool - Perform the usual unary conversions on the specified

View File

@ -308,7 +308,7 @@ class ObjCCommonTypesHelper {
SmallVector<CanQualType,5> Params;
Params.push_back(Ctx.VoidPtrTy);
Params.push_back(Ctx.VoidPtrTy);
Params.push_back(Ctx.LongTy);
Params.push_back(Ctx.getSizeType());
Params.push_back(Ctx.BoolTy);
Params.push_back(Ctx.BoolTy);
llvm::FunctionType *FTy =

View File

@ -1024,6 +1024,18 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
if (requiresReturnValueCheck()) {
llvm::Constant *SLoc = EmitCheckSourceLocation(S.getLocStart());
auto *SLocPtr =
new llvm::GlobalVariable(CGM.getModule(), SLoc->getType(), false,
llvm::GlobalVariable::PrivateLinkage, SLoc);
SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
assert(ReturnLocation.isValid() && "No valid return location");
Builder.CreateStore(Builder.CreateBitCast(SLocPtr, Int8PtrTy),
ReturnLocation);
}
// Returning from an outlined SEH helper is UB, and we already warn on it.
if (IsOutlinedSEHHelper) {
Builder.CreateUnreachable();

View File

@ -860,6 +860,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
Builder.SetInsertPoint(EntryBB);
// If we're checking the return value, allocate space for a pointer to a
// precise source location of the checked return statement.
if (requiresReturnValueCheck()) {
ReturnLocation = CreateDefaultAlignTempAlloca(Int8PtrTy, "return.sloc.ptr");
InitTempAlloca(ReturnLocation, llvm::ConstantPointerNull::get(Int8PtrTy));
}
// Emit subprogram debug descriptor.
if (CGDebugInfo *DI = getDebugInfo()) {
// Reconstruct the type from the argument list so that implicit parameters,
@ -887,8 +894,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (CGM.getCodeGenOpts().InstrumentForProfiling) {
if (CGM.getCodeGenOpts().CallFEntry)
Fn->addFnAttr("fentry-call", "true");
else
Fn->addFnAttr("counting-function", getTarget().getMCountName());
else {
if (!CurFuncDecl || !CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>())
Fn->addFnAttr("counting-function", getTarget().getMCountName());
}
}
if (RetTy->isVoidType()) {

View File

@ -116,9 +116,9 @@ enum TypeEvaluationKind {
SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \
SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \
SANITIZER_CHECK(NullabilityArg, nullability_arg, 0) \
SANITIZER_CHECK(NullabilityReturn, nullability_return, 0) \
SANITIZER_CHECK(NullabilityReturn, nullability_return, 1) \
SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \
SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) \
SANITIZER_CHECK(NonnullReturn, nonnull_return, 1) \
SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \
SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \
SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \
@ -1407,6 +1407,17 @@ class CodeGenFunction : public CodeGenTypeCache {
return RetValNullabilityPrecondition;
}
/// Used to store precise source locations for return statements by the
/// runtime return value checks.
Address ReturnLocation = Address::invalid();
/// Check if the return value of this function requires sanitization.
bool requiresReturnValueCheck() const {
return requiresReturnValueNullabilityCheck() ||
(SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) &&
CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>());
}
llvm::BasicBlock *TerminateLandingPad;
llvm::BasicBlock *TerminateHandler;
llvm::BasicBlock *TrapBB;
@ -1778,7 +1789,7 @@ class CodeGenFunction : public CodeGenTypeCache {
SourceLocation EndLoc);
/// Emit a test that checks if the return value \p RV is nonnull.
void EmitReturnValueCheck(llvm::Value *RV, SourceLocation EndLoc);
void EmitReturnValueCheck(llvm::Value *RV);
/// EmitStartEHSpec - Emit the start of the exception spec.
void EmitStartEHSpec(const Decl *D);
@ -1916,13 +1927,36 @@ class CodeGenFunction : public CodeGenTypeCache {
LValueBaseInfo *BaseInfo = nullptr);
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy);
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block. The caller is responsible for setting an appropriate alignment on
/// CreateTempAlloca - This creates an alloca and inserts it into the entry
/// block if \p ArraySize is nullptr, otherwise inserts it at the current
/// insertion point of the builder. The caller is responsible for setting an
/// appropriate alignment on
/// the alloca.
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty,
const Twine &Name = "tmp");
///
/// \p ArraySize is the number of array elements to be allocated if it
/// is not nullptr.
///
/// LangAS::Default is the address space of pointers to local variables and
/// temporaries, as exposed in the source language. In certain
/// configurations, this is not the same as the alloca address space, and a
/// cast is needed to lift the pointer from the alloca AS into
/// LangAS::Default. This can happen when the target uses a restricted
/// address space for the stack but the source language requires
/// LangAS::Default to be a generic address space. The latter condition is
/// common for most programming languages; OpenCL is an exception in that
/// LangAS::Default is the private address space, which naturally maps
/// to the stack.
///
/// Because the address of a temporary is often exposed to the program in
/// various ways, this function will perform the cast by default. The cast
/// may be avoided by passing false as \p CastToDefaultAddrSpace; this is
/// more efficient if the caller knows that the address will not be exposed.
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp",
llvm::Value *ArraySize = nullptr);
Address CreateTempAlloca(llvm::Type *Ty, CharUnits align,
const Twine &Name = "tmp");
const Twine &Name = "tmp",
llvm::Value *ArraySize = nullptr,
bool CastToDefaultAddrSpace = true);
/// CreateDefaultAlignedTempAlloca - This creates an alloca with the
/// default ABI alignment of the given LLVM type.
@ -1957,9 +1991,12 @@ class CodeGenFunction : public CodeGenTypeCache {
Address CreateIRTemp(QualType T, const Twine &Name = "tmp");
/// CreateMemTemp - Create a temporary memory object of the given type, with
/// appropriate alignment.
Address CreateMemTemp(QualType T, const Twine &Name = "tmp");
Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp");
/// appropriate alignment. Cast it to the default address space if
/// \p CastToDefaultAddrSpace is true.
Address CreateMemTemp(QualType T, const Twine &Name = "tmp",
bool CastToDefaultAddrSpace = true);
Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp",
bool CastToDefaultAddrSpace = true);
/// CreateAggTemp - Create a temporary memory object for the given
/// aggregate type.

View File

@ -98,6 +98,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
Int16Ty = llvm::Type::getInt16Ty(LLVMContext);
Int32Ty = llvm::Type::getInt32Ty(LLVMContext);
Int64Ty = llvm::Type::getInt64Ty(LLVMContext);
HalfTy = llvm::Type::getHalfTy(LLVMContext);
FloatTy = llvm::Type::getFloatTy(LLVMContext);
DoubleTy = llvm::Type::getDoubleTy(LLVMContext);
PointerWidthInBits = C.getTargetInfo().getPointerWidth(0);
@ -506,6 +507,26 @@ void CodeGenModule::Release() {
LangOpts.CUDADeviceFlushDenormalsToZero ? 1 : 0);
}
// Emit OpenCL specific module metadata: OpenCL/SPIR version.
if (LangOpts.OpenCL) {
EmitOpenCLMetadata();
// Emit SPIR version.
if (getTriple().getArch() == llvm::Triple::spir ||
getTriple().getArch() == llvm::Triple::spir64) {
// SPIR v2.0 s2.12 - The SPIR version used by the module is stored in the
// opencl.spir.version named metadata.
llvm::Metadata *SPIRVerElts[] = {
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, LangOpts.OpenCLVersion / 100)),
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, (LangOpts.OpenCLVersion / 100 > 1) ? 0 : 2))};
llvm::NamedMDNode *SPIRVerMD =
TheModule.getOrInsertNamedMetadata("opencl.spir.version");
llvm::LLVMContext &Ctx = TheModule.getContext();
SPIRVerMD->addOperand(llvm::MDNode::get(Ctx, SPIRVerElts));
}
}
if (uint32_t PLevel = Context.getLangOpts().PICLevel) {
assert(PLevel < 3 && "Invalid PIC Level");
getModule().setPICLevel(static_cast<llvm::PICLevel::Level>(PLevel));
@ -529,6 +550,20 @@ void CodeGenModule::Release() {
EmitTargetMetadata();
}
void CodeGenModule::EmitOpenCLMetadata() {
// SPIR v2.0 s2.13 - The OpenCL version used by the module is stored in the
// opencl.ocl.version named metadata node.
llvm::Metadata *OCLVerElts[] = {
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, LangOpts.OpenCLVersion / 100)),
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, (LangOpts.OpenCLVersion % 100) / 10))};
llvm::NamedMDNode *OCLVerMD =
TheModule.getOrInsertNamedMetadata("opencl.ocl.version");
llvm::LLVMContext &Ctx = TheModule.getContext();
OCLVerMD->addOperand(llvm::MDNode::get(Ctx, OCLVerElts));
}
void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {
// Make sure that this type is translated.
Types.UpdateCompletedType(TD);

View File

@ -1321,6 +1321,9 @@ class CodeGenModule : public CodeGenTypeCache {
/// Emits target specific Metadata for global declarations.
void EmitTargetMetadata();
/// Emits OpenCL specific Metadata e.g. OpenCL version.
void EmitOpenCLMetadata();
/// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and
/// .gcda files in a way that persists in .bc files.
void EmitCoverageFile();

View File

@ -36,7 +36,7 @@ struct CodeGenTypeCache {
/// i8, i16, i32, and i64
llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty;
/// float, double
llvm::Type *FloatTy, *DoubleTy;
llvm::Type *HalfTy, *FloatTy, *DoubleTy;
/// int
llvm::IntegerType *IntTy;

View File

@ -57,6 +57,10 @@ static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type) {
return CharUnits::fromQuantity(CGM.getDataLayout().getTypeStoreSize(type));
}
static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type) {
return CharUnits::fromQuantity(CGM.getDataLayout().getTypeAllocSize(type));
}
void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) {
// Deal with various aggregate types as special cases:
@ -542,7 +546,9 @@ SwiftAggLowering::getCoerceAndExpandTypes() const {
packed = true;
elts.push_back(entry.Type);
lastEnd = entry.End;
lastEnd = entry.Begin + getTypeAllocSize(CGM, entry.Type);
assert(entry.End <= lastEnd);
}
// We don't need to adjust 'packed' to deal with possible tail padding

View File

@ -951,8 +951,7 @@ class X86_32ABIInfo : public SwiftABIInfo {
Class classify(QualType Ty) const;
ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const;
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
ABIArgInfo reclassifyHvaArgType(QualType RetTy, CCState &State,
const ABIArgInfo& current) const;
/// \brief Updates the number of available free registers, returns
/// true if any registers were allocated.
bool updateFreeRegs(QualType Ty, CCState &State) const;
@ -1536,27 +1535,6 @@ bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State) const {
return true;
}
ABIArgInfo
X86_32ABIInfo::reclassifyHvaArgType(QualType Ty, CCState &State,
const ABIArgInfo &current) const {
// Assumes vectorCall calling convention.
const Type *Base = nullptr;
uint64_t NumElts = 0;
if (!Ty->isBuiltinType() && !Ty->isVectorType() &&
isHomogeneousAggregate(Ty, Base, NumElts)) {
if (State.FreeSSERegs >= NumElts) {
// HVA types get passed directly in registers if there is room.
State.FreeSSERegs -= NumElts;
return getDirectX86Hva();
}
// If there's no room, the HVA gets passed as normal indirect
// structure.
return getIndirectResult(Ty, /*ByVal=*/false, State);
}
return current;
}
ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
CCState &State) const {
// FIXME: Set alignment on indirect arguments.
@ -1575,35 +1553,20 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
}
}
// vectorcall adds the concept of a homogenous vector aggregate, similar
// to other targets, regcall uses some of the HVA rules.
// Regcall uses the concept of a homogenous vector aggregate, similar
// to other targets.
const Type *Base = nullptr;
uint64_t NumElts = 0;
if ((State.CC == llvm::CallingConv::X86_VectorCall ||
State.CC == llvm::CallingConv::X86_RegCall) &&
if (State.CC == llvm::CallingConv::X86_RegCall &&
isHomogeneousAggregate(Ty, Base, NumElts)) {
if (State.CC == llvm::CallingConv::X86_RegCall) {
if (State.FreeSSERegs >= NumElts) {
State.FreeSSERegs -= NumElts;
if (Ty->isBuiltinType() || Ty->isVectorType())
return ABIArgInfo::getDirect();
return ABIArgInfo::getExpand();
}
return getIndirectResult(Ty, /*ByVal=*/false, State);
} else if (State.CC == llvm::CallingConv::X86_VectorCall) {
if (State.FreeSSERegs >= NumElts && (Ty->isBuiltinType() || Ty->isVectorType())) {
// Actual floating-point types get registers first time through if
// there is registers available
State.FreeSSERegs -= NumElts;
if (State.FreeSSERegs >= NumElts) {
State.FreeSSERegs -= NumElts;
if (Ty->isBuiltinType() || Ty->isVectorType())
return ABIArgInfo::getDirect();
} else if (!Ty->isBuiltinType() && !Ty->isVectorType()) {
// HVA Types only get registers after everything else has been
// set, so it gets set as indirect for now.
return ABIArgInfo::getIndirect(getContext().getTypeAlignInChars(Ty));
}
return ABIArgInfo::getExpand();
}
return getIndirectResult(Ty, /*ByVal=*/false, State);
}
if (isAggregateTypeForABI(Ty)) {
@ -1684,31 +1647,53 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
void X86_32ABIInfo::computeVectorCallArgs(CGFunctionInfo &FI, CCState &State,
bool &UsedInAlloca) const {
// Vectorcall only allows the first 6 parameters to be passed in registers,
// and homogeneous vector aggregates are only put into registers as a second
// priority.
unsigned Count = 0;
CCState ZeroState = State;
ZeroState.FreeRegs = ZeroState.FreeSSERegs = 0;
// HVAs must be done as a second priority for registers, so the deferred
// items are dealt with by going through the pattern a second time.
// Vectorcall x86 works subtly different than in x64, so the format is
// a bit different than the x64 version. First, all vector types (not HVAs)
// are assigned, with the first 6 ending up in the YMM0-5 or XMM0-5 registers.
// This differs from the x64 implementation, where the first 6 by INDEX get
// registers.
// After that, integers AND HVAs are assigned Left to Right in the same pass.
// Integers are passed as ECX/EDX if one is available (in order). HVAs will
// first take up the remaining YMM/XMM registers. If insufficient registers
// remain but an integer register (ECX/EDX) is available, it will be passed
// in that, else, on the stack.
for (auto &I : FI.arguments()) {
if (Count < VectorcallMaxParamNumAsReg)
I.info = classifyArgumentType(I.type, State);
else
// Parameters after the 6th cannot be passed in registers,
// so pretend there are no registers left for them.
I.info = classifyArgumentType(I.type, ZeroState);
UsedInAlloca |= (I.info.getKind() == ABIArgInfo::InAlloca);
++Count;
// First pass do all the vector types.
const Type *Base = nullptr;
uint64_t NumElts = 0;
const QualType& Ty = I.type;
if ((Ty->isVectorType() || Ty->isBuiltinType()) &&
isHomogeneousAggregate(Ty, Base, NumElts)) {
if (State.FreeSSERegs >= NumElts) {
State.FreeSSERegs -= NumElts;
I.info = ABIArgInfo::getDirect();
} else {
I.info = classifyArgumentType(Ty, State);
}
UsedInAlloca |= (I.info.getKind() == ABIArgInfo::InAlloca);
}
}
Count = 0;
// Go through the arguments a second time to get HVAs registers if there
// are still some available.
for (auto &I : FI.arguments()) {
if (Count < VectorcallMaxParamNumAsReg)
I.info = reclassifyHvaArgType(I.type, State, I.info);
++Count;
// Second pass, do the rest!
const Type *Base = nullptr;
uint64_t NumElts = 0;
const QualType& Ty = I.type;
bool IsHva = isHomogeneousAggregate(Ty, Base, NumElts);
if (IsHva && !Ty->isVectorType() && !Ty->isBuiltinType()) {
// Assign true HVAs (non vector/native FP types).
if (State.FreeSSERegs >= NumElts) {
State.FreeSSERegs -= NumElts;
I.info = getDirectX86Hva();
} else {
I.info = getIndirectResult(Ty, /*ByVal=*/false, State);
}
} else if (!IsHva) {
// Assign all Non-HVAs, so this will exclude Vector/FP args.
I.info = classifyArgumentType(Ty, State);
UsedInAlloca |= (I.info.getKind() == ABIArgInfo::InAlloca);
}
}
}
@ -3901,6 +3886,8 @@ void WinX86_64ABIInfo::computeVectorCallArgs(CGFunctionInfo &FI,
bool IsRegCall) const {
unsigned Count = 0;
for (auto &I : FI.arguments()) {
// Vectorcall in x64 only permits the first 6 arguments to be passed
// as XMM/YMM registers.
if (Count < VectorcallMaxParamNumAsReg)
I.info = classify(I.type, FreeSSERegs, false, IsVectorCall, IsRegCall);
else {
@ -3913,11 +3900,8 @@ void WinX86_64ABIInfo::computeVectorCallArgs(CGFunctionInfo &FI,
++Count;
}
Count = 0;
for (auto &I : FI.arguments()) {
if (Count < VectorcallMaxParamNumAsReg)
I.info = reclassifyHvaArgType(I.type, FreeSSERegs, I.info);
++Count;
I.info = reclassifyHvaArgType(I.type, FreeSSERegs, I.info);
}
}
@ -7344,8 +7328,6 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
};
}
static void appendOpenCLVersionMD (CodeGen::CodeGenModule &CGM);
void AMDGPUTargetCodeGenInfo::setTargetAttributes(
const Decl *D,
llvm::GlobalValue *GV,
@ -7402,8 +7384,6 @@ void AMDGPUTargetCodeGenInfo::setTargetAttributes(
if (NumVGPR != 0)
F->addFnAttr("amdgpu-num-vgpr", llvm::utostr(NumVGPR));
}
appendOpenCLVersionMD(M);
}
unsigned AMDGPUTargetCodeGenInfo::getOpenCLKernelCallingConv() const {
@ -8074,8 +8054,6 @@ class SPIRTargetCodeGenInfo : public TargetCodeGenInfo {
public:
SPIRTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
void emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
unsigned getOpenCLKernelCallingConv() const override;
};
@ -8090,41 +8068,6 @@ void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) {
}
}
/// Emit SPIR specific metadata: OpenCL and SPIR version.
void SPIRTargetCodeGenInfo::emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const {
llvm::LLVMContext &Ctx = CGM.getModule().getContext();
llvm::Type *Int32Ty = llvm::Type::getInt32Ty(Ctx);
llvm::Module &M = CGM.getModule();
// SPIR v2.0 s2.12 - The SPIR version used by the module is stored in the
// opencl.spir.version named metadata.
llvm::Metadata *SPIRVerElts[] = {
llvm::ConstantAsMetadata::get(
llvm::ConstantInt::get(Int32Ty, CGM.getLangOpts().OpenCLVersion / 100)),
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, (CGM.getLangOpts().OpenCLVersion / 100 > 1) ? 0 : 2))};
llvm::NamedMDNode *SPIRVerMD =
M.getOrInsertNamedMetadata("opencl.spir.version");
SPIRVerMD->addOperand(llvm::MDNode::get(Ctx, SPIRVerElts));
appendOpenCLVersionMD(CGM);
}
static void appendOpenCLVersionMD(CodeGen::CodeGenModule &CGM) {
llvm::LLVMContext &Ctx = CGM.getModule().getContext();
llvm::Type *Int32Ty = llvm::Type::getInt32Ty(Ctx);
llvm::Module &M = CGM.getModule();
// SPIR v2.0 s2.13 - The OpenCL version used by the module is stored in the
// opencl.ocl.version named metadata node.
llvm::Metadata *OCLVerElts[] = {
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, CGM.getLangOpts().OpenCLVersion / 100)),
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, (CGM.getLangOpts().OpenCLVersion % 100) / 10))};
llvm::NamedMDNode *OCLVerMD =
M.getOrInsertNamedMetadata("opencl.ocl.version");
OCLVerMD->addOperand(llvm::MDNode::get(Ctx, OCLVerElts));
}
unsigned SPIRTargetCodeGenInfo::getOpenCLKernelCallingConv() const {
return llvm::CallingConv::SPIR_KERNEL;
}

View File

@ -28,6 +28,7 @@ add_clang_library(clangDriver
ToolChains/Arch/Sparc.cpp
ToolChains/Arch/SystemZ.cpp
ToolChains/Arch/X86.cpp
ToolChains/Ananas.cpp
ToolChains/AMDGPU.cpp
ToolChains/AVR.cpp
ToolChains/Bitrig.cpp

View File

@ -11,6 +11,7 @@
#include "InputInfo.h"
#include "ToolChains/AMDGPU.h"
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
#include "ToolChains/Bitrig.h"
#include "ToolChains/Clang.h"
#include "ToolChains/CloudABI.h"
@ -1227,7 +1228,32 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {
// Print out all options that start with a given argument. This is used for
// shell autocompletion.
llvm::outs() << llvm::join(Opts->findByPrefix(A->getValue()), " ") << '\n';
StringRef PassedFlags = A->getValue();
std::vector<std::string> SuggestedCompletions;
if (PassedFlags.find(',') == StringRef::npos) {
// If the flag is in the form of "--autocomplete=-foo",
// we were requested to print out all option names that start with "-foo".
// For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".
SuggestedCompletions = Opts->findByPrefix(PassedFlags);
} else {
// If the flag is in the form of "--autocomplete=foo,bar", we were
// requested to print out all option values for "-foo" that start with
// "bar". For example,
// "--autocomplete=-stdlib=,l" is expanded to "libc++" and "libstdc++".
StringRef Option, Arg;
std::tie(Option, Arg) = PassedFlags.split(',');
SuggestedCompletions = Opts->suggestValueCompletions(Option, Arg);
}
// Sort the autocomplete candidates so that shells print them out in a
// deterministic order. We could sort in any way, but we chose
// case-insensitive sorting for consistency with the -help option
// which prints out options in the case-insensitive alphabetical order.
std::sort(SuggestedCompletions.begin(), SuggestedCompletions.end(),
[](StringRef A, StringRef B) { return A.compare_lower(B) < 0; });
llvm::outs() << llvm::join(SuggestedCompletions, " ") << '\n';
return false;
}
@ -3724,6 +3750,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::Haiku:
TC = llvm::make_unique<toolchains::Haiku>(*this, Target, Args);
break;
case llvm::Triple::Ananas:
TC = llvm::make_unique<toolchains::Ananas>(*this, Target, Args);
break;
case llvm::Triple::CloudABI:
TC = llvm::make_unique<toolchains::CloudABI>(*this, Target, Args);
break;

View File

@ -21,10 +21,10 @@ using namespace llvm::opt;
#undef PREFIX
static const OptTable::Info InfoTable[] = {
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR) \
{ PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES) \
{PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, \
PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES},
#include "clang/Driver/Options.inc"
#undef OPTION
};

View File

@ -208,12 +208,28 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
// The object size sanitizer should not be enabled at -O0.
Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
bool RemoveObjectSizeAtO0 =
!OptLevel || OptLevel->getOption().matches(options::OPT_O0);
for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
I != E; ++I) {
const auto *Arg = *I;
if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
Arg->claim();
SanitizerMask Add = parseArgValues(D, Arg, true);
SanitizerMask Add = parseArgValues(D, Arg, /*AllowGroups=*/true);
if (RemoveObjectSizeAtO0) {
AllRemove |= SanitizerKind::ObjectSize;
// The user explicitly enabled the object size sanitizer. Warn that
// that this does nothing at -O0.
if (Add & SanitizerKind::ObjectSize)
D.Diag(diag::warn_drv_object_size_disabled_O0)
<< Arg->getAsString(Args);
}
AllAddedKinds |= expandSanitizerGroups(Add);
// Avoid diagnosing any sanitizer which is disabled later.

View File

@ -0,0 +1,120 @@
//===--- Ananas.cpp - Ananas ToolChain Implementations ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "Ananas.h"
#include "InputInfo.h"
#include "CommonArgs.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
void ananas::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const ToolChain &ToolChain = getToolChain();
const Driver &D = ToolChain.getDriver();
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
Args.ClaimAllArgs(options::OPT_g_Group);
// and "clang -emit-llvm foo.o -o foo"
Args.ClaimAllArgs(options::OPT_emit_llvm);
// and for "clang -w foo.o -o foo". Other warning options are already
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
// Ananas only supports static linkage for now.
CmdArgs.push_back("-Bstatic");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
assert(Output.isNothing() && "Invalid output.");
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
Args.AddAllArgs(CmdArgs,
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
if (D.isUsingLTO())
AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX())
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lc");
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
// Ananas - Ananas tool chain which can call as(1) and ld(1) directly.
Ananas::Ananas(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
Tool *Ananas::buildAssembler() const {
return new tools::ananas::Assembler(*this);
}
Tool *Ananas::buildLinker() const { return new tools::ananas::Linker(*this); }

View File

@ -0,0 +1,67 @@
//===--- Ananas.h - Ananas ToolChain Implementations --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ANANAS_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ANANAS_H
#include "Gnu.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
namespace clang {
namespace driver {
namespace tools {
/// ananas -- Directly call GNU Binutils assembler and linker
namespace ananas {
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
public:
Assembler(const ToolChain &TC)
: GnuTool("ananas::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("ananas::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
} // end namespace ananas
} // end namespace tools
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY Ananas : public Generic_ELF {
public:
Ananas(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ANANAS_H

View File

@ -910,6 +910,37 @@ static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
}
}
static void RenderDebugInfoCompressionArgs(const ArgList &Args,
ArgStringList &CmdArgs,
const Driver &D) {
const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ);
if (!A)
return;
if (A->getOption().getID() == options::OPT_gz) {
if (llvm::zlib::isAvailable())
CmdArgs.push_back("-compress-debug-sections");
else
D.Diag(diag::warn_debug_compression_unavailable);
return;
}
StringRef Value = A->getValue();
if (Value == "none") {
CmdArgs.push_back("-compress-debug-sections=none");
} else if (Value == "zlib" || Value == "zlib-gnu") {
if (llvm::zlib::isAvailable()) {
CmdArgs.push_back(
Args.MakeArgString("-compress-debug-sections=" + Twine(Value)));
} else {
D.Diag(diag::warn_debug_compression_unavailable);
}
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
static const char *RelocationModelName(llvm::Reloc::Model Model) {
switch (Model) {
case llvm::Reloc::Static:
@ -1747,10 +1778,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
// arg after parsing the '-I' arg.
bool TakeNextArg = false;
// When using an integrated assembler, translate -Wa, and -Xassembler
// options.
bool CompressDebugSections = false;
bool UseRelaxRelocations = ENABLE_X86_RELAX_RELOCATIONS;
const char *MipsTargetFeature = nullptr;
for (const Arg *A :
@ -1825,12 +1852,11 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back("-massembler-fatal-warnings");
} else if (Value == "--noexecstack") {
CmdArgs.push_back("-mnoexecstack");
} else if (Value == "-compress-debug-sections" ||
Value == "--compress-debug-sections") {
CompressDebugSections = true;
} else if (Value == "-nocompress-debug-sections" ||
} else if (Value.startswith("-compress-debug-sections") ||
Value.startswith("--compress-debug-sections") ||
Value == "-nocompress-debug-sections" ||
Value == "--nocompress-debug-sections") {
CompressDebugSections = false;
CmdArgs.push_back(Value.data());
} else if (Value == "-mrelax-relocations=yes" ||
Value == "--mrelax-relocations=yes") {
UseRelaxRelocations = true;
@ -1883,12 +1909,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
}
}
}
if (CompressDebugSections) {
if (llvm::zlib::isAvailable())
CmdArgs.push_back("-compress-debug-sections");
else
D.Diag(diag::warn_debug_compression_unavailable);
}
if (UseRelaxRelocations)
CmdArgs.push_back("--mrelax-relocations");
if (MipsTargetFeature != nullptr) {
@ -2824,6 +2844,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-generate-type-units");
}
RenderDebugInfoCompressionArgs(Args, CmdArgs, D);
bool UseSeparateSections = isUseSeparateSections(Triple);
if (Args.hasFlag(options::OPT_ffunction_sections,
@ -4927,6 +4949,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
const auto &D = getToolChain().getDriver();
// Don't warn about "clang -w -c foo.s"
Args.ClaimAllArgs(options::OPT_w);
@ -5014,6 +5037,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
}
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
llvm::DebuggerKind::Default);
RenderDebugInfoCompressionArgs(Args, CmdArgs, D);
// Handle -fPIC et al -- the relocation-model affects the assembler
// for some targets.

View File

@ -650,6 +650,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const auto &D = getToolChain().getDriver();
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
@ -660,6 +662,23 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
std::tie(RelocationModel, PICLevel, IsPIE) =
ParsePICArgs(getToolChain(), Args);
if (const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ)) {
if (A->getOption().getID() == options::OPT_gz) {
CmdArgs.push_back("-compress-debug-sections");
} else {
StringRef Value = A->getValue();
if (Value == "none") {
CmdArgs.push_back("-compress-debug-sections=none");
} else if (Value == "zlib" || Value == "zlib-gnu") {
CmdArgs.push_back(
Args.MakeArgString("-compress-debug-sections=" + Twine(Value)));
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
}
switch (getToolChain().getArch()) {
default:
break;
@ -2319,9 +2338,11 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
return true;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
// Enabled for Debian mips64/mips64el only. Other targets are unable to
// distinguish N32 from N64.
if (getTriple().getEnvironment() == llvm::Triple::GNUABI64)
// Enabled for Debian and Android mips64/mipsel, as they can precisely
// identify the ABI in use (Debian) or only use N64 for MIPS64 (Android).
// Other targets are unable to distinguish N32 from N64.
if (getTriple().getEnvironment() == llvm::Triple::GNUABI64 ||
getTriple().isAndroid())
return true;
return false;
default:

View File

@ -83,6 +83,8 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-allow-undefined-file");
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("wasm.syms")));
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lcompiler_rt");
}
@ -104,8 +106,7 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
getProgramPaths().push_back(getDriver().getInstalledDir());
getFilePaths().push_back(
getDriver().SysRoot + "/lib" + (Triple.isArch32Bit() ? "32" : "64"));
getFilePaths().push_back(getDriver().SysRoot + "/lib");
}
bool WebAssembly::IsMathErrnoDefault() const { return false; }

View File

@ -28,13 +28,18 @@ void EditedSource::deconstructMacroArgLoc(SourceLocation Loc,
MacroArgUse &ArgUse) {
assert(SourceMgr.isMacroArgExpansion(Loc));
SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first;
ExpansionLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
SourceLocation ImmediateExpansionLoc =
SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
ExpansionLoc = ImmediateExpansionLoc;
while (SourceMgr.isMacroBodyExpansion(ExpansionLoc))
ExpansionLoc = SourceMgr.getImmediateExpansionRange(ExpansionLoc).first;
SmallString<20> Buf;
StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
Buf, SourceMgr, LangOpts);
ArgUse = {nullptr, SourceLocation()};
ArgUse = MacroArgUse{nullptr, SourceLocation(), SourceLocation()};
if (!ArgName.empty())
ArgUse = {&IdentTable.get(ArgName), SourceMgr.getSpellingLoc(DefArgLoc)};
ArgUse = {&IdentTable.get(ArgName), ImmediateExpansionLoc,
SourceMgr.getSpellingLoc(DefArgLoc)};
}
void EditedSource::startingCommit() {}
@ -69,10 +74,11 @@ bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
auto I = ExpansionToArgMap.find(ExpLoc.getRawEncoding());
if (I != ExpansionToArgMap.end() &&
std::find_if(
I->second.begin(), I->second.end(), [&](const MacroArgUse &U) {
return ArgUse.first == U.first && ArgUse.second != U.second;
}) != I->second.end()) {
find_if(I->second, [&](const MacroArgUse &U) {
return ArgUse.Identifier == U.Identifier &&
std::tie(ArgUse.ImmediateExpansionLoc, ArgUse.UseLoc) !=
std::tie(U.ImmediateExpansionLoc, U.UseLoc);
}) != I->second.end()) {
// Trying to write in a macro argument input that has already been
// written by a previous commit for another expansion of the same macro
// argument name. For example:
@ -89,7 +95,6 @@ bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
return false;
}
}
return true;
}
@ -102,13 +107,13 @@ bool EditedSource::commitInsert(SourceLocation OrigLoc,
return true;
if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
SourceLocation ExpLoc;
MacroArgUse ArgUse;
SourceLocation ExpLoc;
deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
if (ArgUse.first)
if (ArgUse.Identifier)
CurrCommitMacroArgExps.emplace_back(ExpLoc, ArgUse);
}
FileEdit &FA = FileEdits[Offs];
if (FA.Text.empty()) {
FA.Text = copyString(text);

View File

@ -13,6 +13,7 @@ add_clang_library(clangFormat
TokenAnnotator.cpp
UnwrappedLineFormatter.cpp
UnwrappedLineParser.cpp
UsingDeclarationsSorter.cpp
WhitespaceManager.cpp
LINK_LIBS

View File

@ -453,7 +453,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
State.Column += Spaces;
if (Current.isNot(tok::comment) && Previous.is(tok::l_paren) &&
Previous.Previous &&
Previous.Previous->isOneOf(tok::kw_if, tok::kw_for)) {
(Previous.Previous->isOneOf(tok::kw_if, tok::kw_for) ||
Previous.Previous->endsSequence(tok::kw_constexpr, tok::kw_if))) {
// Treat the condition inside an if as if it was a second function
// parameter, i.e. let nested calls have a continuation indent.
State.Stack.back().LastSpace = State.Column;
@ -1049,7 +1050,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
(Current.is(TT_ArrayInitializerLSquare) && EndsInComma) ||
Current.is(TT_DictLiteral) ||
Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments ||
(NextNoComment && NextNoComment->is(TT_DesignatedInitializerPeriod));
(NextNoComment &&
NextNoComment->isOneOf(TT_DesignatedInitializerPeriod,
TT_DesignatedInitializerLSquare));
if (Current.ParameterCount > 1)
NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
} else {

View File

@ -23,6 +23,7 @@
#include "TokenAnnotator.h"
#include "UnwrappedLineFormatter.h"
#include "UnwrappedLineParser.h"
#include "UsingDeclarationsSorter.h"
#include "WhitespaceManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
@ -96,6 +97,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
IO.enumCase(Value, "All", FormatStyle::SFS_All);
IO.enumCase(Value, "true", FormatStyle::SFS_All);
IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
}
};
@ -377,6 +379,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
IO.mapOptional("ReflowComments", Style.ReflowComments);
IO.mapOptional("SortIncludes", Style.SortIncludes);
IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword);
IO.mapOptional("SpaceBeforeAssignmentOperators",
@ -617,6 +620,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.DisableFormat = false;
LLVMStyle.SortIncludes = true;
LLVMStyle.SortUsingDeclarations = true;
return LLVMStyle;
}
@ -771,6 +775,7 @@ FormatStyle getNoStyle() {
FormatStyle NoStyle = getLLVMStyle();
NoStyle.DisableFormat = true;
NoStyle.SortIncludes = false;
NoStyle.SortUsingDeclarations = false;
return NoStyle;
}
@ -1877,38 +1882,53 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
return tooling::Replacements();
if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
return tooling::Replacements();
auto Env = Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
auto reformatAfterApplying = [&] (TokenAnalyzer& Fixer) {
tooling::Replacements Fixes = Fixer.process();
if (!Fixes.empty()) {
auto NewCode = applyAllReplacements(Code, Fixes);
if (NewCode) {
auto NewEnv = Environment::CreateVirtualEnvironment(
*NewCode, FileName,
tooling::calculateRangesAfterReplacements(Fixes, Ranges));
Formatter Format(*NewEnv, Expanded, Status);
return Fixes.merge(Format.process());
}
}
Formatter Format(*Env, Expanded, Status);
return Format.process();
};
typedef std::function<tooling::Replacements(const Environment &)>
AnalyzerPass;
SmallVector<AnalyzerPass, 4> Passes;
if (Style.Language == FormatStyle::LK_Cpp &&
Style.FixNamespaceComments) {
NamespaceEndCommentsFixer CommentsFixer(*Env, Expanded);
return reformatAfterApplying(CommentsFixer);
if (Style.Language == FormatStyle::LK_Cpp) {
if (Style.FixNamespaceComments)
Passes.emplace_back([&](const Environment &Env) {
return NamespaceEndCommentsFixer(Env, Expanded).process();
});
if (Style.SortUsingDeclarations)
Passes.emplace_back([&](const Environment &Env) {
return UsingDeclarationsSorter(Env, Expanded).process();
});
}
if (Style.Language == FormatStyle::LK_JavaScript &&
Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
JavaScriptRequoter Requoter(*Env, Expanded);
return reformatAfterApplying(Requoter);
Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
Passes.emplace_back([&](const Environment &Env) {
return JavaScriptRequoter(Env, Expanded).process();
});
Passes.emplace_back([&](const Environment &Env) {
return Formatter(Env, Expanded, Status).process();
});
std::unique_ptr<Environment> Env =
Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
llvm::Optional<std::string> CurrentCode = None;
tooling::Replacements Fixes;
for (size_t I = 0, E = Passes.size(); I < E; ++I) {
tooling::Replacements PassFixes = Passes[I](*Env);
auto NewCode = applyAllReplacements(
CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes);
if (NewCode) {
Fixes = Fixes.merge(PassFixes);
if (I + 1 < E) {
CurrentCode = std::move(*NewCode);
Env = Environment::CreateVirtualEnvironment(
*CurrentCode, FileName,
tooling::calculateRangesAfterReplacements(Fixes, Ranges));
}
}
}
Formatter Format(*Env, Expanded, Status);
return Format.process();
return Fixes;
}
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
@ -1943,6 +1963,16 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
return Fix.process();
}
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName) {
std::unique_ptr<Environment> Env =
Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
UsingDeclarationsSorter Sorter(*Env, Style);
return Sorter.process();
}
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOptions LangOpts;
LangOpts.CPlusPlus = 1;

View File

@ -39,6 +39,7 @@ namespace format {
TYPE(ConflictStart) \
TYPE(CtorInitializerColon) \
TYPE(CtorInitializerComma) \
TYPE(DesignatedInitializerLSquare) \
TYPE(DesignatedInitializerPeriod) \
TYPE(DictLiteral) \
TYPE(ForEachMacro) \

View File

@ -145,6 +145,7 @@ class AnnotatingParser {
(Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
tok::kw_if, tok::kw_while, tok::l_paren,
tok::comma) ||
Left->Previous->endsSequence(tok::kw_constexpr, tok::kw_if) ||
Left->Previous->is(TT_BinaryOperator))) {
// static_assert, if and while usually contain expressions.
Contexts.back().IsExpression = true;
@ -339,6 +340,9 @@ class AnnotatingParser {
Contexts.back().ContextKind == tok::l_brace &&
Parent->isOneOf(tok::l_brace, tok::comma)) {
Left->Type = TT_JsComputedPropertyName;
} else if (Style.isCpp() && Contexts.back().ContextKind == tok::l_brace &&
Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
Left->Type = TT_DesignatedInitializerLSquare;
} else if (CurrentToken->is(tok::r_square) && Parent &&
Parent->is(TT_TemplateCloser)) {
Left->Type = TT_ArraySubscriptLSquare;
@ -391,7 +395,8 @@ class AnnotatingParser {
if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
return false;
if (CurrentToken->is(tok::colon)) {
if (Left->is(TT_ArraySubscriptLSquare)) {
if (Left->isOneOf(TT_ArraySubscriptLSquare,
TT_DesignatedInitializerLSquare)) {
Left->Type = TT_ObjCMethodExpr;
StartsObjCMethodExpr = true;
Contexts.back().ColonIsObjCMethodExpr = true;
@ -572,6 +577,8 @@ class AnnotatingParser {
break;
case tok::kw_if:
case tok::kw_while:
if (Tok->is(tok::kw_if) && CurrentToken && CurrentToken->is(tok::kw_constexpr))
next();
if (CurrentToken && CurrentToken->is(tok::l_paren)) {
next();
if (!parseParens(/*LookForDecls=*/true))
@ -1972,7 +1979,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal))
return 35;
if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_ArrayInitializerLSquare))
TT_ArrayInitializerLSquare,
TT_DesignatedInitializerLSquare))
return 500;
}
@ -2060,7 +2068,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign)
return 100;
if (Left.is(tok::l_paren) && Left.Previous &&
Left.Previous->isOneOf(tok::kw_if, tok::kw_for))
(Left.Previous->isOneOf(tok::kw_if, tok::kw_for)
|| Left.Previous->endsSequence(tok::kw_constexpr, tok::kw_if)))
return 1000;
if (Left.is(tok::equal) && InFunctionDecl)
return 110;
@ -2192,7 +2201,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
(Style.SpacesInSquareBrackets &&
Right.MatchingParen->is(TT_ArraySubscriptLSquare)));
if (Right.is(tok::l_square) &&
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare) &&
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_DesignatedInitializerLSquare) &&
!Left.isOneOf(tok::numeric_constant, TT_DictLiteral))
return false;
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
@ -2211,6 +2221,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
(Left.isOneOf(tok::kw_if, tok::pp_elif, tok::kw_for, tok::kw_while,
tok::kw_switch, tok::kw_case, TT_ForEachMacro,
TT_ObjCForIn) ||
Left.endsSequence(tok::kw_constexpr, tok::kw_if) ||
(Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
tok::kw_new, tok::kw_delete) &&
(!Left.Previous || Left.Previous->isNot(tok::period))))) ||
@ -2391,8 +2402,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.is(tok::greater) && Right.is(tok::greater))
return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
(Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
if (Right.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar))
if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
(Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod)))
return false;
if (!Style.SpaceBeforeAssignmentOperators &&
Right.getPrecedence() == prec::Assignment)
@ -2468,8 +2480,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty ||
(Left.NestingLevel == 0 && Line.Level == 0 &&
Style.AllowShortFunctionsOnASingleLine ==
FormatStyle::SFS_Inline);
Style.AllowShortFunctionsOnASingleLine &
FormatStyle::SFS_InlineOnly);
} else if (Style.Language == FormatStyle::LK_Java) {
if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
Right.Next->is(tok::string_literal))

View File

@ -226,7 +226,7 @@ class LineJoiner {
Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All ||
(Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
I[1]->First->is(tok::r_brace)) ||
(Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline &&
(Style.AllowShortFunctionsOnASingleLine & FormatStyle::SFS_InlineOnly &&
TheLine->Level != 0);
if (Style.CompactNamespaces) {
@ -434,8 +434,11 @@ class LineJoiner {
} else if (Limit != 0 && !Line.startsWith(tok::kw_namespace) &&
!startsExternCBlock(Line)) {
// We don't merge short records.
if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct,
Keywords.kw_interface))
FormatToken *RecordTok =
Line.First->is(tok::kw_typedef) ? Line.First->Next : Line.First;
if (RecordTok &&
RecordTok->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct,
Keywords.kw_interface))
return 0;
// Check that we still have three lines and they fit into the limit.

View File

@ -1516,6 +1516,8 @@ void UnwrappedLineParser::parseSquare() {
void UnwrappedLineParser::parseIfThenElse() {
assert(FormatTok->Tok.is(tok::kw_if) && "'if' expected");
nextToken();
if (FormatTok->Tok.is(tok::kw_constexpr))
nextToken();
if (FormatTok->Tok.is(tok::l_paren))
parseParens();
bool NeedsUnwrappedLine = false;

View File

@ -0,0 +1,144 @@
//===--- UsingDeclarationsSorter.cpp ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file implements UsingDeclarationsSorter, a TokenAnalyzer that
/// sorts consecutive using declarations.
///
//===----------------------------------------------------------------------===//
#include "UsingDeclarationsSorter.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Regex.h"
#include <algorithm>
#define DEBUG_TYPE "using-declarations-sorter"
namespace clang {
namespace format {
namespace {
struct UsingDeclaration {
const AnnotatedLine *Line;
std::string Label;
UsingDeclaration(const AnnotatedLine *Line, const std::string &Label)
: Line(Line), Label(Label) {}
bool operator<(const UsingDeclaration &Other) const {
return Label < Other.Label;
}
};
/// Computes the label of a using declaration starting at tthe using token
/// \p UsingTok.
/// If \p UsingTok doesn't begin a using declaration, returns the empty string.
/// Note that this detects specifically using declarations, as in:
/// using A::B::C;
/// and not type aliases, as in:
/// using A = B::C;
/// Type aliases are in general not safe to permute.
std::string computeUsingDeclarationLabel(const FormatToken *UsingTok) {
assert(UsingTok && UsingTok->is(tok::kw_using) && "Expecting a using token");
std::string Label;
const FormatToken *Tok = UsingTok->Next;
if (Tok && Tok->is(tok::kw_typename)) {
Label.append("typename ");
Tok = Tok->Next;
}
if (Tok && Tok->is(tok::coloncolon)) {
Label.append("::");
Tok = Tok->Next;
}
bool HasIdentifier = false;
while (Tok && Tok->is(tok::identifier)) {
HasIdentifier = true;
Label.append(Tok->TokenText.str());
Tok = Tok->Next;
if (!Tok || Tok->isNot(tok::coloncolon))
break;
Label.append("::");
Tok = Tok->Next;
}
if (HasIdentifier && Tok && Tok->isOneOf(tok::semi, tok::comma))
return Label;
return "";
}
void endUsingDeclarationBlock(
SmallVectorImpl<UsingDeclaration> *UsingDeclarations,
const SourceManager &SourceMgr, tooling::Replacements *Fixes) {
SmallVector<UsingDeclaration, 4> SortedUsingDeclarations(
UsingDeclarations->begin(), UsingDeclarations->end());
std::sort(SortedUsingDeclarations.begin(), SortedUsingDeclarations.end());
for (size_t I = 0, E = UsingDeclarations->size(); I < E; ++I) {
if ((*UsingDeclarations)[I].Line == SortedUsingDeclarations[I].Line)
continue;
auto Begin = (*UsingDeclarations)[I].Line->First->Tok.getLocation();
auto End = (*UsingDeclarations)[I].Line->Last->Tok.getEndLoc();
auto SortedBegin =
SortedUsingDeclarations[I].Line->First->Tok.getLocation();
auto SortedEnd = SortedUsingDeclarations[I].Line->Last->Tok.getEndLoc();
StringRef Text(SourceMgr.getCharacterData(SortedBegin),
SourceMgr.getCharacterData(SortedEnd) -
SourceMgr.getCharacterData(SortedBegin));
DEBUG({
StringRef OldText(SourceMgr.getCharacterData(Begin),
SourceMgr.getCharacterData(End) -
SourceMgr.getCharacterData(Begin));
llvm::dbgs() << "Replacing '" << OldText << "' with '" << Text << "'\n";
});
auto Range = CharSourceRange::getCharRange(Begin, End);
auto Err = Fixes->add(tooling::Replacement(SourceMgr, Range, Text));
if (Err) {
llvm::errs() << "Error while sorting using declarations: "
<< llvm::toString(std::move(Err)) << "\n";
}
}
UsingDeclarations->clear();
}
} // namespace
UsingDeclarationsSorter::UsingDeclarationsSorter(const Environment &Env,
const FormatStyle &Style)
: TokenAnalyzer(Env, Style) {}
tooling::Replacements UsingDeclarationsSorter::analyze(
TokenAnnotator &Annotator, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) {
const SourceManager &SourceMgr = Env.getSourceManager();
AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
AnnotatedLines.end());
tooling::Replacements Fixes;
SmallVector<UsingDeclaration, 4> UsingDeclarations;
for (size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) {
if (!AnnotatedLines[I]->Affected || AnnotatedLines[I]->InPPDirective ||
!AnnotatedLines[I]->startsWith(tok::kw_using) ||
AnnotatedLines[I]->First->Finalized) {
endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
continue;
}
if (AnnotatedLines[I]->First->NewlinesBefore > 1)
endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
std::string Label = computeUsingDeclarationLabel(AnnotatedLines[I]->First);
if (Label.empty()) {
endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
continue;
}
UsingDeclarations.push_back(UsingDeclaration(AnnotatedLines[I], Label));
}
endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
return Fixes;
}
} // namespace format
} // namespace clang

View File

@ -0,0 +1,37 @@
//===--- UsingDeclarationsSorter.h ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file declares UsingDeclarationsSorter, a TokenAnalyzer that
/// sorts consecutive using declarations.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_FORMAT_USINGDECLARATIONSSORTER_H
#define LLVM_CLANG_LIB_FORMAT_USINGDECLARATIONSSORTER_H
#include "TokenAnalyzer.h"
namespace clang {
namespace format {
class UsingDeclarationsSorter : public TokenAnalyzer {
public:
UsingDeclarationsSorter(const Environment &Env, const FormatStyle &Style);
tooling::Replacements
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override;
};
} // end namespace format
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,7 @@ add_clang_library(clangFrontend
ModuleDependencyCollector.cpp
MultiplexConsumer.cpp
PCHContainerOperations.cpp
PrecompiledPreamble.cpp
PrintPreprocessedOutput.cpp
SerializedDiagnosticPrinter.cpp
SerializedDiagnosticReader.cpp

View File

@ -11,6 +11,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/MemoryBufferCache.h"
@ -1902,17 +1903,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
void CompilerInstance::loadModuleFromSource(SourceLocation ImportLoc,
StringRef ModuleName,
StringRef Source) {
// Avoid creating filenames with special characters.
SmallString<128> CleanModuleName(ModuleName);
for (auto &C : CleanModuleName)
if (!isAlphanumeric(C))
C = '_';
// FIXME: Using a randomized filename here means that our intermediate .pcm
// output is nondeterministic (as .pcm files refer to each other by name).
// Can this affect the output in any way?
SmallString<128> ModuleFileName;
if (std::error_code EC = llvm::sys::fs::createTemporaryFile(
ModuleName, "pcm", ModuleFileName)) {
CleanModuleName, "pcm", ModuleFileName)) {
getDiagnostics().Report(ImportLoc, diag::err_fe_unable_to_open_output)
<< ModuleFileName << EC.message();
return;
}
std::string ModuleMapFileName = (ModuleName + ".map").str();
std::string ModuleMapFileName = (CleanModuleName + ".map").str();
FrontendInputFile Input(
ModuleMapFileName,

View File

@ -745,9 +745,22 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
Opts.CallFEntry = Args.hasArg(OPT_mfentry);
Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
// TODO: map this from -gz in the driver and give it a named value
if (Args.hasArg(OPT_compress_debug_sections))
Opts.setCompressDebugSections(llvm::DebugCompressionType::GNU);
if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections,
OPT_compress_debug_sections_EQ)) {
if (A->getOption().getID() == OPT_compress_debug_sections) {
// TODO: be more clever about the compression type auto-detection
Opts.setCompressDebugSections(llvm::DebugCompressionType::GNU);
} else {
auto DCT = llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
.Case("none", llvm::DebugCompressionType::None)
.Case("zlib", llvm::DebugCompressionType::Z)
.Case("zlib-gnu", llvm::DebugCompressionType::GNU)
.Default(llvm::DebugCompressionType::None);
Opts.setCompressDebugSections(DCT);
}
}
Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) {
@ -892,14 +905,18 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DiagnosticsWithHotness =
Args.hasArg(options::OPT_fdiagnostics_show_hotness);
bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
if (Opts.DiagnosticsWithHotness &&
Opts.getProfileUse() == CodeGenOptions::ProfileNone)
Opts.getProfileUse() == CodeGenOptions::ProfileNone &&
!UsingSampleProfile) {
Diags.Report(diag::warn_drv_fdiagnostics_show_hotness_requires_pgo);
}
// If the user requested to use a sample profile for PGO, then the
// backend will need to track source location information so the profile
// can be incorporated into the IR.
if (!Opts.SampleProfileFile.empty())
if (UsingSampleProfile)
NeedLocTracking = true;
// If the user requested a flag that requires source locations available in
@ -2379,9 +2396,51 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders);
}
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
switch (Action) {
case frontend::ASTDeclList:
case frontend::ASTDump:
case frontend::ASTPrint:
case frontend::ASTView:
case frontend::EmitAssembly:
case frontend::EmitBC:
case frontend::EmitHTML:
case frontend::EmitLLVM:
case frontend::EmitLLVMOnly:
case frontend::EmitCodeGenOnly:
case frontend::EmitObj:
case frontend::FixIt:
case frontend::GenerateModule:
case frontend::GenerateModuleInterface:
case frontend::GeneratePCH:
case frontend::GeneratePTH:
case frontend::ParseSyntaxOnly:
case frontend::ModuleFileInfo:
case frontend::VerifyPCH:
case frontend::PluginAction:
case frontend::PrintDeclContext:
case frontend::RewriteObjC:
case frontend::RewriteTest:
case frontend::RunAnalysis:
case frontend::MigrateSource:
return false;
case frontend::DumpRawTokens:
case frontend::DumpTokens:
case frontend::InitOnly:
case frontend::PrintPreamble:
case frontend::PrintPreprocessedInput:
case frontend::RewriteMacros:
case frontend::RunPreprocessorOnly:
return true;
}
llvm_unreachable("invalid frontend action");
}
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
FileManager &FileMgr,
DiagnosticsEngine &Diags) {
DiagnosticsEngine &Diags,
frontend::ActionKind Action) {
using namespace options;
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
@ -2454,6 +2513,12 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
else
Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library;
}
// Always avoid lexing editor placeholders when we're just running the
// preprocessor as we never want to emit the
// "editor placeholder in source file" error in PP only mode.
if (isStrictlyPreprocessorAction(Action))
Opts.LexEditorPlaceholders = false;
}
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
@ -2461,45 +2526,10 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
frontend::ActionKind Action) {
using namespace options;
switch (Action) {
case frontend::ASTDeclList:
case frontend::ASTDump:
case frontend::ASTPrint:
case frontend::ASTView:
case frontend::EmitAssembly:
case frontend::EmitBC:
case frontend::EmitHTML:
case frontend::EmitLLVM:
case frontend::EmitLLVMOnly:
case frontend::EmitCodeGenOnly:
case frontend::EmitObj:
case frontend::FixIt:
case frontend::GenerateModule:
case frontend::GenerateModuleInterface:
case frontend::GeneratePCH:
case frontend::GeneratePTH:
case frontend::ParseSyntaxOnly:
case frontend::ModuleFileInfo:
case frontend::VerifyPCH:
case frontend::PluginAction:
case frontend::PrintDeclContext:
case frontend::RewriteObjC:
case frontend::RewriteTest:
case frontend::RunAnalysis:
case frontend::MigrateSource:
Opts.ShowCPP = 0;
break;
case frontend::DumpRawTokens:
case frontend::DumpTokens:
case frontend::InitOnly:
case frontend::PrintPreamble:
case frontend::PrintPreprocessedInput:
case frontend::RewriteMacros:
case frontend::RunPreprocessorOnly:
if (isStrictlyPreprocessorAction(Action))
Opts.ShowCPP = !Args.hasArg(OPT_dM);
break;
}
else
Opts.ShowCPP = 0;
Opts.ShowComments = Args.hasArg(OPT_C);
Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
@ -2626,7 +2656,8 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
// ParsePreprocessorArgs and remove the FileManager
// parameters from the function and the "FileManager.h" #include.
FileManager FileMgr(Res.getFileSystemOpts());
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags);
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags,
Res.getFrontendOpts().ProgramAction);
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
Res.getFrontendOpts().ProgramAction);

View File

@ -561,7 +561,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.setFileManager(&AST->getFileManager());
CI.createSourceManager(CI.getFileManager());
CI.getSourceManager().initializeForReplay(AST->getSourceManager());
CI.createPreprocessor(getTranslationUnitKind());
// Set up the input file for replay purposes.
auto Kind = AST->getInputKind();

View File

@ -517,7 +517,7 @@ void PrintPreprocessedAction::ExecuteAction() {
// file. This is mostly a sanity check in case the file has no
// newlines whatsoever.
if (end - cur > 256) end = cur + 256;
while (next < end) {
if (*cur == 0x0D) { // CR
if (*next == 0x0A) // CRLF

View File

@ -0,0 +1,563 @@
//===--- PrecompiledPreamble.cpp - Build precompiled preambles --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Helper class to build precompiled preamble.
//
//===----------------------------------------------------------------------===//
#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ASTWriter.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
using namespace clang;
namespace {
/// Keeps a track of files to be deleted in destructor.
class TemporaryFiles {
public:
// A static instance to be used by all clients.
static TemporaryFiles &getInstance();
private:
// Disallow constructing the class directly.
TemporaryFiles() = default;
// Disallow copy.
TemporaryFiles(const TemporaryFiles &) = delete;
public:
~TemporaryFiles();
/// Adds \p File to a set of tracked files.
void addFile(StringRef File);
/// Remove \p File from disk and from the set of tracked files.
void removeFile(StringRef File);
private:
llvm::sys::SmartMutex<false> Mutex;
llvm::StringSet<> Files;
};
TemporaryFiles &TemporaryFiles::getInstance() {
static TemporaryFiles Instance;
return Instance;
}
TemporaryFiles::~TemporaryFiles() {
llvm::MutexGuard Guard(Mutex);
for (const auto &File : Files)
llvm::sys::fs::remove(File.getKey());
}
void TemporaryFiles::addFile(StringRef File) {
llvm::MutexGuard Guard(Mutex);
auto IsInserted = Files.insert(File).second;
(void)IsInserted;
assert(IsInserted && "File has already been added");
}
void TemporaryFiles::removeFile(StringRef File) {
llvm::MutexGuard Guard(Mutex);
auto WasPresent = Files.erase(File);
(void)WasPresent;
assert(WasPresent && "File was not tracked");
llvm::sys::fs::remove(File);
}
class PreambleMacroCallbacks : public PPCallbacks {
public:
PreambleMacroCallbacks(PreambleCallbacks &Callbacks) : Callbacks(Callbacks) {}
void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) override {
Callbacks.HandleMacroDefined(MacroNameTok, MD);
}
private:
PreambleCallbacks &Callbacks;
};
class PrecompilePreambleAction : public ASTFrontendAction {
public:
PrecompilePreambleAction(PreambleCallbacks &Callbacks)
: Callbacks(Callbacks) {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
bool hasEmittedPreamblePCH() const { return HasEmittedPreamblePCH; }
void setEmittedPreamblePCH(ASTWriter &Writer) {
this->HasEmittedPreamblePCH = true;
Callbacks.AfterPCHEmitted(Writer);
}
bool shouldEraseOutputFiles() override { return !hasEmittedPreamblePCH(); }
bool hasCodeCompletionSupport() const override { return false; }
bool hasASTFileSupport() const override { return false; }
TranslationUnitKind getTranslationUnitKind() override { return TU_Prefix; }
private:
friend class PrecompilePreambleConsumer;
bool HasEmittedPreamblePCH = false;
PreambleCallbacks &Callbacks;
};
class PrecompilePreambleConsumer : public PCHGenerator {
public:
PrecompilePreambleConsumer(PrecompilePreambleAction &Action,
const Preprocessor &PP, StringRef isysroot,
std::unique_ptr<raw_ostream> Out)
: PCHGenerator(PP, "", isysroot, std::make_shared<PCHBuffer>(),
ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
/*AllowASTWithErrors=*/true),
Action(Action), Out(std::move(Out)) {}
bool HandleTopLevelDecl(DeclGroupRef DG) override {
Action.Callbacks.HandleTopLevelDecl(DG);
return true;
}
void HandleTranslationUnit(ASTContext &Ctx) override {
PCHGenerator::HandleTranslationUnit(Ctx);
if (!hasEmittedPCH())
return;
// Write the generated bitstream to "Out".
*Out << getPCH();
// Make sure it hits disk now.
Out->flush();
// Free the buffer.
llvm::SmallVector<char, 0> Empty;
getPCH() = std::move(Empty);
Action.setEmittedPreamblePCH(getWriter());
}
private:
PrecompilePreambleAction &Action;
std::unique_ptr<raw_ostream> Out;
};
std::unique_ptr<ASTConsumer>
PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
std::unique_ptr<raw_ostream> OS =
GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
OutputFile);
if (!OS)
return nullptr;
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
CI.getPreprocessor().addPPCallbacks(
llvm::make_unique<PreambleMacroCallbacks>(Callbacks));
return llvm::make_unique<PrecompilePreambleConsumer>(
*this, CI.getPreprocessor(), Sysroot, std::move(OS));
}
template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
if (!Val)
return false;
Output = std::move(*Val);
return true;
}
} // namespace
PreambleBounds clang::ComputePreambleBounds(const LangOptions &LangOpts,
llvm::MemoryBuffer *Buffer,
unsigned MaxLines) {
auto Pre = Lexer::ComputePreamble(Buffer->getBuffer(), LangOpts, MaxLines);
return PreambleBounds(Pre.first, Pre.second);
}
llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
PreambleCallbacks &Callbacks) {
assert(VFS && "VFS is null");
if (!Bounds.Size)
return BuildPreambleError::PreambleIsEmpty;
auto PreambleInvocation = std::make_shared<CompilerInvocation>(Invocation);
FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts();
PreprocessorOptions &PreprocessorOpts =
PreambleInvocation->getPreprocessorOpts();
// Create a temporary file for the precompiled preamble. In rare
// circumstances, this can fail.
llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PreamblePCHFile =
PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile();
if (!PreamblePCHFile)
return BuildPreambleError::CouldntCreateTempFile;
// Save the preamble text for later; we'll need to compare against it for
// subsequent reparses.
std::vector<char> PreambleBytes(MainFileBuffer->getBufferStart(),
MainFileBuffer->getBufferStart() +
Bounds.Size);
bool PreambleEndsAtStartOfLine = Bounds.PreambleEndsAtStartOfLine;
// Tell the compiler invocation to generate a temporary precompiled header.
FrontendOpts.ProgramAction = frontend::GeneratePCH;
// FIXME: Generate the precompiled header into memory?
FrontendOpts.OutputFile = PreamblePCHFile->getFilePath();
PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
PreprocessorOpts.PrecompiledPreambleBytes.second = false;
// Create the compiler instance to use for building the precompiled preamble.
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(std::move(PCHContainerOps)));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(
Clang.get());
Clang->setInvocation(std::move(PreambleInvocation));
Clang->setDiagnostics(&Diagnostics);
// Create the target instance.
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
if (!Clang->hasTarget())
return BuildPreambleError::CouldntCreateTargetInfo;
// Inform the target of the language options.
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
Clang->getTarget().adjust(Clang->getLangOpts());
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
InputKind::Source &&
"FIXME: AST inputs not yet supported here!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
InputKind::LLVM_IR &&
"IR inputs not support here!");
// Clear out old caches and data.
Diagnostics.Reset();
ProcessWarningOptions(Diagnostics, Clang->getDiagnosticOpts());
VFS =
createVFSFromCompilerInvocation(Clang->getInvocation(), Diagnostics, VFS);
if (!VFS)
return BuildPreambleError::CouldntCreateVFSOverlay;
// Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
// Create the source manager.
Clang->setSourceManager(
new SourceManager(Diagnostics, Clang->getFileManager()));
auto PreambleDepCollector = std::make_shared<DependencyCollector>();
Clang->addDependencyCollector(PreambleDepCollector);
// Remap the main source file to the preamble buffer.
StringRef MainFilePath = FrontendOpts.Inputs[0].getFile();
auto PreambleInputBuffer = llvm::MemoryBuffer::getMemBufferCopy(
MainFileBuffer->getBuffer().slice(0, Bounds.Size), MainFilePath);
if (PreprocessorOpts.RetainRemappedFileBuffers) {
// MainFileBuffer will be deleted by unique_ptr after leaving the method.
PreprocessorOpts.addRemappedFile(MainFilePath, PreambleInputBuffer.get());
} else {
// In that case, remapped buffer will be deleted by CompilerInstance on
// BeginSourceFile, so we call release() to avoid double deletion.
PreprocessorOpts.addRemappedFile(MainFilePath,
PreambleInputBuffer.release());
}
std::unique_ptr<PrecompilePreambleAction> Act;
Act.reset(new PrecompilePreambleAction(Callbacks));
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
return BuildPreambleError::BeginSourceFileFailed;
Act->Execute();
// Run the callbacks.
Callbacks.AfterExecute(*Clang);
Act->EndSourceFile();
if (!Act->hasEmittedPreamblePCH())
return BuildPreambleError::CouldntEmitPCH;
// Keep track of all of the files that the source manager knows about,
// so we can verify whether they have changed or not.
llvm::StringMap<PrecompiledPreamble::PreambleFileHash> FilesInPreamble;
SourceManager &SourceMgr = Clang->getSourceManager();
for (auto &Filename : PreambleDepCollector->getDependencies()) {
const FileEntry *File = Clang->getFileManager().getFile(Filename);
if (!File || File == SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()))
continue;
if (time_t ModTime = File->getModificationTime()) {
FilesInPreamble[File->getName()] =
PrecompiledPreamble::PreambleFileHash::createForFile(File->getSize(),
ModTime);
} else {
llvm::MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File);
FilesInPreamble[File->getName()] =
PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(Buffer);
}
}
return PrecompiledPreamble(
std::move(*PreamblePCHFile), std::move(PreambleBytes),
PreambleEndsAtStartOfLine, std::move(FilesInPreamble));
}
PreambleBounds PrecompiledPreamble::getBounds() const {
return PreambleBounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
}
bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer,
PreambleBounds Bounds,
vfs::FileSystem *VFS) const {
assert(
Bounds.Size <= MainFileBuffer->getBufferSize() &&
"Buffer is too large. Bounds were calculated from a different buffer?");
auto PreambleInvocation = std::make_shared<CompilerInvocation>(Invocation);
PreprocessorOptions &PreprocessorOpts =
PreambleInvocation->getPreprocessorOpts();
if (!Bounds.Size)
return false;
// We've previously computed a preamble. Check whether we have the same
// preamble now that we did before, and that there's enough space in
// the main-file buffer within the precompiled preamble to fit the
// new main file.
if (PreambleBytes.size() != Bounds.Size ||
PreambleEndsAtStartOfLine != Bounds.PreambleEndsAtStartOfLine ||
memcmp(PreambleBytes.data(), MainFileBuffer->getBufferStart(),
Bounds.Size) != 0)
return false;
// The preamble has not changed. We may be able to re-use the precompiled
// preamble.
// Check that none of the files used by the preamble have changed.
// First, make a record of those files that have been overridden via
// remapping or unsaved_files.
std::map<llvm::sys::fs::UniqueID, PreambleFileHash> OverriddenFiles;
for (const auto &R : PreprocessorOpts.RemappedFiles) {
vfs::Status Status;
if (!moveOnNoError(VFS->status(R.second), Status)) {
// If we can't stat the file we're remapping to, assume that something
// horrible happened.
return false;
}
OverriddenFiles[Status.getUniqueID()] = PreambleFileHash::createForFile(
Status.getSize(), llvm::sys::toTimeT(Status.getLastModificationTime()));
}
for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
vfs::Status Status;
if (!moveOnNoError(VFS->status(RB.first), Status))
return false;
OverriddenFiles[Status.getUniqueID()] =
PreambleFileHash::createForMemoryBuffer(RB.second);
}
// Check whether anything has changed.
for (const auto &F : FilesInPreamble) {
vfs::Status Status;
if (!moveOnNoError(VFS->status(F.first()), Status)) {
// If we can't stat the file, assume that something horrible happened.
return false;
}
std::map<llvm::sys::fs::UniqueID, PreambleFileHash>::iterator Overridden =
OverriddenFiles.find(Status.getUniqueID());
if (Overridden != OverriddenFiles.end()) {
// This file was remapped; check whether the newly-mapped file
// matches up with the previous mapping.
if (Overridden->second != F.second)
return false;
continue;
}
// The file was not remapped; check whether it has changed on disk.
if (Status.getSize() != uint64_t(F.second.Size) ||
llvm::sys::toTimeT(Status.getLastModificationTime()) !=
F.second.ModTime)
return false;
}
return true;
}
void PrecompiledPreamble::AddImplicitPreamble(
CompilerInvocation &CI, llvm::MemoryBuffer *MainFileBuffer) const {
auto &PreprocessorOpts = CI.getPreprocessorOpts();
// Configure ImpicitPCHInclude.
PreprocessorOpts.PrecompiledPreambleBytes.first = PreambleBytes.size();
PreprocessorOpts.PrecompiledPreambleBytes.second = PreambleEndsAtStartOfLine;
PreprocessorOpts.ImplicitPCHInclude = PCHFile.getFilePath();
PreprocessorOpts.DisablePCHValidation = true;
// Remap main file to point to MainFileBuffer.
auto MainFilePath = CI.getFrontendOpts().Inputs[0].getFile();
PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer);
}
PrecompiledPreamble::PrecompiledPreamble(
TempPCHFile PCHFile, std::vector<char> PreambleBytes,
bool PreambleEndsAtStartOfLine,
llvm::StringMap<PreambleFileHash> FilesInPreamble)
: PCHFile(std::move(PCHFile)), FilesInPreamble(FilesInPreamble),
PreambleBytes(std::move(PreambleBytes)),
PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile() {
// FIXME: This is a hack so that we can override the preamble file during
// crash-recovery testing, which is the only case where the preamble files
// are not necessarily cleaned up.
const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE");
if (TmpFile)
return TempPCHFile::createFromCustomPath(TmpFile);
return TempPCHFile::createInSystemTempDir("preamble", "pch");
}
llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
PrecompiledPreamble::TempPCHFile::createInSystemTempDir(const Twine &Prefix,
StringRef Suffix) {
llvm::SmallString<64> File;
auto EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, /*ref*/ File);
if (EC)
return EC;
return TempPCHFile(std::move(File).str());
}
llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
PrecompiledPreamble::TempPCHFile::createFromCustomPath(const Twine &Path) {
return TempPCHFile(Path.str());
}
PrecompiledPreamble::TempPCHFile::TempPCHFile(std::string FilePath)
: FilePath(std::move(FilePath)) {
TemporaryFiles::getInstance().addFile(*this->FilePath);
}
PrecompiledPreamble::TempPCHFile::TempPCHFile(TempPCHFile &&Other) {
FilePath = std::move(Other.FilePath);
Other.FilePath = None;
}
PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::TempPCHFile::
operator=(TempPCHFile &&Other) {
RemoveFileIfPresent();
FilePath = std::move(Other.FilePath);
Other.FilePath = None;
return *this;
}
PrecompiledPreamble::TempPCHFile::~TempPCHFile() { RemoveFileIfPresent(); }
void PrecompiledPreamble::TempPCHFile::RemoveFileIfPresent() {
if (FilePath) {
TemporaryFiles::getInstance().removeFile(*FilePath);
FilePath = None;
}
}
llvm::StringRef PrecompiledPreamble::TempPCHFile::getFilePath() const {
assert(FilePath && "TempPCHFile doesn't have a FilePath. Had it been moved?");
return *FilePath;
}
PrecompiledPreamble::PreambleFileHash
PrecompiledPreamble::PreambleFileHash::createForFile(off_t Size,
time_t ModTime) {
PreambleFileHash Result;
Result.Size = Size;
Result.ModTime = ModTime;
Result.MD5 = {};
return Result;
}
PrecompiledPreamble::PreambleFileHash
PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(
const llvm::MemoryBuffer *Buffer) {
PreambleFileHash Result;
Result.Size = Buffer->getBufferSize();
Result.ModTime = 0;
llvm::MD5 MD5Ctx;
MD5Ctx.update(Buffer->getBuffer().data());
MD5Ctx.final(Result.MD5);
return Result;
}
void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {}
void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {}
void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {}
void PreambleCallbacks::HandleMacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) {}
std::error_code clang::make_error_code(BuildPreambleError Error) {
return std::error_code(static_cast<int>(Error), BuildPreambleErrorCategory());
}
const char *BuildPreambleErrorCategory::name() const noexcept {
return "build-preamble.error";
}
std::string BuildPreambleErrorCategory::message(int condition) const {
switch (static_cast<BuildPreambleError>(condition)) {
case BuildPreambleError::PreambleIsEmpty:
return "Preamble is empty";
case BuildPreambleError::CouldntCreateTempFile:
return "Could not create temporary file for PCH";
case BuildPreambleError::CouldntCreateTargetInfo:
return "CreateTargetInfo() return null";
case BuildPreambleError::CouldntCreateVFSOverlay:
return "Could not create VFS Overlay";
case BuildPreambleError::BeginSourceFileFailed:
return "BeginSourceFile() return an error";
case BuildPreambleError::CouldntEmitPCH:
return "Could not emit PCH";
}
llvm_unreachable("unexpected BuildPreambleError");
}

View File

@ -349,7 +349,7 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
case tok::pp_include_next:
startNewLineIfNeeded();
MoveToLine(HashLoc);
OS << "#pragma clang module import " << Imported->getFullModuleName()
OS << "#pragma clang module import " << Imported->getFullModuleName(true)
<< " /* clang -E: implicit import for "
<< "#" << PP.getSpelling(IncludeTok) << " "
<< (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
@ -378,14 +378,14 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
/// Handle entering the scope of a module during a module compilation.
void PrintPPOutputPPCallbacks::BeginModule(const Module *M) {
startNewLineIfNeeded();
OS << "#pragma clang module begin " << M->getFullModuleName();
OS << "#pragma clang module begin " << M->getFullModuleName(true);
setEmittedDirectiveOnThisLine();
}
/// Handle leaving the scope of a module during a module compilation.
void PrintPPOutputPPCallbacks::EndModule(const Module *M) {
startNewLineIfNeeded();
OS << "#pragma clang module end /*" << M->getFullModuleName() << "*/";
OS << "#pragma clang module end /*" << M->getFullModuleName(true) << "*/";
setEmittedDirectiveOnThisLine();
}

View File

@ -9,6 +9,7 @@
#include "clang/Rewrite/Frontend/FrontendActions.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
@ -224,7 +225,15 @@ class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener {
auto OS = Out.lock();
assert(OS && "loaded module file after finishing rewrite action?");
(*OS) << "#pragma clang module build " << MF->ModuleName << "\n";
(*OS) << "#pragma clang module build ";
if (isValidIdentifier(MF->ModuleName))
(*OS) << MF->ModuleName;
else {
(*OS) << '"';
OS->write_escaped(MF->ModuleName);
(*OS) << '"';
}
(*OS) << '\n';
// Rewrite the contents of the module in a separate compiler instance.
CompilerInstance Instance(CI.getPCHContainerOperations(),
@ -234,9 +243,12 @@ class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener {
Instance.createDiagnostics(
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
/*ShouldOwnClient=*/true);
Instance.getFrontendOpts().DisableFree = false;
Instance.getFrontendOpts().Inputs.clear();
Instance.getFrontendOpts().Inputs.emplace_back(
Filename, InputKind(InputKind::Unknown, InputKind::Precompiled));
Instance.getFrontendOpts().ModuleFiles.clear();
Instance.getFrontendOpts().ModuleMapFiles.clear();
// Don't recursively rewrite imports. We handle them all at the top level.
Instance.getPreprocessorOutputOpts().RewriteImports = false;

View File

@ -140,7 +140,7 @@ void InclusionRewriter::WriteLineInfo(StringRef Filename, int Line,
}
void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod) {
OS << "#pragma clang module import " << Mod->getFullModuleName()
OS << "#pragma clang module import " << Mod->getFullModuleName(true)
<< " /* clang -frewrite-includes: implicit import */" << MainEOL;
}
@ -471,15 +471,15 @@ void InclusionRewriter::Process(FileID FileId,
else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) {
const Module *Mod = FindEnteredModule(Loc);
if (Mod)
OS << "#pragma clang module begin " << Mod->getFullModuleName()
<< "\n";
OS << "#pragma clang module begin "
<< Mod->getFullModuleName(true) << "\n";
// Include and recursively process the file.
Process(Inc->Id, Inc->FileType);
if (Mod)
OS << "#pragma clang module end /*" << Mod->getFullModuleName()
<< "*/\n";
OS << "#pragma clang module end /*"
<< Mod->getFullModuleName(true) << "*/\n";
// Add line marker to indicate we're returning from an included
// file.

View File

@ -351,9 +351,11 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
IndexCtx.indexTagDecl(D, Relations);
} else {
auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
SmallVector<SymbolRelation, 1> Relations;
gatherTemplatePseudoOverrides(D, Relations);
return IndexCtx.handleReference(D, D->getLocation(), Parent,
D->getLexicalDeclContext(),
SymbolRoleSet());
SymbolRoleSet(), Relations);
}
}
return true;
@ -609,18 +611,16 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
ClassTemplateSpecializationDecl *D) {
// FIXME: Notify subsequent callbacks if info comes from implicit
// instantiation.
if (D->isThisDeclarationADefinition()) {
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
Template = D->getSpecializedTemplateOrPartial();
const Decl *SpecializationOf =
Template.is<ClassTemplateDecl *>()
? (Decl *)Template.get<ClassTemplateDecl *>()
: Template.get<ClassTemplatePartialSpecializationDecl *>();
IndexCtx.indexTagDecl(
D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
SpecializationOf));
}
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
Template = D->getSpecializedTemplateOrPartial();
const Decl *SpecializationOf =
Template.is<ClassTemplateDecl *>()
? (Decl *)Template.get<ClassTemplateDecl *>()
: Template.get<ClassTemplatePartialSpecializationDecl *>();
IndexCtx.indexTagDecl(
D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
SpecializationOf));
if (TypeSourceInfo *TSI = D->getTypeAsWritten())
IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
D->getLexicalDeclContext());

View File

@ -19,6 +19,7 @@
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
@ -2750,7 +2751,7 @@ static const char *findPlaceholderEnd(const char *CurPtr,
bool Lexer::lexEditorPlaceholder(Token &Result, const char *CurPtr) {
assert(CurPtr[-1] == '<' && CurPtr[0] == '#' && "Not a placeholder!");
if (!PP || LexingRawMode)
if (!PP || !PP->getPreprocessorOpts().LexEditorPlaceholders || LexingRawMode)
return false;
const char *End = findPlaceholderEnd(CurPtr + 1, BufferEnd);
if (!End)

View File

@ -538,7 +538,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
CurPPLexer->LexingRawMode = false;
IdentifierInfo *IfNDefMacro = nullptr;
const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro);
const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro).Conditional;
CurPPLexer->LexingRawMode = true;
if (Callbacks) {
const SourceLocation CondEnd = CurPPLexer->getSourceLocation();
@ -635,7 +635,7 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() {
// Evaluate the condition of the #elif.
IdentifierInfo *IfNDefMacro = nullptr;
CurPTHLexer->ParsingPreprocessorDirective = true;
bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro);
bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro).Conditional;
CurPTHLexer->ParsingPreprocessorDirective = false;
// If this condition is true, enter it!
@ -2654,7 +2654,13 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
}
// Should we include the stuff contained by this directive?
if (!MI == isIfndef) {
if (PPOpts->SingleFileParseMode && !MI) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
/*wasskip*/false, /*foundnonskip*/false,
/*foundelse*/false);
} else if (!MI == isIfndef) {
// Yes, remember that we are inside a conditional, then lex the next token.
CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
/*wasskip*/false, /*foundnonskip*/true,
@ -2676,7 +2682,8 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
// Parse and evaluate the conditional expression.
IdentifierInfo *IfNDefMacro = nullptr;
const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
const bool ConditionalTrue = EvaluateDirectiveExpression(IfNDefMacro);
const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
const bool ConditionalTrue = DER.Conditional;
const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
// If this condition is equivalent to #ifndef X, and if this is the first
@ -2695,7 +2702,12 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
(ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False));
// Should we include the stuff contained by this directive?
if (ConditionalTrue) {
if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false,
/*foundnonskip*/false, /*foundelse*/false);
} else if (ConditionalTrue) {
// Yes, remember that we are inside a conditional, then lex the next token.
CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false,
/*foundnonskip*/true, /*foundelse*/false);
@ -2756,6 +2768,14 @@ void Preprocessor::HandleElseDirective(Token &Result) {
if (Callbacks)
Callbacks->Else(Result.getLocation(), CI.IfLoc);
if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(CI.IfLoc, /*wasskip*/false,
/*foundnonskip*/false, /*foundelse*/true);
return;
}
// Finally, skip the rest of the contents of this block.
SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true,
/*FoundElse*/true, Result.getLocation());
@ -2791,6 +2811,14 @@ void Preprocessor::HandleElifDirective(Token &ElifToken) {
SourceRange(ConditionalBegin, ConditionalEnd),
PPCallbacks::CVK_NotEvaluated, CI.IfLoc);
if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(ElifToken.getLocation(), /*wasskip*/false,
/*foundnonskip*/false, /*foundelse*/false);
return;
}
// Finally, skip the rest of the contents of this block.
SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true,
/*FoundElse*/CI.FoundElse,

View File

@ -73,6 +73,7 @@ class PPValue {
static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
Token &PeekTok, bool ValueLive,
bool &IncludedUndefinedIds,
Preprocessor &PP);
/// DefinedTracker - This struct is used while parsing expressions to keep track
@ -93,6 +94,7 @@ struct DefinedTracker {
/// TheMacro - When the state is DefinedMacro or NotDefinedMacro, this
/// indicates the macro that was checked.
IdentifierInfo *TheMacro;
bool IncludedUndefinedIds = false;
};
/// EvaluateDefined - Process a 'defined(sym)' expression.
@ -128,6 +130,7 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
MacroDefinition Macro = PP.getMacroDefinition(II);
Result.Val = !!Macro;
Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
DT.IncludedUndefinedIds = !Macro;
// If there is a macro, mark it used.
if (Result.Val != 0 && ValueLive)
@ -255,6 +258,8 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
Result.setIdentifier(II);
Result.setRange(PeekTok.getLocation());
DT.IncludedUndefinedIds = (II->getTokenID() != tok::kw_true &&
II->getTokenID() != tok::kw_false);
PP.LexNonComment(PeekTok);
return false;
}
@ -400,7 +405,8 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// Just use DT unmodified as our result.
} else {
// Otherwise, we have something like (x+y), and we consumed '(x'.
if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive, PP))
if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive,
DT.IncludedUndefinedIds, PP))
return true;
if (PeekTok.isNot(tok::r_paren)) {
@ -532,6 +538,7 @@ static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS,
/// evaluation, such as division by zero warnings.
static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
Token &PeekTok, bool ValueLive,
bool &IncludedUndefinedIds,
Preprocessor &PP) {
unsigned PeekPrec = getPrecedence(PeekTok.getKind());
// If this token isn't valid, report the error.
@ -571,6 +578,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
// Parse the RHS of the operator.
DefinedTracker DT;
if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true;
IncludedUndefinedIds = DT.IncludedUndefinedIds;
// Remember the precedence of this operator and get the precedence of the
// operator immediately to the right of the RHS.
@ -601,7 +609,8 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
RHSPrec = ThisPrec+1;
if (PeekPrec >= RHSPrec) {
if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive, PP))
if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive,
IncludedUndefinedIds, PP))
return true;
PeekPrec = getPrecedence(PeekTok.getKind());
}
@ -769,7 +778,8 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
// Parse anything after the : with the same precedence as ?. We allow
// things of equal precedence because ?: is right associative.
if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec,
PeekTok, AfterColonLive, PP))
PeekTok, AfterColonLive,
IncludedUndefinedIds, PP))
return true;
// Now that we have the condition, the LHS and the RHS of the :, evaluate.
@ -806,7 +816,8 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
/// may occur after a #if or #elif directive. If the expression is equivalent
/// to "!defined(X)" return X in IfNDefMacro.
bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
Preprocessor::DirectiveEvalResult
Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
SaveAndRestore<bool> PPDir(ParsingIfOrElifDirective, true);
// Save the current state of 'DisableMacroExpansion' and reset it to false. If
// 'DisableMacroExpansion' is true, then we must be in a macro argument list
@ -833,7 +844,7 @@ bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// Restore 'DisableMacroExpansion'.
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return false;
return {false, DT.IncludedUndefinedIds};
}
// If we are at the end of the expression after just parsing a value, there
@ -847,20 +858,20 @@ bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// Restore 'DisableMacroExpansion'.
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return ResVal.Val != 0;
return {ResVal.Val != 0, DT.IncludedUndefinedIds};
}
// Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
// operator and the stuff after it.
if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question),
Tok, true, *this)) {
Tok, true, DT.IncludedUndefinedIds, *this)) {
// Parse error, skip the rest of the macro line.
if (Tok.isNot(tok::eod))
DiscardUntilEndOfDirective();
// Restore 'DisableMacroExpansion'.
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return false;
return {false, DT.IncludedUndefinedIds};
}
// If we aren't at the tok::eod token, something bad happened, like an extra
@ -872,5 +883,5 @@ bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// Restore 'DisableMacroExpansion'.
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return ResVal.Val != 0;
return {ResVal.Val != 0, DT.IncludedUndefinedIds};
}

View File

@ -20,6 +20,7 @@
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
@ -754,15 +755,52 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName);
}
// Lex a component of a module name: either an identifier or a string literal;
// for components that can be expressed both ways, the two forms are equivalent.
static bool LexModuleNameComponent(
Preprocessor &PP, Token &Tok,
std::pair<IdentifierInfo *, SourceLocation> &ModuleNameComponent,
bool First) {
PP.LexUnexpandedToken(Tok);
if (Tok.is(tok::string_literal) && !Tok.hasUDSuffix()) {
StringLiteralParser Literal(Tok, PP);
if (Literal.hadError)
return true;
ModuleNameComponent = std::make_pair(
PP.getIdentifierInfo(Literal.GetString()), Tok.getLocation());
} else if (!Tok.isAnnotation() && Tok.getIdentifierInfo()) {
ModuleNameComponent =
std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation());
} else {
PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << First;
return true;
}
return false;
}
static bool LexModuleName(
Preprocessor &PP, Token &Tok,
llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>>
&ModuleName) {
while (true) {
std::pair<IdentifierInfo*, SourceLocation> NameComponent;
if (LexModuleNameComponent(PP, Tok, NameComponent, ModuleName.empty()))
return true;
ModuleName.push_back(NameComponent);
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::period))
return false;
}
}
void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
SourceLocation Loc = Tok.getLocation();
LexUnexpandedToken(Tok);
if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) {
Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << true;
std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc;
if (LexModuleNameComponent(*this, Tok, ModuleNameLoc, true))
return;
}
IdentifierInfo *ModuleName = Tok.getIdentifierInfo();
IdentifierInfo *ModuleName = ModuleNameLoc.first;
LexUnexpandedToken(Tok);
if (Tok.isNot(tok::eod)) {
@ -1383,26 +1421,6 @@ struct PragmaMessageHandler : public PragmaHandler {
}
};
static bool LexModuleName(
Preprocessor &PP, Token &Tok,
llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>>
&ModuleName) {
while (true) {
PP.LexUnexpandedToken(Tok);
if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) {
PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name)
<< ModuleName.empty();
return true;
}
ModuleName.emplace_back(Tok.getIdentifierInfo(), Tok.getLocation());
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::period))
return false;
}
}
/// Handle the clang \#pragma module import extension. The syntax is:
/// \code
/// #pragma clang module import some.module.name
@ -1473,7 +1491,7 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
// be loaded or implicitly loadable.
// FIXME: We could create the submodule here. We'd need to know whether
// it's supposed to be explicit, but not much else.
Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(Current);
Module *M = PP.getHeaderSearchInfo().lookupModule(Current);
if (!M) {
PP.Diag(ModuleName.front().second,
diag::err_pp_module_begin_no_module_map) << Current;

View File

@ -2629,6 +2629,8 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
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)
@ -4261,7 +4263,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
AS, DS.getModulePrivateSpecLoc(), TParams,
Owned, IsDependent, ScopedEnumKWLoc,
IsScopedUsingClassTag, BaseType,
DSC == DSC_type_specifier, &SkipBody);
DSC == DSC_type_specifier,
DSC == DSC_template_param ||
DSC == DSC_template_type_arg, &SkipBody);
if (SkipBody.ShouldSkip) {
assert(TUK == Sema::TUK_Definition && "can only skip a definition");

View File

@ -1887,7 +1887,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
SourceLocation(), false,
clang::TypeResult(),
DSC == DSC_type_specifier,
&SkipBody);
DSC == DSC_template_param ||
DSC == DSC_template_type_arg, &SkipBody);
// If ActOnTag said the type was dependent, try again with the
// less common call.

View File

@ -3627,6 +3627,14 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
SourceLocation OrigLoc = Tok.getLocation();
assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!");
// Store an artificial EOF token to ensure that we don't run off the end of
// the method's body when we come to parse it.
Token Eof;
Eof.startToken();
Eof.setKind(tok::eof);
Eof.setEofData(MCDecl);
Eof.setLocation(OrigLoc);
LM.Toks.push_back(Eof);
// Append the current token at the end of the new token stream so that it
// doesn't get lost.
LM.Toks.push_back(Tok);
@ -3658,7 +3666,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
Actions.ActOnDefaultCtorInitializers(MCDecl);
ParseFunctionStatementBody(MCDecl, BodyScope);
}
if (Tok.getLocation() != OrigLoc) {
// Due to parsing error, we either went over the cached tokens or
// there are still cached tokens left. If it's the latter case skip the
@ -3670,4 +3678,6 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
ConsumeAnyToken();
}
// Clean up the remaining EOF token.
ConsumeAnyToken();
}

View File

@ -674,7 +674,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// FIXME: The type should probably be restricted in some way... Not all
// declarators (parts of declarators?) are accepted for parameters.
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS);
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
DSC_template_param);
// Parse this as a typename.
Declarator ParamDecl(DS, Declarator::TemplateParamContext);

View File

@ -278,6 +278,150 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
}
//===----------------------------------------------------------------------===//
// Check for throw in a non-throwing function.
//===----------------------------------------------------------------------===//
enum ThrowState {
FoundNoPathForThrow,
FoundPathForThrow,
FoundPathWithNoThrowOutFunction,
};
static bool isThrowCaught(const CXXThrowExpr *Throw,
const CXXCatchStmt *Catch) {
const Type *ThrowType = nullptr;
if (Throw->getSubExpr())
ThrowType = Throw->getSubExpr()->getType().getTypePtrOrNull();
if (!ThrowType)
return false;
const Type *CaughtType = Catch->getCaughtType().getTypePtrOrNull();
if (!CaughtType)
return true;
if (ThrowType->isReferenceType())
ThrowType = ThrowType->castAs<ReferenceType>()
->getPointeeType()
->getUnqualifiedDesugaredType();
if (CaughtType->isReferenceType())
CaughtType = CaughtType->castAs<ReferenceType>()
->getPointeeType()
->getUnqualifiedDesugaredType();
if (CaughtType == ThrowType)
return true;
const CXXRecordDecl *CaughtAsRecordType =
CaughtType->getPointeeCXXRecordDecl();
const CXXRecordDecl *ThrowTypeAsRecordType = ThrowType->getAsCXXRecordDecl();
if (CaughtAsRecordType && ThrowTypeAsRecordType)
return ThrowTypeAsRecordType->isDerivedFrom(CaughtAsRecordType);
return false;
}
static bool isThrowCaughtByHandlers(const CXXThrowExpr *CE,
const CXXTryStmt *TryStmt) {
for (unsigned H = 0, E = TryStmt->getNumHandlers(); H < E; ++H) {
if (isThrowCaught(CE, TryStmt->getHandler(H)))
return true;
}
return false;
}
static bool doesThrowEscapePath(CFGBlock Block, SourceLocation &OpLoc) {
for (const auto &B : Block) {
if (B.getKind() != CFGElement::Statement)
continue;
const auto *CE = dyn_cast<CXXThrowExpr>(B.getAs<CFGStmt>()->getStmt());
if (!CE)
continue;
OpLoc = CE->getThrowLoc();
for (const auto &I : Block.succs()) {
if (!I.isReachable())
continue;
if (const auto *Terminator =
dyn_cast_or_null<CXXTryStmt>(I->getTerminator()))
if (isThrowCaughtByHandlers(CE, Terminator))
return false;
}
return true;
}
return false;
}
static bool hasThrowOutNonThrowingFunc(SourceLocation &OpLoc, CFG *BodyCFG) {
unsigned ExitID = BodyCFG->getExit().getBlockID();
SmallVector<ThrowState, 16> States(BodyCFG->getNumBlockIDs(),
FoundNoPathForThrow);
States[BodyCFG->getEntry().getBlockID()] = FoundPathWithNoThrowOutFunction;
SmallVector<CFGBlock *, 16> Stack;
Stack.push_back(&BodyCFG->getEntry());
while (!Stack.empty()) {
CFGBlock *CurBlock = Stack.back();
Stack.pop_back();
unsigned ID = CurBlock->getBlockID();
ThrowState CurState = States[ID];
if (CurState == FoundPathWithNoThrowOutFunction) {
if (ExitID == ID)
continue;
if (doesThrowEscapePath(*CurBlock, OpLoc))
CurState = FoundPathForThrow;
}
// Loop over successor blocks and add them to the Stack if their state
// changes.
for (const auto &I : CurBlock->succs())
if (I.isReachable()) {
unsigned NextID = I->getBlockID();
if (NextID == ExitID && CurState == FoundPathForThrow) {
States[NextID] = CurState;
} else if (States[NextID] < CurState) {
States[NextID] = CurState;
Stack.push_back(I);
}
}
}
// Return true if the exit node is reachable, and only reachable through
// a throw expression.
return States[ExitID] == FoundPathForThrow;
}
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc,
const FunctionDecl *FD) {
if (!S.getSourceManager().isInSystemHeader(OpLoc)) {
S.Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
if (S.getLangOpts().CPlusPlus11 &&
(isa<CXXDestructorDecl>(FD) ||
FD->getDeclName().getCXXOverloadedOperator() == OO_Delete ||
FD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete))
S.Diag(FD->getLocation(), diag::note_throw_in_dtor);
else
S.Diag(FD->getLocation(), diag::note_throw_in_function);
}
}
static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD,
AnalysisDeclContext &AC) {
CFG *BodyCFG = AC.getCFG();
if (!BodyCFG)
return;
if (BodyCFG->getExit().pred_empty())
return;
SourceLocation OpLoc;
if (hasThrowOutNonThrowingFunc(OpLoc, BodyCFG))
EmitDiagForCXXThrowInNonThrowingFunc(S, OpLoc, FD);
}
static bool isNoexcept(const FunctionDecl *FD) {
const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
if (FPT->getExceptionSpecType() != EST_None &&
FPT->isNothrow(FD->getASTContext()))
return true;
return false;
}
//===----------------------------------------------------------------------===//
// Check for missing return value.
//===----------------------------------------------------------------------===//
@ -2127,6 +2271,12 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
}
}
// Check for throw out of non-throwing function.
if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getLocStart()))
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
if (S.getLangOpts().CPlusPlus && isNoexcept(FD))
checkThrowInNonThrowingFunc(S, FD, AC);
// If none of the previous checks caused a CFG build, trigger one here
// for -Wtautological-overlap-compare
if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison,

View File

@ -740,6 +740,9 @@ void Sema::ActOnEndOfTranslationUnit() {
// Load pending instantiations from the external source.
SmallVector<PendingImplicitInstantiation, 4> Pending;
ExternalSource->ReadPendingInstantiations(Pending);
for (auto PII : Pending)
if (auto Func = dyn_cast<FunctionDecl>(PII.first))
Func->setInstantiationIsPending(true);
PendingInstantiations.insert(PendingInstantiations.begin(),
Pending.begin(), Pending.end());
}

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