Import Clang, at r72770.

This commit is contained in:
Ed Schouten 2009-06-03 13:29:08 +00:00
parent ec2b103c26
commit 922a209773
26 changed files with 1897 additions and 52 deletions

View File

@ -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-&gt;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

File diff suppressed because it is too large Load Diff

BIN
docs/PCHLayout.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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";
}

View File

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

View File

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

View File

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

View File

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

View 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();
}

View File

@ -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());

View 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}}

View 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();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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