Import Clang, at r72770.
This commit is contained in:
parent
ec2b103c26
commit
922a209773
@ -63,9 +63,250 @@ with the <b><tt>-include-pch</tt></b> option:</p>
|
||||
PCH file generation serializes the build when all compilations
|
||||
require the PCH file to be up-to-date.</li>
|
||||
</ul>
|
||||
|
||||
<p>Clang's precompiled headers are designed with a compact on-disk
|
||||
representation, which minimizes both PCH creation time and the time
|
||||
required to initially load the PCH file. The PCH file itself contains
|
||||
a serialized representation of Clang's abstract syntax trees and
|
||||
supporting data structures, stored using the same compressed bitstream
|
||||
as <a href="http://llvm.org/docs/BitCodeFormat.html">LLVM's bitcode
|
||||
file format</a>.</p>
|
||||
|
||||
<p>Clang's precompiled headers are loaded "lazily" from disk. When a
|
||||
PCH file is initially loaded, Clang reads only a small amount of data
|
||||
from the PCH file to establish where certain important data structures
|
||||
are stored. The amount of data read in this initial load is
|
||||
independent of the size of the PCH file, such that a larger PCH file
|
||||
does not lead to longer PCH load times. The actual header data in the
|
||||
PCH file--macros, functions, variables, types, etc.--is loaded only
|
||||
when it is referenced from the user's code, at which point only that
|
||||
entity (and those entities it depends on) are deserialized from the
|
||||
PCH file. With this approach, the cost of using a precompiled header
|
||||
for a translation unit is proportional to the amount of code actually
|
||||
used from the header, rather than being proportional to the size of
|
||||
the header itself.</p> </body>
|
||||
|
||||
<h2>Precompiled Header Contents</h2>
|
||||
|
||||
<img src="PCHLayout.png" align="right" alt="Precompiled header layout">
|
||||
|
||||
<p>Clang's precompiled headers are organized into several different
|
||||
blocks, each of which contains the serialized representation of a part
|
||||
of Clang's internal representation. Each of the blocks corresponds to
|
||||
either a block or a record within <a
|
||||
href="http://llvm.org/docs/BitCodeFormat.html">LLVM's bitstream
|
||||
format</a>. The contents of each of these logical blocks are described
|
||||
below.</p>
|
||||
|
||||
<h3 name="metadata">Metadata Block</h3>
|
||||
|
||||
<p>The metadata block contains several records that provide
|
||||
information about how the precompiled header was built. This metadata
|
||||
is primarily used to validate the use of a precompiled header. For
|
||||
example, a precompiled header built for x86 (32-bit) cannot be used
|
||||
when compiling for x86-64 (64-bit). The metadata block contains
|
||||
information about:</p>
|
||||
|
||||
<dl>
|
||||
<dt>Language options</dt>
|
||||
<dd>Describes the particular language dialect used to compile the
|
||||
PCH file, including major options (e.g., Objective-C support) and more
|
||||
minor options (e.g., support for "//" comments). The contents of this
|
||||
record correspond to the <code>LangOptions</code> class.</dd>
|
||||
|
||||
<p>More to be written...</p>
|
||||
<dt>Target architecture</dt>
|
||||
<dd>The target triple that describes the architecture, platform, and
|
||||
ABI for which the PCH file was generated, e.g.,
|
||||
<code>i386-apple-darwin9</code>.</dd>
|
||||
|
||||
<dt>PCH version</dt>
|
||||
<dd>The major and minor version numbers of the precompiled header
|
||||
format. Changes in the minor version number should not affect backward
|
||||
compatibility, while changes in the major version number imply that a
|
||||
newer compiler cannot read an older precompiled header (and
|
||||
vice-versa).</dd>
|
||||
|
||||
<dt>Original file name</dt>
|
||||
<dd>The full path of the header that was used to generate the
|
||||
precompiled header.</dd> </dl>
|
||||
|
||||
<dt>Predefines buffer</dt>
|
||||
<dd>Although not explicitly stored as part of the metadata, the
|
||||
predefines buffer is used in the validation of the precompiled header.
|
||||
The predefines buffer itself contains code generated by the compiler
|
||||
to initialize the preprocessor state according to the current target,
|
||||
platform, and command-line options. For example, the predefines buffer
|
||||
will contain "<code>#define __STDC__ 1</code>" when we are compiling C
|
||||
without Microsoft extensions. The predefines buffer itself is stored
|
||||
within the <a href="#sourcemgr">source manager block</a>, but its
|
||||
contents are verified along with the rest of the metadata.</dd> </dl>
|
||||
|
||||
<h3 name="sourcemgr">Source Manager Block</h3>
|
||||
|
||||
<p>The source manager block contains the serialized representation of
|
||||
Clang's <a
|
||||
href="InternalsManual.html#SourceLocation">SourceManager</a> class,
|
||||
which handles the mapping from source locations (as represented in
|
||||
Clang's abstract syntax tree) into actual column/line positions within
|
||||
a source file or macro instantiation. The precompiled header's
|
||||
representation of the source manager also includes information about
|
||||
all of the headers that were (transitively) included when building the
|
||||
precompiled header.</p>
|
||||
|
||||
<p>The bulk of the source manager block is dedicated to information
|
||||
about the various files, buffers, and macro instantiations into which
|
||||
a source location can refer. Each of these is referenced by a numeric
|
||||
"file ID", which is a unique number (allocated starting at 1) stored
|
||||
in the source location. Clang serializes the information for each kind
|
||||
of file ID, along with an index that maps file IDs to the position
|
||||
within the PCH file where the information about that file ID is
|
||||
stored. The data associated with a file ID is loaded only when
|
||||
required by the front end, e.g., to emit a diagnostic that includes a
|
||||
macro instantiation history inside the header itself.</p>
|
||||
|
||||
<p>The source manager block also contains information about all of the
|
||||
headers that were included when building the precompiled header. This
|
||||
includes information about the controlling macro for the header (e.g.,
|
||||
when the preprocessor identified that the contents of the header
|
||||
dependent on a macro like <code>LLVM_CLANG_SOURCEMANAGER_H</code>)
|
||||
along with a cached version of the results of the <code>stat()</code>
|
||||
system calls performed when building the precompiled header. The
|
||||
latter is particularly useful in reducing system time when searching
|
||||
for include files.</p>
|
||||
|
||||
<h3 name="preprocessor">Preprocessor Block</h3>
|
||||
|
||||
<p>The preprocessor block contains the serialized representation of
|
||||
the preprocessor. Specifically, it contains all of the macros that
|
||||
have been defined by the end of the header used to build the
|
||||
precompiled header, along with the token sequences that comprise each
|
||||
macro. The macro definitions are only read from the PCH file when the
|
||||
name of the macro first occurs in the program. This lazy loading of
|
||||
macro definitions is trigged by lookups into the <a
|
||||
href="#idtable">identifier table</a>.</p>
|
||||
|
||||
<h3 name="types">Types Block</h3>
|
||||
|
||||
<p>The types block contains the serialized representation of all of
|
||||
the types referenced in the translation unit. Each Clang type node
|
||||
(<code>PointerType</code>, <code>FunctionProtoType</code>, etc.) has a
|
||||
corresponding record type in the PCH file. When types are deserialized
|
||||
from the precompiled header, the data within the record is used to
|
||||
reconstruct the appropriate type node using the AST context.</p>
|
||||
|
||||
<p>Each type has a unique type ID, which is an integer that uniquely
|
||||
identifies that type. Type ID 0 represents the NULL type, type IDs
|
||||
less than <code>NUM_PREDEF_TYPE_IDS</code> represent predefined types
|
||||
(<code>void</code>, <code>float</code>, etc.), while other
|
||||
"user-defined" type IDs are assigned consecutively from
|
||||
<code>NUM_PREDEF_TYPE_IDS</code> upward as the types are encountered.
|
||||
The PCH file has an associated mapping from the user-defined types
|
||||
block to the location within the types block where the serialized
|
||||
representation of that type resides, enabling lazy deserialization of
|
||||
types. When a type is referenced from within the PCH file, that
|
||||
reference is encoded using the type ID shifted left by 3 bits. The
|
||||
lower three bits are used to represent the <code>const</code>,
|
||||
<code>volatile</code>, and <code>restrict</code> qualifiers, as in
|
||||
Clang's <a
|
||||
href="http://clang.llvm.org/docs/InternalsManual.html#Type">QualType</a>
|
||||
class.</p>
|
||||
|
||||
<h3 name="decls">Declarations Block</h3>
|
||||
|
||||
<p>The declarations block contains the serialized representation of
|
||||
all of the declarations referenced in the translation unit. Each Clang
|
||||
declaration node (<code>VarDecl</code>, <code>FunctionDecl</code>,
|
||||
etc.) has a corresponding record type in the PCH file. When
|
||||
declarations are deserialized from the precompiled header, the data
|
||||
within the record is used to build and populate a new instance of the
|
||||
corresponding <code>Decl</code> node. As with types, each declaration
|
||||
node has a numeric ID that is used to refer to that declaration within
|
||||
the PCH file. In addition, a lookup table provides a mapping from that
|
||||
numeric ID to the offset within the precompiled header where that
|
||||
declaration is described.</p>
|
||||
|
||||
<p>Declarations in Clang's abstract syntax trees are stored
|
||||
hierarchically. At the top of the hierarchy is the translation unit
|
||||
(<code>TranslationUnitDecl</code>), which contains all of the
|
||||
declarations in the translation unit. These declarations---such as
|
||||
functions or struct types---may also contain other declarations inside
|
||||
them, and so on. Within Clang, each declaration is stored within a <a
|
||||
href="http://clang.llvm.org/docs/InternalsManual.html#DeclContext">declaration
|
||||
context</a>, as represented by the <code>DeclContext</code> class.
|
||||
Declaration contexts provide the mechanism to perform name lookup
|
||||
within a given declaration (e.g., find the member named <code>x</code>
|
||||
in a structure) and iterate over the declarations stored within a
|
||||
context (e.g., iterate over all of the fields of a structure for
|
||||
structure layout).</p>
|
||||
|
||||
<p>In Clang's precompiled header format, deserializing a declaration
|
||||
that is a <code>DeclContext</code> is a separate operation from
|
||||
deserializing all of the declarations stored within that declaration
|
||||
context. Therefore, Clang will deserialize the translation unit
|
||||
declaration without deserializing the declarations within that
|
||||
translation unit. When required, the declarations stored within a
|
||||
declaration context will be serialized. There are two representations
|
||||
of the declarations within a declaration context, which correspond to
|
||||
the name-lookup and iteration behavior described above:</p>
|
||||
|
||||
<ul>
|
||||
<li>When the front end performs name lookup to find a name
|
||||
<code>x</code> within a given declaration context (for example,
|
||||
during semantic analysis of the expression <code>p->x</code>,
|
||||
where <code>p</code>'s type is defined in the precompiled header),
|
||||
Clang deserializes a hash table mapping from the names within that
|
||||
declaration context to the declaration IDs that represent each
|
||||
visible declaration with that name. The entire hash table is
|
||||
deserialized at this point (into the <code>llvm::DenseMap</code>
|
||||
stored within each <code>DeclContext</code> object), but the actual
|
||||
declarations are not yet deserialized. In a second step, those
|
||||
declarations with the name <code>x</code> will be deserialized and
|
||||
will be used as the result of name lookup.</li>
|
||||
|
||||
<li>When the front end performs iteration over all of the
|
||||
declarations within a declaration context, all of those declarations
|
||||
are immediately de-serialized. For large declaration contexts (e.g.,
|
||||
the translation unit), this operation is expensive; however, large
|
||||
declaration contexts are not traversed in normal compilation, since
|
||||
such a traversal is unnecessary. However, it is common for the code
|
||||
generator and semantic analysis to traverse declaration contexts for
|
||||
structs, classes, unions, and enumerations, although those contexts
|
||||
contain relatively few declarations in the common case.</li>
|
||||
</ul>
|
||||
|
||||
<h3 name="idtable">Identifier Table Block</h3>
|
||||
|
||||
<p>The identifier table block contains an on-disk hash table that maps
|
||||
each identifier mentioned within the precompiled header to the
|
||||
serialized representation of the identifier's information (e.g, the
|
||||
<code>IdentifierInfo</code> structure). The serialized representation
|
||||
contains:</p>
|
||||
|
||||
<ul>
|
||||
<li>The actual identifier string.</li>
|
||||
<li>Flags that describe whether this identifier is the name of a
|
||||
built-in, a poisoned identifier, an extension token, or a
|
||||
macro.</li>
|
||||
<li>If the identifier names a macro, the offset of the macro
|
||||
definition within the <a href="#preprocessor">preprocessor
|
||||
block</a>.</li>
|
||||
<li>If the identifier names one or more declarations visible from
|
||||
translation unit scope, the <a href="#decls">declaration IDs</a> of these
|
||||
declarations.</li>
|
||||
</ul>
|
||||
|
||||
<p>When a precompiled header is loaded, the precompiled header
|
||||
mechanism introduces itself into the identifier table as an external
|
||||
lookup source. Thus, when the user program refers to an identifier
|
||||
that has not yet been seen, Clang will perform a lookup into the
|
||||
on-disk hash table ... FINISH THIS!
|
||||
|
||||
<p>A separate table provides a mapping from the numeric representation
|
||||
of identifiers used in the PCH file to the location within the on-disk
|
||||
hash table where that identifier is stored. This mapping is used when
|
||||
deserializing the name of a declaration, the identifier of a token, or
|
||||
any other construct in the PCH file that refers to a name.</p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
1495
docs/PCHLayout.graffle
Normal file
1495
docs/PCHLayout.graffle
Normal file
File diff suppressed because it is too large
Load Diff
BIN
docs/PCHLayout.png
Normal file
BIN
docs/PCHLayout.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
@ -356,7 +356,7 @@ LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h")
|
||||
LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h")
|
||||
LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h")
|
||||
LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h")
|
||||
LIBBUILTIN(vfprintf, "iP*cC*a", "fP:1:", "stdio.h")
|
||||
LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h")
|
||||
LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h")
|
||||
LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h")
|
||||
|
||||
|
@ -30,6 +30,7 @@ def : DiagGroup<"conversion">;
|
||||
def : DiagGroup<"declaration-after-statement">;
|
||||
def : DiagGroup<"disabled-optimization">;
|
||||
def : DiagGroup<"discard-qual">;
|
||||
def EmptyBody : DiagGroup<"empty-body">;
|
||||
def ExtraTokens : DiagGroup<"extra-tokens">;
|
||||
|
||||
def FormatExtraArgs : DiagGroup<"format-extra-args">;
|
||||
|
@ -909,13 +909,13 @@ def err_array_init_list_required : Error<
|
||||
"initialization with '{...}' expected for array">;
|
||||
def err_excess_initializers : Error<
|
||||
"excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
|
||||
def warn_excess_initializers : Warning<
|
||||
def warn_excess_initializers : ExtWarn<
|
||||
"excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
|
||||
def err_excess_initializers_in_char_array_initializer : Error<
|
||||
"excess elements in char array initializer">;
|
||||
def warn_excess_initializers_in_char_array_initializer : Warning<
|
||||
def warn_excess_initializers_in_char_array_initializer : ExtWarn<
|
||||
"excess elements in char array initializer">;
|
||||
def warn_initializer_string_for_char_array_too_long : Warning<
|
||||
def warn_initializer_string_for_char_array_too_long : ExtWarn<
|
||||
"initializer-string for char array is too long">;
|
||||
def warn_braces_around_scalar_init : Warning<
|
||||
"braces around scalar initializer">;
|
||||
@ -1029,7 +1029,7 @@ def err_offsetof_record_type : Error<
|
||||
def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">;
|
||||
def ext_offsetof_extended_field_designator : Extension<
|
||||
"using extended field designator is an extension">;
|
||||
def warn_offsetof_non_pod_type : Warning<"offset of on non-POD type %0">,
|
||||
def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
|
||||
InGroup<InvalidOffsetof>;
|
||||
|
||||
def warn_floatingpoint_eq : Warning<
|
||||
@ -1130,11 +1130,11 @@ def err_typecheck_sub_ptr_object : Error<
|
||||
"subtraction of pointer %0 requires pointee to be a complete object type">;
|
||||
def err_typecheck_sub_ptr_compatible : Error<
|
||||
"%0 and %1 are not pointers to compatible types">;
|
||||
def ext_typecheck_comparison_of_pointer_integer : Warning<
|
||||
def ext_typecheck_comparison_of_pointer_integer : ExtWarn<
|
||||
"comparison between pointer and integer (%0 and %1)">;
|
||||
def ext_typecheck_comparison_of_distinct_pointers : Warning<
|
||||
def ext_typecheck_comparison_of_distinct_pointers : ExtWarn<
|
||||
"comparison of distinct pointer types (%0 and %1)">;
|
||||
def ext_typecheck_cond_incompatible_operands : Warning<
|
||||
def ext_typecheck_cond_incompatible_operands : ExtWarn<
|
||||
"incompatible operand types (%0 and %1)">;
|
||||
def err_typecheck_comparison_of_distinct_pointers : Error<
|
||||
"comparison of distinct pointer types (%0 and %1)">;
|
||||
@ -1443,9 +1443,9 @@ def err_typecheck_cond_incompatible_operands : Error<
|
||||
"incompatible operand types (%0 and %1)">;
|
||||
def err_cast_selector_expr : Error<
|
||||
"cannot type cast @selector expression">;
|
||||
def warn_typecheck_cond_incompatible_pointers : Warning<
|
||||
def warn_typecheck_cond_incompatible_pointers : ExtWarn<
|
||||
"pointer type mismatch (%0 and %1)">;
|
||||
def warn_typecheck_cond_pointer_integer_mismatch : Warning<
|
||||
def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn<
|
||||
"pointer/integer type mismatch in conditional expression (%0 and %1)">;
|
||||
def err_typecheck_choose_expr_requires_constant : Error<
|
||||
"'__builtin_choose_expr' requires a constant expression">;
|
||||
@ -1717,7 +1717,7 @@ def err_typecheck_statement_requires_integer : Error<
|
||||
def err_multiple_default_labels_defined : Error<
|
||||
"multiple default labels in one switch">;
|
||||
def warn_empty_if_body : Warning<
|
||||
"if statement has empty body">;
|
||||
"if statement has empty body">, InGroup<EmptyBody>;
|
||||
def err_va_start_used_in_non_variadic_function : Error<
|
||||
"'va_start' used in function with fixed args">;
|
||||
def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
|
||||
@ -1789,9 +1789,9 @@ def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
|
||||
def warn_receiver_forward_class : Warning<
|
||||
"receiver %0 is a forward class and corresponding @interface may not exist">;
|
||||
def note_method_sent_forward_class : Note<"method %0 is used for the forward class">;
|
||||
def warn_missing_declspec : Warning<
|
||||
def ext_missing_declspec : ExtWarn<
|
||||
"declaration specifier missing, defaulting to 'int'">;
|
||||
def warn_missing_type_specifier : Warning<
|
||||
def ext_missing_type_specifier : ExtWarn<
|
||||
"type specifier missing, defaults to 'int'">,
|
||||
InGroup<ImplicitInt>;
|
||||
def err_decimal_unsupported : Error<
|
||||
|
@ -23,12 +23,17 @@ namespace clang {
|
||||
/// is optimized and passed to the backend.
|
||||
class CompileOptions {
|
||||
public:
|
||||
enum InliningMethod {
|
||||
NoInlining, // Perform no inlining whatsoever.
|
||||
NormalInlining, // Use the standard function inlining pass.
|
||||
OnlyAlwaysInlining // Only run the always inlining pass.
|
||||
};
|
||||
|
||||
unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
|
||||
unsigned OptimizeSize : 1; /// If -Os is specified.
|
||||
unsigned DebugInfo : 1; /// Should generate deubg info (-g).
|
||||
unsigned UnitAtATime : 1; /// Unused. For mirroring GCC
|
||||
/// optimization selection.
|
||||
unsigned InlineFunctions : 1; /// Should functions be inlined?
|
||||
unsigned SimplifyLibCalls : 1; /// Should standard library calls be
|
||||
/// treated specially.
|
||||
unsigned UnrollLoops : 1; /// Control whether loops are unrolled.
|
||||
@ -37,6 +42,9 @@ class CompileOptions {
|
||||
unsigned TimePasses : 1; /// Set when -ftime-report is enabled.
|
||||
unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
|
||||
|
||||
/// Inlining - The kind of inlining to perform.
|
||||
InliningMethod Inlining;
|
||||
|
||||
/// CPU - An optional CPU to target.
|
||||
std::string CPU;
|
||||
|
||||
@ -50,10 +58,11 @@ class CompileOptions {
|
||||
OptimizeSize = 0;
|
||||
DebugInfo = 0;
|
||||
UnitAtATime = 1;
|
||||
InlineFunctions = SimplifyLibCalls = UnrollLoops = 0;
|
||||
SimplifyLibCalls = UnrollLoops = 0;
|
||||
VerifyModule = 1;
|
||||
TimePasses = 0;
|
||||
NoCommon = 0;
|
||||
Inlining = NoInlining;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2785,7 +2785,7 @@ QualType::GCAttrTypes ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
|
||||
}
|
||||
// Non-pointers have none gc'able attribute regardless of the attribute
|
||||
// set on them.
|
||||
else if (!isObjCObjectPointerType(Ty) && !Ty->isPointerType())
|
||||
else if (!Ty->isPointerType() && !isObjCObjectPointerType(Ty))
|
||||
return QualType::GCNone;
|
||||
}
|
||||
return GCAttrs;
|
||||
@ -3033,26 +3033,52 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
|
||||
if (RHSClass == Type::ExtQual) {
|
||||
QualType::GCAttrTypes GCAttr = RHSCan.getObjCGCAttr();
|
||||
if (GCAttr != QualType::GCNone) {
|
||||
QualType::GCAttrTypes GCLHSAttr = LHSCan.getObjCGCAttr();
|
||||
// __weak attribute must appear on both declarations.
|
||||
// __strong attribue is redundant if other decl is an objective-c
|
||||
// object pointer (or decorated with __strong attribute); otherwise
|
||||
// issue error.
|
||||
if ((GCAttr == QualType::Weak && GCLHSAttr != GCAttr) ||
|
||||
(GCAttr == QualType::Strong && GCLHSAttr != GCAttr &&
|
||||
LHSCan->isPointerType() && !isObjCObjectPointerType(LHSCan) &&
|
||||
!isObjCIdStructType(LHSCan->getAsPointerType()->getPointeeType())))
|
||||
return QualType();
|
||||
|
||||
RHS = QualType(cast<ExtQualType>(RHS.getDesugaredType())->getBaseType(),
|
||||
RHS.getCVRQualifiers());
|
||||
QualType Result = mergeTypes(LHS, RHS);
|
||||
if (Result.getObjCGCAttr() == QualType::GCNone)
|
||||
Result = getObjCGCQualType(Result, GCAttr);
|
||||
else if (Result.getObjCGCAttr() != GCAttr)
|
||||
Result = QualType();
|
||||
if (!Result.isNull()) {
|
||||
if (Result.getObjCGCAttr() == QualType::GCNone)
|
||||
Result = getObjCGCQualType(Result, GCAttr);
|
||||
else if (Result.getObjCGCAttr() != GCAttr)
|
||||
Result = QualType();
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
if (LHSClass == Type::ExtQual) {
|
||||
QualType::GCAttrTypes GCAttr = LHSCan.getObjCGCAttr();
|
||||
if (GCAttr != QualType::GCNone) {
|
||||
QualType::GCAttrTypes GCRHSAttr = RHSCan.getObjCGCAttr();
|
||||
// __weak attribute must appear on both declarations. __strong
|
||||
// __strong attribue is redundant if other decl is an objective-c
|
||||
// object pointer (or decorated with __strong attribute); otherwise
|
||||
// issue error.
|
||||
if ((GCAttr == QualType::Weak && GCRHSAttr != GCAttr) ||
|
||||
(GCAttr == QualType::Strong && GCRHSAttr != GCAttr &&
|
||||
RHSCan->isPointerType() && !isObjCObjectPointerType(RHSCan) &&
|
||||
!isObjCIdStructType(RHSCan->getAsPointerType()->getPointeeType())))
|
||||
return QualType();
|
||||
|
||||
LHS = QualType(cast<ExtQualType>(LHS.getDesugaredType())->getBaseType(),
|
||||
LHS.getCVRQualifiers());
|
||||
QualType Result = mergeTypes(LHS, RHS);
|
||||
if (Result.getObjCGCAttr() == QualType::GCNone)
|
||||
Result = getObjCGCQualType(Result, GCAttr);
|
||||
else if (Result.getObjCGCAttr() != GCAttr)
|
||||
Result = QualType();
|
||||
if (!Result.isNull()) {
|
||||
if (Result.getObjCGCAttr() == QualType::GCNone)
|
||||
Result = getObjCGCQualType(Result, GCAttr);
|
||||
else if (Result.getObjCGCAttr() != GCAttr)
|
||||
Result = QualType();
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
@ -1410,7 +1410,7 @@ void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy
|
||||
if (getNumArgs())
|
||||
S += ", ";
|
||||
S += "...";
|
||||
} else if (getNumArgs() == 0) {
|
||||
} else if (getNumArgs() == 0 && !Policy.CPlusPlus) {
|
||||
// Do not emit int() if we have a proto, emit 'int(void)'.
|
||||
S += "void";
|
||||
}
|
||||
|
@ -294,10 +294,16 @@ void BackendConsumer::CreatePasses() {
|
||||
PM->add(createPruneEHPass()); // Remove dead EH info
|
||||
PM->add(createFunctionAttrsPass()); // Set readonly/readnone attrs
|
||||
}
|
||||
if (CompileOpts.InlineFunctions)
|
||||
switch (CompileOpts.Inlining) {
|
||||
case CompileOptions::NoInlining:
|
||||
break;
|
||||
case CompileOptions::NormalInlining:
|
||||
PM->add(createFunctionInliningPass()); // Inline small functions
|
||||
else
|
||||
break;
|
||||
case CompileOptions::OnlyAlwaysInlining:
|
||||
PM->add(createAlwaysInlinerPass()); // Respect always_inline
|
||||
break;
|
||||
}
|
||||
if (CompileOpts.OptimizationLevel > 2)
|
||||
PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args
|
||||
if (CompileOpts.SimplifyLibCalls)
|
||||
@ -341,7 +347,16 @@ void BackendConsumer::CreatePasses() {
|
||||
if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime)
|
||||
PM->add(createConstantMergePass()); // Merge dup global constants
|
||||
} else {
|
||||
PM->add(createAlwaysInlinerPass());
|
||||
switch (CompileOpts.Inlining) {
|
||||
case CompileOptions::NoInlining:
|
||||
break;
|
||||
case CompileOptions::NormalInlining:
|
||||
PM->add(createFunctionInliningPass()); // Inline small functions
|
||||
break;
|
||||
case CompileOptions::OnlyAlwaysInlining:
|
||||
PM->add(createAlwaysInlinerPass()); // Respect always_inline
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,6 +347,7 @@ void PCHWriter::WriteBlockInfoBlock() {
|
||||
|
||||
// PCH Top-Level Block.
|
||||
BLOCK(PCH_BLOCK);
|
||||
RECORD(ORIGINAL_FILE_NAME);
|
||||
RECORD(TYPE_OFFSET);
|
||||
RECORD(DECL_OFFSET);
|
||||
RECORD(LANGUAGE_OPTIONS);
|
||||
|
@ -60,7 +60,7 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
|
||||
// Not va_list.
|
||||
Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
|
||||
S = "'"+S+"' (aka '";
|
||||
S += DesugaredTy.getAsString();
|
||||
S += DesugaredTy.getAsString(Context.PrintingPolicy);
|
||||
S += "')";
|
||||
Output.append(S.begin(), S.end());
|
||||
return;
|
||||
|
@ -107,7 +107,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
|
||||
if (DS.isEmpty()) {
|
||||
if (DeclLoc.isInvalid())
|
||||
DeclLoc = DS.getSourceRange().getBegin();
|
||||
Diag(DeclLoc, diag::warn_missing_declspec)
|
||||
Diag(DeclLoc, diag::ext_missing_declspec)
|
||||
<< DS.getSourceRange()
|
||||
<< CodeModificationHint::CreateInsertion(DS.getSourceRange().getBegin(),
|
||||
"int");
|
||||
@ -125,7 +125,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
|
||||
Diag(DeclLoc, diag::err_missing_type_specifier)
|
||||
<< DS.getSourceRange();
|
||||
else
|
||||
Diag(DeclLoc, diag::warn_missing_type_specifier)
|
||||
Diag(DeclLoc, diag::ext_missing_type_specifier)
|
||||
<< DS.getSourceRange();
|
||||
|
||||
// FIXME: If we could guarantee that the result would be well-formed, it
|
||||
|
13
test/CodeGen/always_inline.c
Normal file
13
test/CodeGen/always_inline.c
Normal file
@ -0,0 +1,13 @@
|
||||
// RUN: clang-cc -emit-llvm -o %t %s &&
|
||||
// RUN: grep '@f0' %t | count 0 &&
|
||||
// RUN: clang-cc -disable-llvm-optzns -emit-llvm -o %t %s &&
|
||||
// RUN: grep '@f0' %t | count 2
|
||||
|
||||
//static int f0() {
|
||||
static int __attribute__((always_inline)) f0() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int f1() {
|
||||
return f0();
|
||||
}
|
@ -5,9 +5,9 @@ void f() {
|
||||
int x, *px;
|
||||
|
||||
// Type id.
|
||||
(T())x; // expected-error {{used type 'T (void)'}}
|
||||
(T())+x; // expected-error {{used type 'T (void)'}}
|
||||
(T())*px; // expected-error {{used type 'T (void)'}}
|
||||
(T())x; // expected-error {{used type 'T ()'}}
|
||||
(T())+x; // expected-error {{used type 'T ()'}}
|
||||
(T())*px; // expected-error {{used type 'T ()'}}
|
||||
|
||||
// Expression.
|
||||
x = (T());
|
||||
|
6
test/Sema/vfprintf-invalid-redecl.c
Normal file
6
test/Sema/vfprintf-invalid-redecl.c
Normal file
@ -0,0 +1,6 @@
|
||||
// RUN: clang-cc %s -fsyntax-only -verify
|
||||
// PR4290
|
||||
|
||||
// The following declaration is not compatible with vfprintf(), but make
|
||||
// sure this isn't an error: autoconf expects this to build.
|
||||
char vfprintf(); // expected-warning {{incompatible redeclaration of library function 'vfprintf'}} expected-note {{'vfprintf' is a builtin}}
|
6
test/Sema/vfprintf-valid-redecl.c
Normal file
6
test/Sema/vfprintf-valid-redecl.c
Normal file
@ -0,0 +1,6 @@
|
||||
// RUN: clang-cc %s -fsyntax-only -pedantic -verify
|
||||
// PR4290
|
||||
|
||||
// The following declaration is compatible with vfprintf, so we shouldn't
|
||||
// warn.
|
||||
int vfprintf();
|
@ -58,6 +58,6 @@ short *bad_const_cast_test(char const *volatile *const volatile *var)
|
||||
// Function pointers.
|
||||
f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}}
|
||||
void (A::*mfn)() = 0;
|
||||
(void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (struct A::*)(void)', which is not a reference, pointer-to-object, or pointer-to-data-member}}
|
||||
(void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (struct A::*)()', which is not a reference, pointer-to-object, or pointer-to-data-member}}
|
||||
return **var3;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ void f() {
|
||||
(int(1)); // expected-warning {{expression result unused}}
|
||||
|
||||
// type-id
|
||||
(int())1; // expected-error {{used type 'int (void)' where arithmetic or pointer type is required}}
|
||||
(int())1; // expected-error {{used type 'int ()' where arithmetic or pointer type is required}}
|
||||
|
||||
// Declarations.
|
||||
int fd(T(a)); // expected-warning {{parentheses were disambiguated as a function declarator}}
|
||||
|
@ -28,6 +28,6 @@ struct B {
|
||||
A *f0();
|
||||
};
|
||||
int f0(B *b) {
|
||||
return b->f0->f0; // expected-error{{member reference base type 'struct A *(void)' is not a structure or union}} \
|
||||
return b->f0->f0; // expected-error{{member reference base type 'struct A *()' is not a structure or union}} \
|
||||
// expected-note{{perhaps you meant to call this function}}
|
||||
}
|
||||
|
@ -80,11 +80,11 @@ void memptrs()
|
||||
void (structure::*psf)() = 0;
|
||||
(void)reinterpret_cast<int (structure::*)()>(psf);
|
||||
|
||||
(void)reinterpret_cast<void (structure::*)()>(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'void (struct structure::*)(void)' is not allowed}}
|
||||
(void)reinterpret_cast<int structure::*>(psf); // expected-error {{reinterpret_cast from 'void (struct structure::*)(void)' to 'int struct structure::*' is not allowed}}
|
||||
(void)reinterpret_cast<void (structure::*)()>(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'void (struct structure::*)()' is not allowed}}
|
||||
(void)reinterpret_cast<int structure::*>(psf); // expected-error {{reinterpret_cast from 'void (struct structure::*)()' to 'int struct structure::*' is not allowed}}
|
||||
|
||||
// Cannot cast from integers to member pointers, not even the null pointer
|
||||
// literal.
|
||||
(void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (struct structure::*)(void)' is not allowed}}
|
||||
(void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (struct structure::*)()' is not allowed}}
|
||||
(void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int struct structure::*' is not allowed}}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ void t_529_10()
|
||||
// Bad code below
|
||||
|
||||
(void)static_cast<int*>((const void*)0); // expected-error {{static_cast from 'void const *' to 'int *' casts away constness}}
|
||||
(void)static_cast<void (*)()>((void*)0); // expected-error {{static_cast from 'void *' to 'void (*)(void)' is not allowed}}
|
||||
(void)static_cast<void (*)()>((void*)0); // expected-error {{static_cast from 'void *' to 'void (*)()' is not allowed}}
|
||||
}
|
||||
|
||||
// Member pointer upcast.
|
||||
|
@ -10,3 +10,21 @@ extern id p1;
|
||||
extern id CFRunLoopGetMain();
|
||||
extern __strong id CFRunLoopGetMain();
|
||||
|
||||
extern __weak id WLoopGetMain(); // expected-note {{previous declaration is here}}
|
||||
extern id WLoopGetMain(); // expected-error {{conflicting types for 'WLoopGetMain'}}
|
||||
|
||||
extern id p3; // expected-note {{previous definition is here}}
|
||||
extern __weak id p3; // expected-error {{redefinition of 'p3' with a different type}}
|
||||
|
||||
extern void *p4; // expected-note {{previous definition is here}}
|
||||
extern void * __strong p4; // expected-error {{redefinition of 'p4' with a different type}}
|
||||
|
||||
extern id p5;
|
||||
extern __strong id p5;
|
||||
|
||||
extern char* __strong p6; // expected-note {{previous definition is here}}
|
||||
extern char* p6; // expected-error {{redefinition of 'p6' with a different type}}
|
||||
|
||||
// FIXME. We do not issue error here because we don't put the attribute on the pointer type.
|
||||
extern __strong char* p7;
|
||||
extern char* p7;
|
||||
|
@ -3,12 +3,12 @@
|
||||
|
||||
void bar(id(^)(void));
|
||||
void foo(id <NSObject>(^objectCreationBlock)(void)) {
|
||||
return bar(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (^)(void)', expected 'id<NSObject> (^)(void)'}}
|
||||
return bar(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (^)()', expected 'id<NSObject> (^)()'}}
|
||||
}
|
||||
|
||||
void bar2(id(*)(void));
|
||||
void foo2(id <NSObject>(*objectCreationBlock)(void)) {
|
||||
return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (*)(void)', expected 'id<NSObject> (*)(void)'}}
|
||||
return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (*)()', expected 'id<NSObject> (*)()'}}
|
||||
}
|
||||
|
||||
void bar3(id(*)()); // expected-note{{candidate function}}
|
||||
|
@ -3,7 +3,7 @@ template<int N> struct A; // expected-note 5{{template parameter is declared her
|
||||
|
||||
A<0> *a0;
|
||||
|
||||
A<int()> *a1; // expected-error{{template argument for non-type template parameter is treated as type 'int (void)'}}
|
||||
A<int()> *a1; // expected-error{{template argument for non-type template parameter is treated as type 'int ()'}}
|
||||
|
||||
A<int> *a2; // expected-error{{template argument for non-type template parameter must be an expression}}
|
||||
|
||||
|
@ -666,6 +666,10 @@ DollarsInIdents("fdollars-in-identifiers",
|
||||
static llvm::cl::opt<bool>
|
||||
OptSize("Os", llvm::cl::desc("Optimize for size"));
|
||||
|
||||
static llvm::cl::opt<bool>
|
||||
DisableLLVMOptimizations("disable-llvm-optzns",
|
||||
llvm::cl::desc("Don't run LLVM optimization passes"));
|
||||
|
||||
static llvm::cl::opt<bool>
|
||||
NoCommon("fno-common",
|
||||
llvm::cl::desc("Compile common globals like normal definitions"),
|
||||
@ -1420,16 +1424,26 @@ static void InitializeCompileOptions(CompileOptions &Opts,
|
||||
const llvm::StringMap<bool> &Features) {
|
||||
Opts.OptimizeSize = OptSize;
|
||||
Opts.DebugInfo = GenerateDebugInfo;
|
||||
if (OptSize) {
|
||||
// -Os implies -O2
|
||||
// FIXME: Diagnose conflicting options.
|
||||
Opts.OptimizationLevel = 2;
|
||||
|
||||
if (DisableLLVMOptimizations) {
|
||||
Opts.OptimizationLevel = 0;
|
||||
Opts.Inlining = CompileOptions::NoInlining;
|
||||
} else {
|
||||
Opts.OptimizationLevel = OptLevel;
|
||||
if (OptSize) {
|
||||
// -Os implies -O2
|
||||
Opts.OptimizationLevel = 2;
|
||||
} else {
|
||||
Opts.OptimizationLevel = OptLevel;
|
||||
}
|
||||
|
||||
// We must always run at least the always inlining pass.
|
||||
if (Opts.OptimizationLevel > 1)
|
||||
Opts.Inlining = CompileOptions::NormalInlining;
|
||||
else
|
||||
Opts.Inlining = CompileOptions::OnlyAlwaysInlining;
|
||||
}
|
||||
|
||||
// FIXME: There are llvm-gcc options to control these selectively.
|
||||
Opts.InlineFunctions = (Opts.OptimizationLevel > 1);
|
||||
Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !OptSize);
|
||||
Opts.SimplifyLibCalls = !LangOpts.NoBuiltin;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user