Import Clang r73340.

This commit is contained in:
Ed Schouten 2009-06-14 09:24:02 +00:00
parent 8ba99c0032
commit 7ef7bab7e3
160 changed files with 6776 additions and 1503 deletions

View File

@ -23,7 +23,7 @@ macro(add_clang_library name)
endif(MSVC)
install(TARGETS ${name}
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
endmacro(add_clang_library)
macro(add_clang_executable name)

View File

@ -138,6 +138,7 @@
DE3461270AFE68BE00DBC861 /* MinimalAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */; };
DE34621D0AFEB19B00DBC861 /* StmtPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */; };
DE3464220B03040900DBC861 /* Type.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3464210B03040900DBC861 /* Type.h */; };
DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE37252D0FE481AD00CF2CC2 /* Builtins.cpp */; };
DE38CD500D794D0100A273B6 /* CGObjCGNU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */; };
DE38CF270D8C9E6C00A273B6 /* DeclObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE38CF260D8C9E6C00A273B6 /* DeclObjC.cpp */; };
DE3986F00CB8D4B300223765 /* IdentifierTable.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3986EF0CB8D4B300223765 /* IdentifierTable.h */; };
@ -200,9 +201,6 @@
DECB78170FA5882F00F5FBC7 /* PCHWriterStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB78160FA5882F00F5FBC7 /* PCHWriterStmt.cpp */; };
DED626C90AE0C065001E80A4 /* TargetInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED626C80AE0C065001E80A4 /* TargetInfo.cpp */; };
DED62ABB0AE2EDF1001E80A4 /* Decl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */; };
DED676D10B6C786700AAD4A3 /* Builtins.def in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED676D00B6C786700AAD4A3 /* Builtins.def */; };
DED676FA0B6C797B00AAD4A3 /* Builtins.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED676F90B6C797B00AAD4A3 /* Builtins.h */; };
DED677C90B6C854100AAD4A3 /* Builtins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED677C80B6C854100AAD4A3 /* Builtins.cpp */; };
DED7D7410A524295003AD0FB /* Diagnostic.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7310A524295003AD0FB /* Diagnostic.h */; };
DED7D7430A524295003AD0FB /* FileManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7330A524295003AD0FB /* FileManager.h */; };
DED7D7450A524295003AD0FB /* SourceLocation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7350A524295003AD0FB /* SourceLocation.h */; };
@ -296,8 +294,6 @@
DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */,
DE1733700B068DC60080B521 /* DeclSpec.h in CopyFiles */,
DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */,
DED676D10B6C786700AAD4A3 /* Builtins.def in CopyFiles */,
DED676FA0B6C797B00AAD4A3 /* Builtins.h in CopyFiles */,
1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */,
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */,
DE67E7150C020EDF00F66BC5 /* Sema.h in CopyFiles */,
@ -353,9 +349,6 @@
1A5D5E570E5E81010023C059 /* CGCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXX.cpp; path = lib/CodeGen/CGCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A649E1D0F9599D9005B965E /* CGBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGBlocks.h; path = lib/CodeGen/CGBlocks.h; sourceTree = "<group>"; };
1A649E1E0F9599DA005B965E /* CGCXX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGCXX.h; path = lib/CodeGen/CGCXX.h; sourceTree = "<group>"; };
1A68BC110D0CADDD001A28C8 /* PPCBuiltins.def */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = text; name = PPCBuiltins.def; path = clang/AST/PPCBuiltins.def; sourceTree = "<group>"; tabWidth = 2; };
1A68BC120D0CADDD001A28C8 /* TargetBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TargetBuiltins.h; path = clang/AST/TargetBuiltins.h; sourceTree = "<group>"; tabWidth = 2; };
1A68BC130D0CADDD001A28C8 /* X86Builtins.def */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = text; name = X86Builtins.def; path = clang/AST/X86Builtins.def; sourceTree = "<group>"; tabWidth = 2; };
1A6FE7080FD6F85800E00CA9 /* CGCXXTemp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXXTemp.cpp; path = lib/CodeGen/CGCXXTemp.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A7019E90F79BC1100FEC4D1 /* DiagnosticAnalysisKinds.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticAnalysisKinds.td; sourceTree = "<group>"; };
1A7019EA0F79BC1100FEC4D1 /* DiagnosticASTKinds.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticASTKinds.td; sourceTree = "<group>"; };
@ -525,6 +518,12 @@
DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = MinimalAction.cpp; path = lib/Parse/MinimalAction.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtPrinter.cpp; path = lib/AST/StmtPrinter.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE3464210B03040900DBC861 /* Type.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Type.h; path = clang/AST/Type.h; sourceTree = "<group>"; tabWidth = 2; };
DE37251C0FE4818000CF2CC2 /* Builtins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Builtins.h; sourceTree = "<group>"; };
DE37252A0FE4818F00CF2CC2 /* Builtins.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Builtins.def; sourceTree = "<group>"; };
DE37252D0FE481AD00CF2CC2 /* Builtins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Builtins.cpp; sourceTree = "<group>"; };
DE3725310FE4822800CF2CC2 /* TargetBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetBuiltins.h; sourceTree = "<group>"; };
DE3725320FE4826C00CF2CC2 /* BuiltinsX86.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BuiltinsX86.def; sourceTree = "<group>"; };
DE3725330FE4827200CF2CC2 /* BuiltinsPPC.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BuiltinsPPC.def; sourceTree = "<group>"; };
DE38CD4E0D794CF900A273B6 /* CGObjCRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGObjCRuntime.h; path = lib/CodeGen/CGObjCRuntime.h; sourceTree = "<group>"; tabWidth = 2; };
DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjCGNU.cpp; path = lib/CodeGen/CGObjCGNU.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE38CF260D8C9E6C00A273B6 /* DeclObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = DeclObjC.cpp; path = lib/AST/DeclObjC.cpp; sourceTree = "<group>"; tabWidth = 2; };
@ -621,9 +620,6 @@
DECB78540FA58F5500F5FBC7 /* AccessSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AccessSpecifier.h; path = clang/Parse/AccessSpecifier.h; sourceTree = "<group>"; };
DED626C80AE0C065001E80A4 /* TargetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = TargetInfo.cpp; sourceTree = "<group>"; tabWidth = 2; };
DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = Decl.cpp; path = lib/AST/Decl.cpp; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
DED676D00B6C786700AAD4A3 /* Builtins.def */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = text; name = Builtins.def; path = clang/AST/Builtins.def; sourceTree = "<group>"; tabWidth = 2; };
DED676F90B6C797B00AAD4A3 /* Builtins.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Builtins.h; path = clang/AST/Builtins.h; sourceTree = "<group>"; tabWidth = 2; };
DED677C80B6C854100AAD4A3 /* Builtins.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = Builtins.cpp; path = lib/AST/Builtins.cpp; sourceTree = "<group>"; tabWidth = 2; };
DED7D7310A524295003AD0FB /* Diagnostic.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = Diagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
DED7D7330A524295003AD0FB /* FileManager.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = FileManager.h; sourceTree = "<group>"; tabWidth = 2; };
DED7D7350A524295003AD0FB /* SourceLocation.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = SourceLocation.h; sourceTree = "<group>"; tabWidth = 2; };
@ -1146,13 +1142,9 @@
DE75ED280B044DC90020CF81 /* ASTContext.h */,
DEA09A6E0F31756F000C2258 /* ASTDiagnostic.h */,
1A72BEAC0D641E9400B085E9 /* Attr.h */,
DED676D00B6C786700AAD4A3 /* Builtins.def */,
DED676F90B6C797B00AAD4A3 /* Builtins.h */,
90FB99DE0F98FB1D008F9415 /* DeclContextInternals.h */,
90FB99DF0F98FB1D008F9415 /* DeclVisitor.h */,
90FB99E00F98FB1D008F9415 /* ExternalASTSource.h */,
1A68BC110D0CADDD001A28C8 /* PPCBuiltins.def */,
1A68BC130D0CADDD001A28C8 /* X86Builtins.def */,
DEC63B1B0C7B940600DBF169 /* CFG.h */,
DEC8D9900A9433CD00353FCA /* Decl.h */,
3538FDB60ED24A2C005EC283 /* DeclarationName.h */,
@ -1176,7 +1168,6 @@
DE345C190AFC658B00DBC861 /* StmtVisitor.h */,
35847BE30CC7DB9000C40FFF /* StmtIterator.h */,
35CFFE010CA1CBDD00E6F2BE /* StmtGraphTraits.h */,
1A68BC120D0CADDD001A28C8 /* TargetBuiltins.h */,
DEDFF87F0F848CE30035BD10 /* TemplateName.h */,
DEF16BE40FA13A5B0098507F /* TypeNodes.def */,
DEF16BE50FA13A650098507F /* TypeOrdering.h */,
@ -1191,7 +1182,6 @@
DE8823CA0ED0046600CBC30A /* APValue.cpp */,
35BB2D7E0D19954000944DB5 /* ASTConsumer.cpp */,
DE1732FF0B068B700080B521 /* ASTContext.cpp */,
DED677C80B6C854100AAD4A3 /* Builtins.cpp */,
DEC63B190C7B940200DBF169 /* CFG.cpp */,
35FE6BCE0DF6EE1F00739712 /* DeclBase.cpp */,
DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */,
@ -1238,6 +1228,10 @@
DED7D7300A524295003AD0FB /* Basic */ = {
isa = PBXGroup;
children = (
DE37251C0FE4818000CF2CC2 /* Builtins.h */,
DE37252A0FE4818F00CF2CC2 /* Builtins.def */,
DE3725330FE4827200CF2CC2 /* BuiltinsPPC.def */,
DE3725320FE4826C00CF2CC2 /* BuiltinsX86.def */,
906BF4AE0F83BA16001071FA /* ConvertUTF.h */,
DED7D7310A524295003AD0FB /* Diagnostic.h */,
DEDFFF070F959EE60035BD10 /* Diagnostic.td */,
@ -1260,6 +1254,7 @@
DED7D7350A524295003AD0FB /* SourceLocation.h */,
DED7D7360A524295003AD0FB /* SourceManager.h */,
9063F2290F9E911F002F7251 /* SourceManagerInternals.h */,
DE3725310FE4822800CF2CC2 /* TargetBuiltins.h */,
DE46BF270AE0A82D00CC047C /* TargetInfo.h */,
9063F22A0F9E911F002F7251 /* TemplateKinds.h */,
DED7D7380A524295003AD0FB /* TokenKinds.h */,
@ -1299,6 +1294,7 @@
DED7D7500A5242C7003AD0FB /* Basic */ = {
isa = PBXGroup;
children = (
DE37252D0FE481AD00CF2CC2 /* Builtins.cpp */,
906BF4AF0F83BA2E001071FA /* ConvertUTF.c */,
DED7D75D0A5242C7003AD0FB /* Diagnostic.cpp */,
DED7D75E0A5242C7003AD0FB /* FileManager.cpp */,
@ -1526,7 +1522,6 @@
DE75EDF10B06880E0020CF81 /* Type.cpp in Sources */,
DE1733000B068B700080B521 /* ASTContext.cpp in Sources */,
DE17336E0B068DC20080B521 /* DeclSpec.cpp in Sources */,
DED677C90B6C854100AAD4A3 /* Builtins.cpp in Sources */,
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */,
DE67E70B0C020EC500F66BC5 /* SemaType.cpp in Sources */,
DE67E70D0C020ECA00F66BC5 /* SemaStmt.cpp in Sources */,
@ -1699,6 +1694,7 @@
1A6FE7090FD6F85800E00CA9 /* CGCXXTemp.cpp in Sources */,
BDF87CF70FD746F300BBF872 /* SemaTemplateDeduction.cpp in Sources */,
1A14D3A70FD78A3F00DA2835 /* DeclPrinter.cpp in Sources */,
DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -19,6 +19,7 @@ td {
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#feature_check">Feature Checking Macros</a></li>
<li><a href="#builtinmacros">Builtin Macros</a></li>
<li><a href="#vectors">Vectors and Extended Vectors</a></li>
<li><a href="#blocks">Blocks</a></li>
@ -45,11 +46,72 @@ td {
<!-- ======================================================================= -->
<p>This document describes the language extensions provided by Clang. In
addition to the langauge extensions listed here, Clang aims to support a broad
addition to the language extensions listed here, Clang aims to support a broad
range of GCC extensions. Please see the <a
href="http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html">GCC manual</a> for
more information on these extensions.</p>
<!-- ======================================================================= -->
<h2 id="feature_check">Feature Checking Macros</h2>
<!-- ======================================================================= -->
<p>Language extensions can be very useful, but only if you know you can depend
on them. In order to allow fine-grain features checks, we support two builtin
function-like macros. This allows you to directly test for a feature in your
code without having to resort to something like autoconf or fragile "compiler
version checks".</p>
<!-- ======================================================================= -->
<h3 id="__has_builtin">__has_builtin</h3>
<!-- ======================================================================= -->
<p>This function-like macro takes a single identifier argument that is the name
of a builtin function. It evaluates to 1 if the builtin is supported or 0 if
not. It can be used like this:</p>
<blockquote>
<pre>
#ifndef __has_builtin // Optional of course.
#define __has_builtin(x) 0 // Compatibility with non-clang compilers.
#endif
...
#if __has_builtin(__builtin_trap)
__builtin_trap();
#else
abort();
#endif
...
</pre>
</blockquote>
<!-- ======================================================================= -->
<h3 id="__has_feature">__has_feature</h3>
<!-- ======================================================================= -->
<p>This function-like macro takes a single identifier argument that is the name
of a feature. It evaluates to 1 if the feature is supported or 0 if not. It
can be used like this:</p>
<blockquote>
<pre>
#ifndef __has_feature // Optional of course.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
...
#if __has_feature(attribute_overloadable) || \
__has_feature(blocks)
...
#endif
...
</pre>
</blockquote>
<p>The feature tag is described along with the language feature below.</p>
<!-- ======================================================================= -->
<h2 id="builtinmacros">Builtin Macros</h2>
<!-- ======================================================================= -->
@ -64,6 +126,8 @@ more information on these extensions.</p>
with V.xyzw syntax and other tidbits. See also <a
href="#__builtin_shufflevector">__builtin_shufflevector</a>.</p>
<p>Query for this feature with __has_feature(attribute_ext_vector_type).</p>
<!-- ======================================================================= -->
<h2 id="blocks">Blocks</h2>
<!-- ======================================================================= -->
@ -73,6 +137,9 @@ href="BlockLanguageSpec.txt">BlockLanguageSpec.txt</a>. Implementation and ABI
details for the clang implementation are in <a
href="BlockImplementation.txt">BlockImplementation.txt</a>.</p>
<p>Query for this feature with __has_feature(blocks).</p>
<!-- ======================================================================= -->
<h2 id="overloading-in-c">Function Overloading in C</h2>
<!-- ======================================================================= -->
@ -171,6 +238,9 @@ caveats to this use of name mangling:</p>
C.</li>
</ul>
<p>Query for this feature with __has_feature(attribute_overloadable).</p>
<!-- ======================================================================= -->
<h2 id="builtins">Builtin Functions</h2>
<!-- ======================================================================= -->
@ -306,11 +376,11 @@ positives due to false paths) by marking their own &quot;panic&quot; functions
with this attribute.</p>
<p>While useful, <tt>noreturn</tt> is not applicable in all cases. Sometimes
there are special functions that for all intensive purposes should be considered
panic functions (i.e., they are only called when an internal program error
occurs) but may actually return so that the program can fail gracefully. The
<tt>analyzer_noreturn</tt> attribute allows one to annotate such functions as
being interpreted as &quot;no return&quot; functions by the analyzer (thus
there are special functions that for all intents and purposes should be
considered panic functions (i.e., they are only called when an internal program
error occurs) but may actually return so that the program can fail gracefully.
The <tt>analyzer_noreturn</tt> attribute allows one to annotate such functions
as being interpreted as &quot;no return&quot; functions by the analyzer (thus
pruning bogus paths) but will not affect compilation (as in the case of
<tt>noreturn</tt>).</p>
@ -320,7 +390,10 @@ placed at the end of function prototypes:</p>
<pre>
void foo() <b>__attribute__((analyzer_noreturn))</b>;
</p>
</pre>
<p>Query for this feature with __has_feature(attribute_analyzer_noreturn).</p>
</div>
</body>

View File

@ -250,7 +250,7 @@ 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
macro definitions is triggered by lookups into the <a
href="#idtable">identifier table</a>.</p>
<h3 id="types">Types Block</h3>
@ -296,8 +296,8 @@ 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
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.
@ -313,7 +313,7 @@ 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
declaration context will be deserialized. There are two representations
of the declarations within a declaration context, which correspond to
the name-lookup and iteration behavior described above:</p>
@ -410,7 +410,8 @@ contains:</p>
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
identifier table. If an identifier is found, its contents---macro definitions, flags, top-level declarations, etc.---will be deserialized, at which point the corresponding <code>IdentifierInfo</code> structure will have the same contents it would have after parsing the headers in the precompiled header.</p>
identifier table. If an identifier is found, its contents (macro
definitions, flags, top-level declarations, etc.) will be deserialized, at which point the corresponding <code>IdentifierInfo</code> structure will have the same contents it would have after parsing the headers in the precompiled header.</p>
<p>Within the PCH file, the identifiers used to name declarations are represented with an integral value. A separate table provides a mapping from this integral value (the identifier ID) to the location within the on-disk
hash table where that identifier is stored. This mapping is used when

View File

@ -455,7 +455,7 @@ GCC.</p>
for headers that are directly included within a source file. For example:</p>
<pre>
$ clang -x c-header test.h -o test.h.cth
$ clang -x c-header test.h -o test.h.pch
$ cat test.c
#include "test.h"
$ clang test.c -o test
@ -564,17 +564,25 @@ implemented.</li>
<li>clang does not support nested functions; this is a complex feature which
is infrequently used, so it is unlikely to be implemented anytime soon.</li>
<li>clang does not support __builtin_apply and friends; this extension requires
complex code generator support that does not currently exist in LLVM, and there
is very little demand, so it is unlikely to be implemented anytime soon.</li>
<li>clang does not support global register variables, this is unlikely
to be implemented soon.</li>
to be implemented soon because it requires additional LLVM backend support.
</li>
<li>clang does not support static initialization of flexible array
members. This appears to be a rarely used extension, but could be
implemented pending user demand.</li>
<li>clang does not support __builtin_va_arg_pack/__builtin_va_arg_pack_len.
This is used rarely, but in some potentially interesting places, like the
glibc headers, so it may be implemented pending user demand. Note that
because clang pretends to be like GCC 4.2, and this extension was introduced
in 4.3, the glibc headers will not try to use this extension with clang at
the moment.</li>
<li>clang does not support the gcc extension for forward-declaring function
parameters; this has not showed up in any real-world code yet, though, so it
might never be implemented.</li>
</ul>
<p>This is not a complete list; if you find an unsupported extension
@ -589,16 +597,32 @@ bug-reporting guidelines somewhere?).</p>
<h3 id="c_unsupp_gcc">Intentionally unsupported GCC extensions</h3>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<p>clang does not support the gcc extension that allows variable-length arrays
<ul>
<li>clang does not support the gcc extension that allows variable-length arrays
in structures. This is for a few of reasons: one, it is tricky
to implement, two, the extension is completely undocumented, and three, the
extension appears to be very rarely used.</p>
extension appears to be rarely used.</li>
<p>clang does not support duplicate definitions of a function where one is
<li>clang does not support duplicate definitions of a function where one is
inline. This complicates clients of the AST which normally can expect there is
at most one definition for each function. Source code using this feature should
be changed to define the inline and out-of-line definitions in separate
translation units.</p>
translation units.</li>
<li>clang does not have an equivalent to gcc's "fold"; this means that
clang doesn't accept some constructs gcc might accept in contexts where a
constant expression is required, like "x-x" where x is a variable, or calls
to C library functions like strlen.</li>
<li>clang does not support multiple alternative constraints in inline asm; this
is an extremely obscure feature which would be complicated to implement
correctly.</li>
<li>clang does not support __builtin_apply and friends; this extension is
extremely obscure and difficult to implement reliably.</li>
</ul>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<h3 id="c_ms">Microsoft extensions</h3>

View File

@ -17,13 +17,11 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/OwningPtr.h"
@ -56,6 +54,8 @@ namespace clang {
class ObjCIvarRefExpr;
class ObjCIvarDecl;
namespace Builtin { class Context; }
/// ASTContext - This class holds long-lived AST nodes (such as types and
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
@ -142,6 +142,7 @@ public:
TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
Builtin::Context &BuiltinInfo;
DeclarationNameTable DeclarationNames;
llvm::OwningPtr<ExternalASTSource> ExternalSource;
clang::PrintingPolicy PrintingPolicy;
@ -164,7 +165,6 @@ public:
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
Builtin::Context BuiltinInfo;
// Builtin Types.
QualType VoidTy;
@ -181,21 +181,12 @@ public:
QualType DependentTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
bool FreeMemory = true, unsigned size_reserve=0,
bool InitializeBuiltins = true);
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
bool FreeMemory = true, unsigned size_reserve=0);
~ASTContext();
/// \brief Initialize builtins.
///
/// Typically, this routine will be called automatically by the
/// constructor. However, in certain cases (e.g., when there is a
/// PCH file to be loaded), the constructor does not perform
/// initialization for builtins. This routine can be called to
/// perform the initialization.
void InitializeBuiltins(IdentifierTable &idents);
/// \brief Attach an external AST source to the AST context.
///
/// The external AST source provides the ability to load parts of
@ -455,6 +446,14 @@ public:
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
const IdentifierInfo *Name);
enum GetBuiltinTypeError {
GE_None, //< No error
GE_Missing_FILE //< Missing the FILE type from <stdio.h>
};
/// GetBuiltinType - Return the type for the specified builtin.
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error);
private:
QualType getFromTargetType(unsigned Type) const;

View File

@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.inc"
#undef DIAG

View File

@ -24,10 +24,16 @@ namespace clang {
}
// Defined in ASTContext.cpp
// Defined in ASTContext.h
void *operator new(size_t Bytes, clang::ASTContext &C,
size_t Alignment = 16) throw ();
// It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
throw ();
namespace clang {
/// Attr - This represents one attribute.

View File

@ -298,9 +298,13 @@ public:
static bool CollectingStats(bool Enable = false);
static void PrintStats();
/// isTemplateParameter - Determines whether this declartion is a
/// isTemplateParameter - Determines whether this declaration is a
/// template parameter.
bool isTemplateParameter() const;
/// isTemplateParameter - Determines whether this declaration is a
/// template parameter pack.
bool isTemplateParameterPack() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *) { return true; }

View File

@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
namespace clang {
@ -29,6 +30,10 @@ class TemplateTypeParmDecl;
class NonTypeTemplateParmDecl;
class TemplateTemplateParmDecl;
/// \brief Stores a template parameter of any kind.
typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
TemplateTemplateParmDecl*> TemplateParameter;
/// TemplateParameterList - Stores a list of template parameters for a
/// TemplateDecl and its derived classes.
class TemplateParameterList {
@ -69,6 +74,11 @@ public:
unsigned size() const { return NumParams; }
Decl* getParam(unsigned Idx) {
assert(Idx < size() && "Template parameter index out-of-range");
return begin()[Idx];
}
const Decl* getParam(unsigned Idx) const {
assert(Idx < size() && "Template parameter index out-of-range");
return begin()[Idx];
@ -77,7 +87,7 @@ public:
/// \btief Returns the minimum number of arguments needed to form a
/// template specialization. This may be fewer than the number of
/// template parameters, if some of the parameters have default
/// arguments.
/// arguments or if there is a parameter pack.
unsigned getMinRequiredArguments() const;
SourceLocation getTemplateLoc() const { return TemplateLoc; }
@ -223,6 +233,9 @@ class TemplateTypeParmDecl : public TypeDecl {
/// default argument.
bool InheritedDefault : 1;
/// \brief Whether this is a parameter pack.
bool ParameterPack : 1;
/// \brief The location of the default argument, if any.
SourceLocation DefaultArgumentLoc;
@ -230,16 +243,17 @@ class TemplateTypeParmDecl : public TypeDecl {
QualType DefaultArgument;
TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
bool Typename, QualType Type)
bool Typename, QualType Type, bool ParameterPack)
: TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
InheritedDefault(false), DefaultArgument() {
InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
TypeForDecl = Type.getTypePtr();
}
public:
static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename);
IdentifierInfo *Id, bool Typename,
bool ParameterPack);
/// \brief Whether this template type parameter was declared with
/// the 'typename' keyword. If not, it was declared with the 'class'
@ -270,6 +284,9 @@ public:
InheritedDefault = Inherited;
}
/// \brief Returns whether this is a parameter pack.
bool isParameterPack() const { return ParameterPack; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == TemplateTypeParm;
@ -575,17 +592,38 @@ public:
/// \brief A helper class for making template argument lists.
class TemplateArgumentListBuilder {
/// Args - contains the template arguments.
llvm::SmallVector<TemplateArgument, 16> Args;
llvm::SmallVector<unsigned, 32> Indices;
ASTContext &Context;
/// isAddingFromParameterPack - Returns whether we're adding arguments from
/// a parameter pack.
bool isAddingFromParameterPack() const { return Indices.size() % 2; }
public:
TemplateArgumentListBuilder(ASTContext &Context) : Context(Context) { }
// FIXME: Should use the index array size.
size_t size() const { return Args.size(); }
size_t size() const {
assert(!isAddingFromParameterPack() &&
"Size is not valid when adding from a parameter pack");
return Indices.size() / 2;
}
size_t flatSize() const { return Args.size(); }
void push_back(const TemplateArgument& Arg);
/// BeginParameterPack - Start adding arguments from a parameter pack.
void BeginParameterPack();
/// EndParameterPack - Finish adding arguments from a parameter pack.
void EndParameterPack();
const TemplateArgument *getFlatArgumentList() const { return Args.data(); }
TemplateArgument *getFlatArgumentList() { return Args.data(); }
};
@ -733,6 +771,7 @@ public:
static void
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
ID.AddInteger(NumTemplateArgs);
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
TemplateArgs[Arg].Profile(ID);
}

View File

@ -709,14 +709,14 @@ class DoStmt : public Stmt {
Stmt* SubExprs[END_EXPR];
SourceLocation DoLoc;
SourceLocation WhileLoc;
SourceLocation RParenLoc; // Location of final ')' in do stmt condition.
public:
DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL)
: Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL) {
DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL,
SourceLocation RP)
: Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) {
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[BODY] = body;
DoLoc = DL;
WhileLoc = WL;
}
/// \brief Build an empty do-while statement.
@ -734,8 +734,11 @@ public:
SourceLocation getWhileLoc() const { return WhileLoc; }
void setWhileLoc(SourceLocation L) { WhileLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
virtual SourceRange getSourceRange() const {
return SourceRange(DoLoc, SubExprs[BODY]->getLocEnd());
return SourceRange(DoLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == DoStmtClass;

View File

@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define ANALYSISSTART
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#undef DIAG

View File

@ -12,12 +12,14 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_BUILTINS_H
#define LLVM_CLANG_AST_BUILTINS_H
#ifndef LLVM_CLANG_BASIC_BUILTINS_H
#define LLVM_CLANG_BASIC_BUILTINS_H
#include <cstring>
#include <string>
#include "llvm/ADT/SmallVector.h"
namespace llvm {
template <typename T> class SmallVectorImpl;
}
namespace clang {
class TargetInfo;
@ -29,7 +31,7 @@ namespace Builtin {
enum ID {
NotBuiltin = 0, // This is not a builtin function.
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/AST/Builtins.def"
#include "clang/Basic/Builtins.def"
FirstTSBuiltin
};
@ -53,14 +55,11 @@ class Context {
public:
Context() : TSRecords(0), NumTSRecords(0) {}
/// \brief Load all of the target builtins. This should be called
/// prior to initializing the builtin identifiers.
void InitializeTargetBuiltins(const TargetInfo &Target);
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false);
void InitializeBuiltins(IdentifierTable &Table, const TargetInfo &Target,
bool NoBuiltins = false);
/// \brief Popular the vector with the names of all of the builtins.
void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
@ -72,6 +71,11 @@ public:
return GetRecord(ID).Name;
}
/// GetTypeString - Get the type descriptor string for the specified builtin.
const char *GetTypeString(unsigned ID) const {
return GetRecord(ID).Type;
}
/// isConst - Return true if this function has no side effects and doesn't
/// read memory.
bool isConst(unsigned ID) const {
@ -121,13 +125,6 @@ public:
return strchr(GetRecord(ID).Attributes, 'e') != 0;
}
/// GetBuiltinType - Return the type for the specified builtin.
enum GetBuiltinTypeError {
GE_None, //< No error
GE_Missing_FILE //< Missing the FILE type from <stdio.h>
};
QualType GetBuiltinType(unsigned ID, ASTContext &Context,
GetBuiltinTypeError &Error) const;
private:
const Info &GetRecord(unsigned ID) const;
};

View File

@ -1,4 +1,4 @@
//===--- PPCBuiltins.def - PowerPC Builtin function database ----*- C++ -*-===//
//===--- BuiltinsPPC.def - PowerPC Builtin function database ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -15,7 +15,7 @@
// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
// adding stuff on demand.
// The format of this database matches clang/AST/Builtins.def.
// The format of this database matches clang/Basic/Builtins.def.
// This is just a placeholder, the types and attributes are wrong.
BUILTIN(__builtin_altivec_abs_v4sf , "ii" , "nc")

View File

@ -1,4 +1,4 @@
//===--- X86Builtins.def - X86 Builtin function database --------*- C++ -*-===//
//===--- BuiltinsX86.def - X86 Builtin function database --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
// The format of this database matches clang/AST/Builtins.def.
// The format of this database matches clang/Basic/Builtins.def.
// FIXME: In GCC, these builtins are defined depending on whether support for
// MMX/SSE/etc is turned on. We should do this too.

View File

@ -50,7 +50,7 @@ namespace clang {
// Get typedefs for common diagnostics.
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#include "clang/Basic/DiagnosticCommonKinds.inc"
NUM_BUILTIN_COMMON_DIAGNOSTICS
#undef DIAG
@ -313,6 +313,16 @@ public:
/// the diagnostic, this returns null.
static const char *getWarningOptionForDiag(unsigned DiagID);
/// \brief Determines whether the given built-in diagnostic ID is
/// for an error that is suppressed if it occurs during C++ template
/// argument deduction.
///
/// When an error is suppressed due to SFINAE, the template argument
/// deduction fails but no diagnostic is emitted. Certain classes of
/// errors, such as those errors that involve C++ access control,
/// are not SFINAE errors.
static bool isBuiltinSFINAEDiag(unsigned DiagID);
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
@ -409,7 +419,10 @@ private:
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
void ProcessDiag();
///
/// \returns true if the diagnostic was emitted, false if it was
/// suppressed.
bool ProcessDiag();
};
//===----------------------------------------------------------------------===//
@ -448,14 +461,26 @@ public:
NumCodeModificationHints = D.NumCodeModificationHints;
}
/// \brief Simple enumeration value used to give a name to the
/// suppress-diagnostic constructor.
enum SuppressKind { Suppress };
/// \brief Create an empty DiagnosticBuilder object that represents
/// no actual diagnostic.
explicit DiagnosticBuilder(SuppressKind)
: DiagObj(0), NumArgs(0), NumRanges(0), NumCodeModificationHints(0) { }
/// \brief Force the diagnostic builder to emit the diagnostic now.
///
/// Once this function has been called, the DiagnosticBuilder object
/// should not be used again before it is destroyed.
void Emit() {
///
/// \returns true if a diagnostic was emitted, false if the
/// diagnostic was suppressed.
bool Emit() {
// If DiagObj is null, then its soul was stolen by the copy ctor
// or the user called Emit().
if (DiagObj == 0) return;
if (DiagObj == 0) return false;
// When emitting diagnostics, we set the final argument count into
// the Diagnostic object.
@ -465,13 +490,15 @@ public:
// Process the diagnostic, sending the accumulated information to the
// DiagnosticClient.
DiagObj->ProcessDiag();
bool Emitted = DiagObj->ProcessDiag();
// Clear out the current diagnostic object.
DiagObj->Clear();
// This diagnostic is dead.
DiagObj = 0;
return Emitted;
}
/// Destructor - The dtor emits the diagnostic if it hasn't already
@ -486,28 +513,34 @@ public:
void AddString(const std::string &S) const {
assert(NumArgs < Diagnostic::MaxArguments &&
"Too many arguments to diagnostic!");
DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
DiagObj->DiagArgumentsStr[NumArgs++] = S;
if (DiagObj) {
DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
DiagObj->DiagArgumentsStr[NumArgs++] = S;
}
}
void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
assert(NumArgs < Diagnostic::MaxArguments &&
"Too many arguments to diagnostic!");
DiagObj->DiagArgumentsKind[NumArgs] = Kind;
DiagObj->DiagArgumentsVal[NumArgs++] = V;
if (DiagObj) {
DiagObj->DiagArgumentsKind[NumArgs] = Kind;
DiagObj->DiagArgumentsVal[NumArgs++] = V;
}
}
void AddSourceRange(const SourceRange &R) const {
assert(NumRanges <
sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
"Too many arguments to diagnostic!");
DiagObj->DiagRanges[NumRanges++] = &R;
if (DiagObj)
DiagObj->DiagRanges[NumRanges++] = &R;
}
void AddCodeModificationHint(const CodeModificationHint &Hint) const {
assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints &&
"Too many code modification hints!");
DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
if (DiagObj)
DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
}
};

View File

@ -45,6 +45,7 @@ class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
string Component = ?;
string Text = text;
DiagClass Class = DC;
bit SFINAE = 1;
DiagMapping DefaultMapping = defaultmapping;
DiagGroup Group;
}
@ -61,6 +62,8 @@ class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; }
class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; }
class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; }
class NoSFINAE { bit SFINAE = 0; }
// Definitions for Diagnostics.
include "DiagnosticASTKinds.td"
include "DiagnosticAnalysisKinds.td"

View File

@ -205,6 +205,10 @@ def err_pp_expr_bad_token_start_expr : Error<
"invalid token at start of a preprocessor expression">;
def err_pp_invalid_poison : Error<"can only poison identifier tokens">;
def err_pp_used_poisoned_id : Error<"attempt to use a poisoned identifier">;
def err_feature_check_malformed : Error<
"builtin feature check macro requires a parenthesized identifier">;
def err__Pragma_malformed : Error<
"_Pragma takes a parenthesized string literal">;
def err_pragma_comment_malformed : Error<

View File

@ -100,10 +100,16 @@ def err_expected_comma : Error<"expected ','">;
def err_expected_lbrace_in_compound_literal : Error<
"expected '{' in compound literal">;
def err_expected_while : Error<"expected 'while' in do/while loop">;
def err_expected_semi_after : Error<"expected ';' after %0">;
def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">;
def err_expected_semi_after_expr : Error<"expected ';' after expression">;
def err_expected_semi_after_method_proto : Error<
"expected ';' after method prototype">;
def err_expected_semi_after_namespace_name : Error<
"expected ';' after namespace name">;
def err_expected_semi_after_attribute_list : Error<
"expected ';' after attribute list">;
def err_expected_semi_after_static_assert : Error<
"expected ';' after static_assert">;
def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
@ -256,6 +262,9 @@ def err_typename_refers_to_non_type_template : Error<
def err_expected_type_name_after_typename : Error<
"expected an identifier or template-id after '::'">;
def err_variadic_templates : Error<
"variadic templates are only allowed in C++0x">;
// Language specific pragmas
// - Generic warnings
def warn_pragma_expected_lparen : Warning<

View File

@ -331,7 +331,7 @@ def note_overridden_virtual_function : Note<
def err_covariant_return_inaccessible_base : Error<
"return type of virtual function %2 is not covariant with the return type "
"of the function it overrides "
"(conversion from %0 to inaccessible base class %1)">;
"(conversion from %0 to inaccessible base class %1)">, NoSFINAE;
def err_covariant_return_ambiguous_derived_to_base_conv : Error<
"return type of virtual function %3 is not covariant with the return type of "
"the function it overrides (ambiguous conversion from derived class "
@ -572,6 +572,11 @@ def err_param_default_argument_nonfunc : Error<
"default arguments can only be specified for parameters in a function "
"declaration">;
def err_use_of_default_argument_to_function_declared_later : Error<
"use of default argument to function %0 that is declared later in class %1">;
def note_default_argument_declared_here : Note<
"default argument declared here">;
def ext_param_promoted_not_compatible_with_prototype : ExtWarn<
"promoted type %0 of K&R function parameter is not compatible with the "
"parameter type %1 declared in a previous prototype">;
@ -737,26 +742,48 @@ def err_template_spec_needs_header : Error<
"template specialization requires 'template<>'">;
def err_template_spec_extra_headers : Error<
"template specialization must have a single 'template<>' header">;
def err_template_spec_decl_out_of_scope_global : Error<
"class template %select{|partial }0specialization of %1 must occur in the "
"global scope">;
def err_template_spec_decl_out_of_scope : Error<
"class template %select{|partial }0specialization of %1 not in namespace %2">;
def err_template_spec_decl_function_scope : Error<
"%select{class template specialization|class template partial specialization|"
"explicit instantiation}0 of %1 in function scope">;
def err_template_spec_redecl_out_of_scope : Error<
"%select{class template specialization|class template partial specialization|"
"explicit instantiation}0 of %1 not in a namespace enclosing %2">;
def err_template_spec_redecl_global_scope : Error<
"%select{class template specialization|class template partial specialization|"
"explicit instantiation}0 of %1 must occur at global scope">;
// C++ Class Template Partial Specialization
def err_default_arg_in_partial_spec : Error<
"default template argument in a class template partial specialization">;
def err_dependent_non_type_arg_in_partial_spec : Error<
"non-type template argument depends on a template parameter of the "
"partial specialization">;
def err_dependent_typed_non_type_arg_in_partial_spec : Error<
"non-type template argument specializes a template parameter with "
"dependent type %0">;
def err_partial_spec_args_match_primary_template : Error<
"class template partial specialization does not specialize any template "
"argument; to %select{declare|define}0 the primary template, remove the "
"template argument list">;
def warn_partial_specs_not_deducible : Warning<
"class template partial specialization contains "
"%select{a template parameter|template parameters}0 that can not be "
"deduced; this partial specialization will never be used">;
def note_partial_spec_unused_parameter : Note<
"non-deducible template parameter %0">;
def unsup_template_partial_spec_ordering : Error<
"partial ordering of class template partial specializations is not yet "
"supported">;
def err_template_spec_decl_out_of_scope_global : Error<
"class template specialization of %0 must occur in the global scope">;
def err_template_spec_decl_out_of_scope : Error<
"class template specialization of %0 not in namespace %1">;
def err_template_spec_decl_function_scope : Error<
"%select{class template specialization|explicit instantiation}0 of %1 "
"in function scope">;
def err_template_spec_redecl_out_of_scope : Error<
"%select{class template specialization|explicit instantiation}0 of %1 "
"not in a namespace enclosing %2">;
def err_template_spec_redecl_global_scope : Error<
"%select{class template specialization|explicit instantiation}0 of %1 must "
"occur at global scope">;
// C++ Template Instantiation
def err_template_recursion_depth_exceeded : Error<
"recursive template instantiation exceeded maximum depth of %0">,DefaultFatal;
"recursive template instantiation exceeded maximum depth of %0">,
DefaultFatal, NoSFINAE;
def note_template_recursion_depth : Note<
"use -ftemplate-depth-N to increase recursive template instantiation depth">;
@ -772,6 +799,9 @@ def note_template_member_function_here : Note<
"in instantiation of member function %q0 requested here">;
def note_default_arg_instantiation_here : Note<
"in instantiation of default argument for '%0' required here">;
def note_partial_spec_deduct_instantiation_here : Note<
"during template argument deduction for class template partial "
"specialization %0, here">;
def err_field_instantiates_to_function : Error<
"data member instantiated with function type %0">;
def err_nested_name_spec_non_tag : Error<
@ -810,6 +840,12 @@ def err_template_kw_refers_to_non_template : Error<
def err_template_kw_refers_to_function_template : Error<
"%0 following the 'template' keyword refers to a function template">;
// C++0x Variadic Templates
def err_template_param_pack_default_arg : Error<
"template parameter pack cannot have a default argument">;
def err_template_param_pack_must_be_last_template_parameter : Error<
"template parameter pack must be the last template parameter">;
def err_unexpected_typedef : Error<
"unexpected type name %0: expected expression">;
def err_unexpected_namespace : Error<
@ -1001,6 +1037,8 @@ def err_illegal_decl_mempointer_to_void : Error<
"'%0' declared as a member pointer to void">;
def err_illegal_decl_mempointer_in_nonclass : Error<
"'%0' does not point into a class">;
def err_mempointer_in_nonclass_type : Error<
"member pointer refers into non-class type %0">;
def err_reference_to_void : Error<"cannot form a reference to 'void'">;
def err_qualified_block_pointer_type : Error<
"qualifier specification on block pointer type not allowed">;
@ -1567,7 +1605,7 @@ def err_memptr_conv_via_virtual : Error<
// C++ access control
def err_conv_to_inaccessible_base : Error<
"conversion from %0 to inaccessible base class %1">;
"conversion from %0 to inaccessible base class %1">, NoSFINAE;
def note_inheritance_specifier_here : Note<
"'%0' inheritance specifier here">;
def note_inheritance_implicitly_private_here : Note<
@ -1814,8 +1852,10 @@ def warn_ivar_use_hidden : Warning<
"local declaration of %0 hides instance variable">;
def error_ivar_use_in_class_method : Error<
"instance variable %0 accessed in class method">;
def error_private_ivar_access : Error<"instance variable %0 is private">;
def error_protected_ivar_access : Error<"instance variable %0 is protected">;
def error_private_ivar_access : Error<"instance variable %0 is private">,
NoSFINAE;
def error_protected_ivar_access : Error<"instance variable %0 is protected">,
NoSFINAE;
def warn_maynot_respond : Warning<"%0 may not respond to %1">;
def warn_attribute_method_def : Warning<
"method attribute can only be specified on method declarations">;

View File

@ -593,6 +593,12 @@ public:
return getFileCharacteristic(Loc) != SrcMgr::C_User;
}
/// isInExternCSystemHeader - Returns if a SourceLocation is in an "extern C"
/// system header.
bool isInExternCSystemHeader(SourceLocation Loc) const {
return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
}
//===--------------------------------------------------------------------===//
// Line Table Manipulation Routines
//===--------------------------------------------------------------------===//

View File

@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TARGET_BUILTINS_H
#define LLVM_CLANG_AST_TARGET_BUILTINS_H
#ifndef LLVM_CLANG_BASIC_TARGET_BUILTINS_H
#define LLVM_CLANG_BASIC_TARGET_BUILTINS_H
#include "clang/AST/Builtins.h"
#include "clang/Basic/Builtins.h"
#undef PPC
namespace clang {
@ -19,7 +19,7 @@ namespace clang {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "X86Builtins.def"
#include "clang/Basic/BuiltinsX86.def"
LastTSBuiltin
};
}
@ -29,7 +29,7 @@ namespace clang {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "PPCBuiltins.def"
#include "clang/Basic/BuiltinsPPC.def"
LastTSBuiltin
};
}

View File

@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define DRIVERSTART
#include "clang/Basic/DiagnosticDriverKinds.inc"
#undef DIAG

View File

@ -419,6 +419,7 @@ OPTION("-fno-keep-inline-functions", fno_keep_inline_functions, Flag, clang_igno
OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-show-column", fno_show_column, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-show-source-location", fno_show_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-stack-protector", fno_stack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-strict-aliasing", fno_strict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-unit-at-a-time", fno_unit_at_a_time, Flag, f_Group, INVALID, "", 0, 0, 0)
@ -446,6 +447,7 @@ OPTION("-fpie", fpie, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fprofile-arcs", fprofile_arcs, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fprofile-generate", fprofile_generate, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0)
OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fstack-protector", fstack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)

View File

@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define FRONTENDSTART
#include "clang/Basic/DiagnosticFrontendKinds.inc"
#undef DIAG

View File

@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define LEXSTART
#include "clang/Basic/DiagnosticLexKinds.inc"
#undef DIAG

View File

@ -19,6 +19,7 @@
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/TokenLexer.h"
#include "clang/Lex/PTHManager.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
@ -69,6 +70,8 @@ class Preprocessor {
IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
IdentifierInfo *Ident__COUNTER__; // __COUNTER__
IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__
IdentifierInfo *Ident__has_feature; // __has_feature
IdentifierInfo *Ident__has_builtin; // __has_builtin
SourceLocation DATELoc, TIMELoc;
unsigned CounterValue; // Next __COUNTER__ value.
@ -99,6 +102,9 @@ class Preprocessor {
/// the lifetime fo the preprocessor.
SelectorTable Selectors;
/// BuiltinInfo - Information about builtins.
Builtin::Context BuiltinInfo;
/// PragmaHandlers - This tracks all of the pragmas that the client registered
/// with this preprocessor.
PragmaNamespace *PragmaHandlers;
@ -194,14 +200,13 @@ private: // Cached tokens state.
public:
Preprocessor(Diagnostic &diags, const LangOptions &opts, TargetInfo &target,
SourceManager &SM, HeaderSearch &Headers,
IdentifierInfoLookup* IILookup = 0);
IdentifierInfoLookup *IILookup = 0);
~Preprocessor();
Diagnostic &getDiagnostics() const { return *Diags; }
void setDiagnostics(Diagnostic &D) { Diags = &D; }
const LangOptions &getLangOptions() const { return Features; }
TargetInfo &getTargetInfo() const { return Target; }
FileManager &getFileManager() const { return FileMgr; }
@ -210,6 +215,7 @@ public:
IdentifierTable &getIdentifierTable() { return Identifiers; }
SelectorTable &getSelectorTable() { return Selectors; }
Builtin::Context &getBuiltinInfo() { return BuiltinInfo; }
llvm::BumpPtrAllocator &getPreprocessorAllocator() { return BP; }
void setPTHManager(PTHManager* pm);
@ -667,7 +673,6 @@ private:
/// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
/// identifier table.
void RegisterBuiltinMacros();
IdentifierInfo *RegisterBuiltinMacro(const char *Name);
/// HandleMacroExpandedIdentifier - If an identifier token is read that is to
/// be expanded as a macro, handle it and return the next token as 'Tok'. If

View File

@ -517,7 +517,10 @@ public:
return StmtEmpty();
}
virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
SourceLocation WhileLoc, ExprArg Cond) {
SourceLocation WhileLoc,
SourceLocation CondLParen,
ExprArg Cond,
SourceLocation CondRParen) {
return StmtEmpty();
}
virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
@ -916,7 +919,8 @@ public:
/// because we're inside a class definition. Note that this default
/// argument will be parsed later.
virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc) { }
SourceLocation EqualLoc,
SourceLocation ArgLoc) { }
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
@ -1165,16 +1169,18 @@ public:
/// ActOnTypeParameter - Called when a C++ template type parameter
/// (e.g., "typename T") has been parsed. Typename specifies whether
/// the keyword "typename" was used to declare the type parameter
/// (otherwise, "class" was used), and KeyLoc is the location of the
/// "class" or "typename" keyword. ParamName is the name of the
/// parameter (NULL indicates an unnamed template parameter) and
/// ParamNameLoc is the location of the parameter name (if any).
/// (otherwise, "class" was used), ellipsis specifies whether this is a
/// C++0x parameter pack, EllipsisLoc specifies the start of the ellipsis,
/// and KeyLoc is the location of the "class" or "typename" keyword.
// ParamName is the name of the parameter (NULL indicates an unnamed template
// parameter) and ParamNameLoc is the location of the parameter name (if any)
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault. Depth and Position provide
/// the number of enclosing templates (see
/// ActOnTemplateParameterList) and the number of previous
/// parameters within this template parameter list.
virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename,
virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,

View File

@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define PARSESTART
#include "clang/Basic/DiagnosticParseKinds.inc"
#undef DIAG

View File

@ -868,7 +868,9 @@ private:
OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false);
OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
bool ParseParenExprOrCondition(OwningExprResult &CondExp,
bool OnlyAllowCondition = false);
bool OnlyAllowCondition = false,
SourceLocation *LParenLoc = 0,
SourceLocation *RParenLoc = 0);
OwningStmtResult ParseIfStatement();
OwningStmtResult ParseSwitchStatement();
OwningStmtResult ParseWhileStatement();
@ -1064,7 +1066,8 @@ private:
// EndLoc, if non-NULL, is filled with the location of the last token of
// the attribute list.
AttributeList *ParseAttributes(SourceLocation *EndLoc = 0);
AttributeList *ParseMicrosoftDeclSpec();
AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
void ParseTypeofSpecifier(DeclSpec &DS);
/// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to

View File

@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define SEMASTART
#include "clang/Basic/DiagnosticSemaKinds.inc"
#undef DIAG

View File

@ -18,6 +18,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
@ -32,18 +33,15 @@ enum FloatingRank {
ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
bool FreeMem, unsigned size_reserve,
bool InitializeBuiltins) :
Builtin::Context &builtins,
bool FreeMem, unsigned size_reserve) :
GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),
ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts),
FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels),
ExternalSource(0) {
BuiltinInfo(builtins), ExternalSource(0) {
if (size_reserve > 0) Types.reserve(size_reserve);
InitBuiltinTypes();
TUDecl = TranslationUnitDecl::Create(*this);
BuiltinInfo.InitializeTargetBuiltins(Target);
if (InitializeBuiltins)
this->InitializeBuiltins(idents);
PrintingPolicy.CPlusPlus = LangOpts.CPlusPlus;
}
@ -86,10 +84,6 @@ ASTContext::~ASTContext() {
TUDecl->Destroy(*this);
}
void ASTContext::InitializeBuiltins(IdentifierTable &idents) {
BuiltinInfo.InitializeBuiltins(idents, LangOpts.NoBuiltin);
}
void
ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) {
ExternalSource.reset(Source.take());
@ -1979,9 +1973,8 @@ unsigned ASTContext::getIntegerRank(Type *T) {
// There are two things which impact the integer rank: the width, and
// the ordering of builtins. The builtin ordering is encoded in the
// bottom three bits; the width is encoded in the bits above that.
if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) {
if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T))
return FWIT->getWidth() << 3;
}
switch (cast<BuiltinType>(T)->getKind()) {
default: assert(0 && "getIntegerRank(): not a built-in integer");
@ -3375,3 +3368,203 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
ExternalASTSource::~ExternalASTSource() { }
void ExternalASTSource::PrintStats() { }
//===----------------------------------------------------------------------===//
// Builtin Type Computation
//===----------------------------------------------------------------------===//
/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
/// pointer over the consumed characters. This returns the resultant type.
static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
ASTContext::GetBuiltinTypeError &Error,
bool AllowTypeModifiers = true) {
// Modifiers.
int HowLong = 0;
bool Signed = false, Unsigned = false;
// Read the modifiers first.
bool Done = false;
while (!Done) {
switch (*Str++) {
default: Done = true; --Str; break;
case 'S':
assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
assert(!Signed && "Can't use 'S' modifier multiple times!");
Signed = true;
break;
case 'U':
assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
assert(!Unsigned && "Can't use 'S' modifier multiple times!");
Unsigned = true;
break;
case 'L':
assert(HowLong <= 2 && "Can't have LLLL modifier");
++HowLong;
break;
}
}
QualType Type;
// Read the base type.
switch (*Str++) {
default: assert(0 && "Unknown builtin type letter!");
case 'v':
assert(HowLong == 0 && !Signed && !Unsigned &&
"Bad modifiers used with 'v'!");
Type = Context.VoidTy;
break;
case 'f':
assert(HowLong == 0 && !Signed && !Unsigned &&
"Bad modifiers used with 'f'!");
Type = Context.FloatTy;
break;
case 'd':
assert(HowLong < 2 && !Signed && !Unsigned &&
"Bad modifiers used with 'd'!");
if (HowLong)
Type = Context.LongDoubleTy;
else
Type = Context.DoubleTy;
break;
case 's':
assert(HowLong == 0 && "Bad modifiers used with 's'!");
if (Unsigned)
Type = Context.UnsignedShortTy;
else
Type = Context.ShortTy;
break;
case 'i':
if (HowLong == 3)
Type = Unsigned ? Context.UnsignedInt128Ty : Context.Int128Ty;
else if (HowLong == 2)
Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
else if (HowLong == 1)
Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
else
Type = Unsigned ? Context.UnsignedIntTy : Context.IntTy;
break;
case 'c':
assert(HowLong == 0 && "Bad modifiers used with 'c'!");
if (Signed)
Type = Context.SignedCharTy;
else if (Unsigned)
Type = Context.UnsignedCharTy;
else
Type = Context.CharTy;
break;
case 'b': // boolean
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
Type = Context.BoolTy;
break;
case 'z': // size_t.
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
Type = Context.getSizeType();
break;
case 'F':
Type = Context.getCFConstantStringType();
break;
case 'a':
Type = Context.getBuiltinVaListType();
assert(!Type.isNull() && "builtin va list type not initialized!");
break;
case 'A':
// This is a "reference" to a va_list; however, what exactly
// this means depends on how va_list is defined. There are two
// different kinds of va_list: ones passed by value, and ones
// passed by reference. An example of a by-value va_list is
// x86, where va_list is a char*. An example of by-ref va_list
// is x86-64, where va_list is a __va_list_tag[1]. For x86,
// we want this argument to be a char*&; for x86-64, we want
// it to be a __va_list_tag*.
Type = Context.getBuiltinVaListType();
assert(!Type.isNull() && "builtin va list type not initialized!");
if (Type->isArrayType()) {
Type = Context.getArrayDecayedType(Type);
} else {
Type = Context.getLValueReferenceType(Type);
}
break;
case 'V': {
char *End;
unsigned NumElements = strtoul(Str, &End, 10);
assert(End != Str && "Missing vector size");
Str = End;
QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false);
Type = Context.getVectorType(ElementType, NumElements);
break;
}
case 'P': {
IdentifierInfo *II = &Context.Idents.get("FILE");
DeclContext::lookup_result Lookup
= Context.getTranslationUnitDecl()->lookup(Context, II);
if (Lookup.first != Lookup.second && isa<TypeDecl>(*Lookup.first)) {
Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first));
break;
}
else {
Error = ASTContext::GE_Missing_FILE;
return QualType();
}
}
}
if (!AllowTypeModifiers)
return Type;
Done = false;
while (!Done) {
switch (*Str++) {
default: Done = true; --Str; break;
case '*':
Type = Context.getPointerType(Type);
break;
case '&':
Type = Context.getLValueReferenceType(Type);
break;
// FIXME: There's no way to have a built-in with an rvalue ref arg.
case 'C':
Type = Type.getQualifiedType(QualType::Const);
break;
}
}
return Type;
}
/// GetBuiltinType - Return the type for the specified builtin.
QualType ASTContext::GetBuiltinType(unsigned id,
GetBuiltinTypeError &Error) {
const char *TypeStr = BuiltinInfo.GetTypeString(id);
llvm::SmallVector<QualType, 8> ArgTypes;
Error = GE_None;
QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error);
if (Error != GE_None)
return QualType();
while (TypeStr[0] && TypeStr[0] != '.') {
QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error);
if (Error != GE_None)
return QualType();
// Do array -> pointer decay. The builtin should use the decayed type.
if (Ty->isArrayType())
Ty = getArrayDecayedType(Ty);
ArgTypes.push_back(Ty);
}
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
"'.' should only occur at end of builtin type list!");
// handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
if (ArgTypes.size() == 0 && TypeStr[0] == '.')
return getFunctionNoProtoType(ResType);
return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(),
TypeStr[0] == '.', 0);
}

View File

@ -1,290 +0,0 @@
//===--- Builtins.cpp - Builtin function implementation -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements various things for builtin functions.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Builtins.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
static const Builtin::Info BuiltinInfo[] = {
{ "not a builtin function", 0, 0, 0, false },
#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
#include "clang/AST/Builtins.def"
};
const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
if (ID < Builtin::FirstTSBuiltin)
return BuiltinInfo[ID];
assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
return TSRecords[ID - Builtin::FirstTSBuiltin];
}
/// \brief Load all of the target builtins. This must be called
/// prior to initializing the builtin identifiers.
void Builtin::Context::InitializeTargetBuiltins(const TargetInfo &Target) {
Target.getTargetBuiltins(TSRecords, NumTSRecords);
}
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
bool NoBuiltins) {
// Step #1: mark all target-independent builtins with their ID's.
for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
if (!BuiltinInfo[i].Suppressed &&
(!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
// Step #2: Register target-specific builtins.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&
(!NoBuiltins ||
(TSRecords[i].Attributes &&
!strchr(TSRecords[i].Attributes, 'f'))))
Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
}
void
Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
bool NoBuiltins) {
// Final all target-independent names
for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
if (!BuiltinInfo[i].Suppressed &&
(!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
Names.push_back(BuiltinInfo[i].Name);
// Find target-specific names.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&
(!NoBuiltins ||
(TSRecords[i].Attributes &&
!strchr(TSRecords[i].Attributes, 'f'))))
Names.push_back(TSRecords[i].Name);
}
bool
Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
bool &HasVAListArg) {
const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP");
if (!Printf)
return false;
HasVAListArg = (*Printf == 'P');
++Printf;
assert(*Printf == ':' && "p or P specifier must have be followed by a ':'");
++Printf;
assert(strchr(Printf, ':') && "printf specifier must end with a ':'");
FormatIdx = strtol(Printf, 0, 10);
return true;
}
/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
/// pointer over the consumed characters. This returns the resultant type.
static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
Builtin::Context::GetBuiltinTypeError &Error,
bool AllowTypeModifiers = true) {
// Modifiers.
int HowLong = 0;
bool Signed = false, Unsigned = false;
// Read the modifiers first.
bool Done = false;
while (!Done) {
switch (*Str++) {
default: Done = true; --Str; break;
case 'S':
assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
assert(!Signed && "Can't use 'S' modifier multiple times!");
Signed = true;
break;
case 'U':
assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
assert(!Unsigned && "Can't use 'S' modifier multiple times!");
Unsigned = true;
break;
case 'L':
assert(HowLong <= 2 && "Can't have LLLL modifier");
++HowLong;
break;
}
}
QualType Type;
// Read the base type.
switch (*Str++) {
default: assert(0 && "Unknown builtin type letter!");
case 'v':
assert(HowLong == 0 && !Signed && !Unsigned &&
"Bad modifiers used with 'v'!");
Type = Context.VoidTy;
break;
case 'f':
assert(HowLong == 0 && !Signed && !Unsigned &&
"Bad modifiers used with 'f'!");
Type = Context.FloatTy;
break;
case 'd':
assert(HowLong < 2 && !Signed && !Unsigned &&
"Bad modifiers used with 'd'!");
if (HowLong)
Type = Context.LongDoubleTy;
else
Type = Context.DoubleTy;
break;
case 's':
assert(HowLong == 0 && "Bad modifiers used with 's'!");
if (Unsigned)
Type = Context.UnsignedShortTy;
else
Type = Context.ShortTy;
break;
case 'i':
if (HowLong == 3)
Type = Unsigned ? Context.UnsignedInt128Ty : Context.Int128Ty;
else if (HowLong == 2)
Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
else if (HowLong == 1)
Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
else
Type = Unsigned ? Context.UnsignedIntTy : Context.IntTy;
break;
case 'c':
assert(HowLong == 0 && "Bad modifiers used with 'c'!");
if (Signed)
Type = Context.SignedCharTy;
else if (Unsigned)
Type = Context.UnsignedCharTy;
else
Type = Context.CharTy;
break;
case 'b': // boolean
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
Type = Context.BoolTy;
break;
case 'z': // size_t.
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
Type = Context.getSizeType();
break;
case 'F':
Type = Context.getCFConstantStringType();
break;
case 'a':
Type = Context.getBuiltinVaListType();
assert(!Type.isNull() && "builtin va list type not initialized!");
break;
case 'A':
// This is a "reference" to a va_list; however, what exactly
// this means depends on how va_list is defined. There are two
// different kinds of va_list: ones passed by value, and ones
// passed by reference. An example of a by-value va_list is
// x86, where va_list is a char*. An example of by-ref va_list
// is x86-64, where va_list is a __va_list_tag[1]. For x86,
// we want this argument to be a char*&; for x86-64, we want
// it to be a __va_list_tag*.
Type = Context.getBuiltinVaListType();
assert(!Type.isNull() && "builtin va list type not initialized!");
if (Type->isArrayType()) {
Type = Context.getArrayDecayedType(Type);
} else {
Type = Context.getLValueReferenceType(Type);
}
break;
case 'V': {
char *End;
unsigned NumElements = strtoul(Str, &End, 10);
assert(End != Str && "Missing vector size");
Str = End;
QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false);
Type = Context.getVectorType(ElementType, NumElements);
break;
}
case 'P': {
IdentifierInfo *II = &Context.Idents.get("FILE");
DeclContext::lookup_result Lookup
= Context.getTranslationUnitDecl()->lookup(Context, II);
if (Lookup.first != Lookup.second && isa<TypeDecl>(*Lookup.first)) {
Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first));
break;
}
else {
Error = Builtin::Context::GE_Missing_FILE;
return QualType();
}
}
}
if (!AllowTypeModifiers)
return Type;
Done = false;
while (!Done) {
switch (*Str++) {
default: Done = true; --Str; break;
case '*':
Type = Context.getPointerType(Type);
break;
case '&':
Type = Context.getLValueReferenceType(Type);
break;
// FIXME: There's no way to have a built-in with an rvalue ref arg.
case 'C':
Type = Type.getQualifiedType(QualType::Const);
break;
}
}
return Type;
}
/// GetBuiltinType - Return the type for the specified builtin.
QualType Builtin::Context::GetBuiltinType(unsigned id, ASTContext &Context,
GetBuiltinTypeError &Error) const {
const char *TypeStr = GetRecord(id).Type;
llvm::SmallVector<QualType, 8> ArgTypes;
Error = GE_None;
QualType ResType = DecodeTypeFromStr(TypeStr, Context, Error);
if (Error != GE_None)
return QualType();
while (TypeStr[0] && TypeStr[0] != '.') {
QualType Ty = DecodeTypeFromStr(TypeStr, Context, Error);
if (Error != GE_None)
return QualType();
// Do array -> pointer decay. The builtin should use the decayed type.
if (Ty->isArrayType())
Ty = Context.getArrayDecayedType(Ty);
ArgTypes.push_back(Ty);
}
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
"'.' should only occur at end of builtin type list!");
// handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
if (ArgTypes.size() == 0 && TypeStr[0] == '.')
return Context.getFunctionNoProtoType(ResType);
return Context.getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(),
TypeStr[0] == '.', 0);
}

View File

@ -4,7 +4,6 @@ add_clang_library(clangAST
APValue.cpp
ASTConsumer.cpp
ASTContext.cpp
Builtins.cpp
CFG.cpp
DeclarationName.cpp
DeclBase.cpp

View File

@ -19,6 +19,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/Expr.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include <vector>

View File

@ -95,6 +95,13 @@ void Decl::addDeclKind(Kind k) {
}
}
bool Decl::isTemplateParameterPack() const {
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
return TTP->isParameterPack();
return false;
}
//===----------------------------------------------------------------------===//
// PrettyStackTraceDecl Implementation
//===----------------------------------------------------------------------===//

View File

@ -260,7 +260,12 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
// the type of this is const volatile X*.
assert(isInstance() && "No 'this' for static methods!");
QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
QualType ClassTy;
if (ClassTemplateDecl *TD = getParent()->getDescribedClassTemplate())
ClassTy = TD->getInjectedClassNameType(C);
else
ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
return C.getPointerType(ClassTy).withConst();
}

View File

@ -527,6 +527,9 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) {
else
Out << "class ";
if (TTP->isParameterPack())
Out << "... ";
Out << ParamType.getAsString(Policy);
if (TTP->hasDefaultArgument()) {

View File

@ -50,7 +50,9 @@ unsigned TemplateParameterList::getMinRequiredArguments() const {
ParamBegin = const_cast<TemplateParameterList *>(this)->begin();
while (Param != ParamBegin) {
--Param;
if (!(isa<TemplateTypeParmDecl>(*Param) &&
if (!(*Param)->isTemplateParameterPack() &&
!(isa<TemplateTypeParmDecl>(*Param) &&
cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) &&
!(isa<NonTypeTemplateParmDecl>(*Param) &&
cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) &&
@ -186,9 +188,10 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
TemplateTypeParmDecl *
TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename) {
IdentifierInfo *Id, bool Typename,
bool ParameterPack) {
QualType Type = C.getTemplateTypeParmType(D, P, Id);
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type);
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
}
//===----------------------------------------------------------------------===//
@ -246,9 +249,27 @@ void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) {
break;
}
if (!isAddingFromParameterPack()) {
// Add begin and end indicies.
Indices.push_back(Args.size());
Indices.push_back(Args.size());
}
Args.push_back(Arg);
}
void TemplateArgumentListBuilder::BeginParameterPack() {
assert(!isAddingFromParameterPack() && "Already adding to parameter pack!");
Indices.push_back(Args.size());
}
void TemplateArgumentListBuilder::EndParameterPack() {
assert(isAddingFromParameterPack() && "Not adding to parameter pack!");
Indices.push_back(Args.size());
}
//===----------------------------------------------------------------------===//
// TemplateArgumentList Implementation
//===----------------------------------------------------------------------===//

View File

@ -19,6 +19,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
#include <algorithm>
using namespace clang;

View File

@ -16,6 +16,7 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Compiler.h"
@ -61,6 +62,13 @@ static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
// Misc utilities
//===----------------------------------------------------------------------===//
static bool EvalPointerValueAsBool(APValue& Value, bool& Result) {
// FIXME: Is this accurate for all kinds of bases? If not, what would
// the check look like?
Result = Value.getLValueBase() || Value.getLValueOffset();
return true;
}
static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
if (E->getType()->isIntegralType()) {
APSInt IntResult;
@ -78,10 +86,7 @@ static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
APValue PointerResult;
if (!EvaluatePointer(E, PointerResult, Info))
return false;
// FIXME: Is this accurate for all kinds of bases? If not, what would
// the check look like?
Result = PointerResult.getLValueBase() || PointerResult.getLValueOffset();
return true;
return EvalPointerValueAsBool(PointerResult, Result);
} else if (E->getType()->isAnyComplexType()) {
APValue ComplexResult;
if (!EvaluateComplex(E, ComplexResult, Info))
@ -936,10 +941,27 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (!EvaluatePointer(E->getRHS(), RHSValue, Info))
return false;
// Reject any bases; this is conservative, but good enough for
// common uses
if (LHSValue.getLValueBase() || RHSValue.getLValueBase())
return false;
// Reject any bases from the normal codepath; we special-case comparisons
// to null.
if (LHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
if (RHSValue.getLValueBase() || RHSValue.getLValueOffset())
return false;
bool bres;
if (!EvalPointerValueAsBool(LHSValue, bres))
return false;
return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E);
} else if (RHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
if (LHSValue.getLValueBase() || LHSValue.getLValueOffset())
return false;
bool bres;
if (!EvalPointerValueAsBool(RHSValue, bres))
return false;
return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E);
}
if (E->getOpcode() == BinaryOperator::Sub) {
const QualType Type = E->getLHS()->getType();

View File

@ -637,10 +637,10 @@ class VISIBILITY_HIDDEN RetainSummaryManager {
/// objects.
RetEffect ObjCAllocRetE;
/// ObjCInitRetE - Default return effect for init methods returning Objective-C
/// ObjCInitRetE - Default return effect for init methods returning Objective-C
/// objects.
RetEffect ObjCInitRetE;
RetainSummary DefaultSummary;
RetainSummary* StopSummary;
@ -780,8 +780,8 @@ public:
GCEnabled(gcenabled), AF(BPAlloc), ScratchArgs(AF.GetEmptyMap()),
ObjCAllocRetE(gcenabled ? RetEffect::MakeGCNotOwned()
: RetEffect::MakeOwned(RetEffect::ObjC, true)),
ObjCInitRetE(gcenabled ? RetEffect::MakeGCNotOwned()
: RetEffect::MakeOwnedWhenTrackedReceiver()),
ObjCInitRetE(gcenabled ? RetEffect::MakeGCNotOwned()
: RetEffect::MakeOwnedWhenTrackedReceiver()),
DefaultSummary(AF.GetEmptyMap() /* per-argument effects (none) */,
RetEffect::MakeNoRet() /* return effect */,
MayEscape, /* default argument effect */
@ -971,15 +971,42 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// FIXME: This should all be refactored into a chain of "summary lookup"
// filters.
if (strcmp(FName, "IOServiceGetMatchingServices") == 0) {
// FIXES: <rdar://problem/6326900>
// This should be addressed using a API table. This strcmp is also
// a little gross, but there is no need to super optimize here.
assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
break;
switch (strlen(FName)) {
default: break;
case 17:
// Handle: id NSMakeCollectable(CFTypeRef)
if (!memcmp(FName, "NSMakeCollectable", 17)) {
S = (RetTy == Ctx.getObjCIdType())
? getUnarySummary(FT, cfmakecollectable)
: getPersistentStopSummary();
}
break;
case 27:
if (!memcmp(FName, "IOServiceGetMatchingService", 27)) {
// Part of <rdar://problem/6961230>.
// This should be addressed using a API table.
assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
case 28:
if (!memcmp(FName, "IOServiceGetMatchingServices", 28)) {
// FIXES: <rdar://problem/6326900>
// This should be addressed using a API table. This strcmp is also
// a little gross, but there is no need to super optimize here.
assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
}
// Did we get a summary?
if (S)
break;
// Enable this code once the semantics of NSDeallocateObject are resolved
// for GC. <rdar://problem/6619988>
@ -992,15 +1019,6 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
: getPersistentStopSummary();
}
#endif
// Handle: id NSMakeCollectable(CFTypeRef)
if (strcmp(FName, "NSMakeCollectable") == 0) {
S = (RetTy == Ctx.getObjCIdType())
? getUnarySummary(FT, cfmakecollectable)
: getPersistentStopSummary();
break;
}
if (RetTy->isPointerType()) {
// For CoreFoundation ('CF') types.
@ -1173,19 +1191,19 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
if (!FD)
return;
QualType RetTy = FD->getResultType();
QualType RetTy = FD->getResultType();
// Determine if there is a special return effect for this method.
if (isTrackedObjCObjectType(RetTy)) {
if (FD->getAttr<NSReturnsRetainedAttr>()) {
Summ.setRetEffect(ObjCAllocRetE);
}
else if (FD->getAttr<CFReturnsRetainedAttr>()) {
else if (FD->getAttr<CFReturnsRetainedAttr>()) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
else if (RetTy->getAsPointerType()) {
if (FD->getAttr<CFReturnsRetainedAttr>()) {
}
}
else if (RetTy->getAsPointerType()) {
if (FD->getAttr<CFReturnsRetainedAttr>()) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
@ -1379,7 +1397,7 @@ void RetainSummaryManager::InitializeMethodSummaries() {
// Create the "init" selector. It just acts as a pass-through for the
// receiver.
addNSObjectMethSummary(GetNullarySelector("init", Ctx),
getPersistentSummary(ObjCInitRetE, DecRefMsg));
getPersistentSummary(ObjCInitRetE, DecRefMsg));
// The next methods are allocators.
RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);

View File

@ -18,6 +18,7 @@
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/PrettyStackTrace.h"

View File

@ -651,7 +651,7 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
// Get symbol's type. It should be a pointer type.
SymbolRef Sym = SR->getSymbol();
QualType T = Sym->getType(getContext());
QualType EleTy = cast<PointerType>(T.getTypePtr())->getPointeeType();
QualType EleTy = T->getAsPointerType()->getPointeeType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR);
@ -840,7 +840,7 @@ SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){
QualType T = R->getValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
const RecordType* RT = T->getAsStructureType();
RecordDecl* RD = RT->getDecl();
assert(RD->isDefinition());
@ -1198,6 +1198,11 @@ RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R, SVal V){
if (V.isUnknown())
return KillStruct(St, R);
// We may get non-CompoundVal accidentally due to imprecise cast logic. Ignore
// them and make struct unknown.
if (!isa<nonloc::CompoundVal>(V))
return KillStruct(St, R);
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
RecordDecl::field_iterator FI = RD->field_begin(getContext()),

92
lib/Basic/Builtins.cpp Normal file
View File

@ -0,0 +1,92 @@
//===--- Builtins.cpp - Builtin function implementation -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements various things for builtin functions.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
static const Builtin::Info BuiltinInfo[] = {
{ "not a builtin function", 0, 0, 0, false },
#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
#include "clang/Basic/Builtins.def"
};
const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
if (ID < Builtin::FirstTSBuiltin)
return BuiltinInfo[ID];
assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
return TSRecords[ID - Builtin::FirstTSBuiltin];
}
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
const TargetInfo &Target,
bool NoBuiltins) {
// Step #1: mark all target-independent builtins with their ID's.
for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
if (!BuiltinInfo[i].Suppressed &&
(!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
// Get the target specific builtins from the target.
Target.getTargetBuiltins(TSRecords, NumTSRecords);
// Step #2: Register target-specific builtins.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&
(!NoBuiltins ||
(TSRecords[i].Attributes &&
!strchr(TSRecords[i].Attributes, 'f'))))
Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
}
void
Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
bool NoBuiltins) {
// Final all target-independent names
for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
if (!BuiltinInfo[i].Suppressed &&
(!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
Names.push_back(BuiltinInfo[i].Name);
// Find target-specific names.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&
(!NoBuiltins ||
(TSRecords[i].Attributes &&
!strchr(TSRecords[i].Attributes, 'f'))))
Names.push_back(TSRecords[i].Name);
}
bool
Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
bool &HasVAListArg) {
const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP");
if (!Printf)
return false;
HasVAListArg = (*Printf == 'P');
++Printf;
assert(*Printf == ':' && "p or P specifier must have be followed by a ':'");
++Printf;
assert(strchr(Printf, ':') && "printf specifier must end with a ':'");
FormatIdx = strtol(Printf, 0, 10);
return true;
}

View File

@ -1,6 +1,7 @@
set(LLVM_NO_RTTI 1)
add_clang_library(clangBasic
Builtins.cpp
ConvertUTF.c
Diagnostic.cpp
FileManager.cpp

View File

@ -46,6 +46,7 @@ struct StaticDiagInfoRec {
unsigned short DiagID;
unsigned Mapping : 3;
unsigned Class : 3;
bool SFINAE : 1;
const char *Description;
const char *OptionGroup;
@ -58,8 +59,8 @@ struct StaticDiagInfoRec {
};
static const StaticDiagInfoRec StaticDiagInfo[] = {
#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP) \
{ diag::ENUM, DEFAULT_MAPPING, CLASS, DESC, GROUP },
#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) \
{ diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, DESC, GROUP },
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
@ -68,7 +69,7 @@ static const StaticDiagInfoRec StaticDiagInfo[] = {
#include "clang/Basic/DiagnosticASTKinds.inc"
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
{ 0, 0, 0, 0, 0 }
{ 0, 0, 0, 0, 0, 0}
};
#undef DIAG
@ -89,7 +90,7 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
#endif
// Search the diagnostic table with a binary search.
StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0 };
StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0 };
const StaticDiagInfoRec *Found =
std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
@ -115,6 +116,12 @@ const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
return 0;
}
bool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->SFINAE && Info->Class != CLASS_NOTE;
return false;
}
/// getDiagClass - Return the class field of the diagnostic.
///
static unsigned getBuiltinDiagClass(unsigned DiagID) {
@ -399,7 +406,7 @@ bool Diagnostic::setDiagnosticGroupMapping(const char *Group,
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
void Diagnostic::ProcessDiag() {
bool Diagnostic::ProcessDiag() {
DiagnosticInfo Info(this);
// Figure out the diagnostic level of this message.
@ -449,13 +456,13 @@ void Diagnostic::ProcessDiag() {
// If a fatal error has already been emitted, silence all subsequent
// diagnostics.
if (FatalErrorOccurred)
return;
return false;
// If the client doesn't care about this message, don't issue it. If this is
// a note and the last real diagnostic was ignored, ignore it too.
if (DiagLevel == Diagnostic::Ignored ||
(DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored))
return;
return false;
// If this diagnostic is in a system header and is not a clang error, suppress
// it.
@ -464,7 +471,7 @@ void Diagnostic::ProcessDiag() {
Info.getLocation().getSpellingLoc().isInSystemHeader() &&
(DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) {
LastDiagLevel = Diagnostic::Ignored;
return;
return false;
}
if (DiagLevel >= Diagnostic::Error) {
@ -477,6 +484,8 @@ void Diagnostic::ProcessDiag() {
if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics;
CurDiagID = ~0U;
return true;
}

View File

@ -12,9 +12,8 @@
//
//===----------------------------------------------------------------------===//
// FIXME: Layering violation
#include "clang/AST/Builtins.h"
#include "clang/AST/TargetBuiltins.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
@ -315,7 +314,7 @@ public:
const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
#include "clang/AST/PPCBuiltins.def"
#include "clang/Basic/BuiltinsPPC.def"
};
@ -489,7 +488,7 @@ namespace {
const Builtin::Info BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
#include "clang/AST/X86Builtins.def"
#include "clang/Basic/BuiltinsX86.def"
};
const char *GCCRegNames[] = {
@ -767,6 +766,7 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
// x86_64 instructions.
case 'N': // unsigned 8-bit integer constant for use with in and out
// instructions.
case 'R': // "legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
Info.setAllowsRegister();
return true;
}
@ -931,6 +931,10 @@ public:
TLSSupported = false;
WCharType = SignedShort;
WCharWidth = WCharAlign = 16;
DoubleAlign = LongLongAlign = 64;
DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
"a0:0:64-f80:32:32";
}
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const {
@ -965,7 +969,7 @@ public:
DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
"a0:0:64-f80:128:128";
"a0:0:64-s0:64:64-f80:128:128";
}
virtual const char *getVAListDeclaration() const {
return "typedef struct __va_list_tag {"

View File

@ -17,7 +17,7 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/TargetBuiltins.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/Intrinsics.h"
using namespace clang;
using namespace CodeGen;

View File

@ -682,10 +682,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// location that we would like to return into.
QualType RetTy = CallInfo.getReturnType();
const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
if (CGM.ReturnTypeUsesSret(CallInfo)) {
// Create a temporary alloca to hold the result of the call. :(
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result.
if (CGM.ReturnTypeUsesSret(CallInfo))
Args.push_back(CreateTempAlloca(ConvertTypeForMem(RetTy)));
}
assert(CallInfo.arg_size() == CallArgs.size() &&
"Mismatch between function signature & arguments.");
@ -747,6 +749,35 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
break;
}
}
// If the callee is a bitcast of a function to a varargs pointer to function
// type, check to see if we can remove the bitcast. This handles some cases
// with unprototyped functions.
if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee))
if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) {
const llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType());
const llvm::FunctionType *CurFT =
cast<llvm::FunctionType>(CurPT->getElementType());
const llvm::FunctionType *ActualFT = CalleeF->getFunctionType();
if (CE->getOpcode() == llvm::Instruction::BitCast &&
ActualFT->getReturnType() == CurFT->getReturnType() &&
ActualFT->getNumParams() == CurFT->getNumParams()) {
bool ArgsMatch = true;
for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i)
if (ActualFT->getParamType(i) != CurFT->getParamType(i)) {
ArgsMatch = false;
break;
}
// Strip the cast if we can get away with it. This is a nice cleanup,
// but also allows us to inline the function at -O0 if it is marked
// always_inline.
if (ArgsMatch)
Callee = CalleeF;
}
}
llvm::BasicBlock *InvokeDest = getInvokeDest();
CodeGen::AttributeListType AttributeList;
@ -765,7 +796,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
CS.setAttributes(Attrs);
if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee->stripPointerCasts()))
if (const llvm::Function *F =
dyn_cast<llvm::Function>(Callee->stripPointerCasts()))
CS.setCallingConv(F->getCallingConv());
// If the call doesn't return, finish the basic block and clear the

View File

@ -1156,10 +1156,9 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) {
}
}
if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E)) {
if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E))
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl))
return EmitCXXOperatorMemberCallExpr(CE, MD);
}
llvm::Value *Callee = EmitScalarExpr(E->getCallee());
return EmitCall(Callee, E->getCallee()->getType(),

View File

@ -77,7 +77,14 @@ public:
/// and returns the result.
ComplexPairTy EmitLoadOfLValue(const Expr *E) {
LValue LV = CGF.EmitLValue(E);
return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
if (LV.isSimple())
return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
if (LV.isPropertyRef())
return CGF.EmitObjCPropertyGet(LV.getPropertyRefExpr()).getComplexVal();
assert(LV.isKVCRef() && "Unknown LValue type!");
return CGF.EmitObjCPropertyGet(LV.getKVCRefExpr()).getComplexVal();
}
/// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load
@ -107,6 +114,18 @@ public:
// l-values.
ComplexPairTy VisitDeclRefExpr(const Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
return EmitLoadOfLValue(E);
}
ComplexPairTy VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
return EmitLoadOfLValue(E);
}
ComplexPairTy VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) {
return EmitLoadOfLValue(E);
}
ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) {
return CGF.EmitObjCMessageExpr(E).getComplexVal();
}
ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
@ -522,15 +541,32 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
// Compute the address to store into.
LValue LHS = CGF.EmitLValue(E->getLHS());
// Store into it, if simple.
if (LHS.isSimple()) {
EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified());
// And now return the LHS
IgnoreReal = ignreal;
IgnoreImag = ignimag;
IgnoreRealAssign = ignreal;
IgnoreImagAssign = ignimag;
return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified());
}
// Store into it.
EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified());
// And now return the LHS
// Otherwise we must have a property setter (no complex vector/bitfields).
if (LHS.isPropertyRef())
CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), RValue::getComplex(Val));
else
CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), RValue::getComplex(Val));
// There is no reload after a store through a method, but we need to restore
// the Ignore* flags.
IgnoreReal = ignreal;
IgnoreImag = ignimag;
IgnoreRealAssign = ignreal;
IgnoreImagAssign = ignimag;
return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified());
return Val;
}
ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {

View File

@ -17,6 +17,7 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"

View File

@ -1508,6 +1508,8 @@ CodeGen::RValue CGObjCCommonMac::EmitLegacyMessageSend(
BuiltinType::Kind k = BT->getKind();
Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper)
: ObjCTypes.getSendFn2(IsSuper);
} else {
Fn = ObjCTypes.getSendFn2(IsSuper);
}
}
else

View File

@ -21,6 +21,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@ -1107,9 +1108,9 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) {
Name += 10;
// Get the type for the builtin.
Builtin::Context::GetBuiltinTypeError Error;
QualType Type = Context.BuiltinInfo.GetBuiltinType(BuiltinID, Context, Error);
assert(Error == Builtin::Context::GE_None && "Can't get builtin type");
ASTContext::GetBuiltinTypeError Error;
QualType Type = Context.GetBuiltinType(BuiltinID, Error);
assert(Error == ASTContext::GE_None && "Can't get builtin type");
const llvm::FunctionType *Ty =
cast<llvm::FunctionType>(getTypes().ConvertType(Type));
@ -1481,7 +1482,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::CXXDestructor:
EmitCXXDestructors(cast<CXXDestructorDecl>(D));
break;
case Decl::StaticAssert:
// Nothing to do.
break;
// Objective-C Decls
// Forward declarations, no (immediate) code generation.

View File

@ -87,19 +87,20 @@ static bool isInCLinkageSpecification(const Decl *D) {
bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
// Clang's "overloadable" attribute extension to C/C++ implies
// name mangling (always).
if (FD->hasAttr<OverloadableAttr>()) {
; // fall into mangling code unconditionally.
} else if (// C functions are not mangled
!Context.getLangOptions().CPlusPlus ||
// "main" is not mangled in C++
FD->isMain() ||
// No mangling in an "implicit extern C" header.
(FD->getLocation().isValid() &&
Context.getSourceManager().getFileCharacteristic(FD->getLocation()))
== SrcMgr::C_ExternCSystem ||
// No name mangling in a C linkage specification.
isInCLinkageSpecification(FD))
return false;
if (!FD->hasAttr<OverloadableAttr>()) {
// C functions are not mangled, and "main" is never mangled.
if (!Context.getLangOptions().CPlusPlus || FD->isMain())
return false;
// No mangling in an "implicit extern C" header.
if (FD->getLocation().isValid() &&
Context.getSourceManager().isInExternCSystemHeader(FD->getLocation()))
return false;
// No name mangling in a C linkage specification.
if (isInCLinkageSpecification(FD))
return false;
}
// If we get here, mangle the decl name!
Out << "_Z";

View File

@ -159,6 +159,23 @@ static bool areAllFields32Or64BitBasicType(const RecordDecl *RD,
return true;
}
static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) {
for (RecordDecl::field_iterator i = RD->field_begin(Context),
e = RD->field_end(Context); i != e; ++i) {
const FieldDecl *FD = *i;
if (FD->getType()->isVectorType() &&
Context.getTypeSize(FD->getType()) >= 128)
return true;
if (const RecordType* RT = FD->getType()->getAsRecordType())
if (typeContainsSSEVector(RT->getDecl(), Context))
return true;
}
return false;
}
namespace {
/// DefaultABIInfo - The default implementation for ABI specific
/// details. This implementation provides information which results in
@ -193,6 +210,9 @@ class X86_32ABIInfo : public ABIInfo {
static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context);
static unsigned getIndirectArgumentAlignment(QualType Ty,
ASTContext &Context);
public:
ABIArgInfo classifyReturnType(QualType RetTy,
ASTContext &Context) const;
@ -350,6 +370,16 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
}
}
unsigned X86_32ABIInfo::getIndirectArgumentAlignment(QualType Ty,
ASTContext &Context) {
unsigned Align = Context.getTypeAlign(Ty);
if (Align < 128) return 0;
if (const RecordType* RT = Ty->getAsRecordType())
if (typeContainsSSEVector(RT->getDecl(), Context))
return 16;
return 0;
}
ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
ASTContext &Context) const {
// FIXME: Set alignment on indirect arguments.
@ -357,11 +387,11 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
// Structures with flexible arrays are always indirect.
if (const RecordType *RT = Ty->getAsStructureType())
if (RT->getDecl()->hasFlexibleArrayMember())
return ABIArgInfo::getIndirect(0);
return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty,
Context));
// Ignore empty structs.
uint64_t Size = Context.getTypeSize(Ty);
if (Ty->isStructureType() && Size == 0)
if (Ty->isStructureType() && Context.getTypeSize(Ty) == 0)
return ABIArgInfo::getIgnore();
// Expand structs with size <= 128-bits which consist only of
@ -373,7 +403,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
return ABIArgInfo::getExpand();
}
return ABIArgInfo::getIndirect(0);
return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, Context));
} else {
return (Ty->isPromotableIntegerType() ?
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());

View File

@ -43,8 +43,17 @@ void Clang::AddPreprocessingOptions(const Driver &D,
ArgStringList &CmdArgs,
const InputInfo &Output,
const InputInfoList &Inputs) const {
// Handle dependency file generation.
Arg *A;
if ((A = Args.getLastArg(options::OPT_C)) ||
(A = Args.getLastArg(options::OPT_CC))) {
if (!Args.hasArg(options::OPT_E))
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-E";
A->render(Args, CmdArgs);
}
// Handle dependency file generation.
if ((A = Args.getLastArg(options::OPT_M)) ||
(A = Args.getLastArg(options::OPT_MM)) ||
(A = Args.getLastArg(options::OPT_MD)) ||
@ -550,8 +559,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_diagnostics_show_option))
CmdArgs.push_back("-fdiagnostics-show-option");
if (!Args.hasFlag(options::OPT_fcolor_diagnostics,
options::OPT_fno_color_diagnostics))
options::OPT_fno_color_diagnostics))
CmdArgs.push_back("-fno-color-diagnostics");
if (!Args.hasFlag(options::OPT_fshow_source_location,
options::OPT_fno_show_source_location))
CmdArgs.push_back("-fno-show-source-location");
// -fdollars-in-identifiers default varies depending on platform and
// language; only pass if specified.

View File

@ -272,9 +272,13 @@ void BackendConsumer::CreatePasses() {
llvm::Pass *InliningPass = 0;
switch (CompileOpts.Inlining) {
case CompileOptions::NoInlining: break;
case CompileOptions::NormalInlining:
InliningPass = createFunctionInliningPass(); // Inline small functions
case CompileOptions::NormalInlining: {
// Inline small functions
unsigned Threshold = (CompileOpts.OptimizeSize ||
CompileOpts.OptimizationLevel < 3) ? 50 : 200;
InliningPass = createFunctionInliningPass(Threshold);
break;
}
case CompileOptions::OnlyAlwaysInlining:
InliningPass = createAlwaysInlinerPass(); // Respect always_inline
break;

View File

@ -210,6 +210,7 @@ unsigned PCHStmtReader::VisitDoStmt(DoStmt *S) {
S->setBody(StmtStack.back());
S->setDoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
return 2;
}

View File

@ -23,7 +23,6 @@ using namespace clang;
namespace {
class PCHStmtWriter : public StmtVisitor<PCHStmtWriter, void> {
PCHWriter &Writer;
PCHWriter::RecordData &Record;
@ -197,6 +196,7 @@ void PCHStmtWriter::VisitDoStmt(DoStmt *S) {
Writer.WriteSubStmt(S->getBody());
Writer.AddSourceLocation(S->getDoLoc(), Record);
Writer.AddSourceLocation(S->getWhileLoc(), Record);
Writer.AddSourceLocation(S->getRParenLoc(), Record);
Code = pch::STMT_DO;
}

View File

@ -327,7 +327,9 @@ namespace {
return StmtEmpty();
}
virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
SourceLocation WhileLoc, ExprArg Cond){
SourceLocation WhileLoc,
SourceLocation LPLoc, ExprArg Cond,
SourceLocation RPLoc){
Out << __FUNCTION__ << "\n";
return StmtEmpty();
}
@ -701,7 +703,8 @@ namespace {
}
virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc) {
SourceLocation EqualLoc,
SourceLocation ArgLoc) {
Out << __FUNCTION__ << "\n";
}

View File

@ -898,7 +898,10 @@ do { \
(row3) = _mm_movelh_ps(tmp3, tmp1); \
} while (0)
/* Ugly hack for backwards-compatibility (compatible with gcc) */
#ifdef __SSE2__
#include <emmintrin.h>
#endif
#endif /* __SSE__ */

View File

@ -56,6 +56,10 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf,
PP.Diag(Loc, diag::ext_nonstandard_escape) << "e";
ResultChar = 27;
break;
case 'E':
PP.Diag(Loc, diag::ext_nonstandard_escape) << "E";
ResultChar = 27;
break;
case 'f':
ResultChar = 12;
break;
@ -135,7 +139,6 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf,
PP.Diag(Loc, diag::ext_nonstandard_escape)
<< std::string()+(char)ResultChar;
break;
// FALL THROUGH.
default:
if (isgraph(ThisTokBuf[0]))
PP.Diag(Loc, diag::ext_unknown_escape) << std::string()+(char)ResultChar;

View File

@ -36,14 +36,14 @@ void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) {
/// RegisterBuiltinMacro - Register the specified identifier in the identifier
/// table and mark it as a builtin macro to be expanded.
IdentifierInfo *Preprocessor::RegisterBuiltinMacro(const char *Name) {
static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){
// Get the identifier.
IdentifierInfo *Id = getIdentifierInfo(Name);
IdentifierInfo *Id = PP.getIdentifierInfo(Name);
// Mark it as being a macro that is builtin.
MacroInfo *MI = AllocateMacroInfo(SourceLocation());
MacroInfo *MI = PP.AllocateMacroInfo(SourceLocation());
MI->setIsBuiltinMacro();
setMacroInfo(Id, MI);
PP.setMacroInfo(Id, MI);
return Id;
}
@ -51,17 +51,21 @@ IdentifierInfo *Preprocessor::RegisterBuiltinMacro(const char *Name) {
/// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
/// identifier table.
void Preprocessor::RegisterBuiltinMacros() {
Ident__LINE__ = RegisterBuiltinMacro("__LINE__");
Ident__FILE__ = RegisterBuiltinMacro("__FILE__");
Ident__DATE__ = RegisterBuiltinMacro("__DATE__");
Ident__TIME__ = RegisterBuiltinMacro("__TIME__");
Ident__COUNTER__ = RegisterBuiltinMacro("__COUNTER__");
Ident_Pragma = RegisterBuiltinMacro("_Pragma");
Ident__LINE__ = RegisterBuiltinMacro(*this, "__LINE__");
Ident__FILE__ = RegisterBuiltinMacro(*this, "__FILE__");
Ident__DATE__ = RegisterBuiltinMacro(*this, "__DATE__");
Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__");
Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__");
Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma");
// GCC Extensions.
Ident__BASE_FILE__ = RegisterBuiltinMacro("__BASE_FILE__");
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__");
Ident__TIMESTAMP__ = RegisterBuiltinMacro("__TIMESTAMP__");
Ident__BASE_FILE__ = RegisterBuiltinMacro(*this, "__BASE_FILE__");
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__");
Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
// Clang Extensions.
Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
}
/// isTrivialSingleTokenExpansion - Return true if MI, which has a single token
@ -469,6 +473,34 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
TIMELoc = TmpTok.getLocation();
}
/// HasFeature - Return true if we recognize and implement the specified feature
/// specified by the identifier.
static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
const LangOptions &LangOpts = PP.getLangOptions();
switch (II->getLength()) {
default: return false;
case 6:
if (II->isStr("blocks")) return LangOpts.Blocks;
return false;
case 22:
if (II->isStr("attribute_overloadable")) return true;
return false;
case 25:
if (II->isStr("attribute_ext_vector_type")) return true;
return false;
case 27:
if (II->isStr("attribute_analyzer_noreturn")) return true;
return false;
case 29:
if (II->isStr("attribute_ns_returns_retained")) return true;
if (II->isStr("attribute_cf_returns_retained")) return true;
return false;
}
}
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
@ -599,6 +631,43 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
sprintf(TmpBuffer, "%u", CounterValue++);
Tok.setKind(tok::numeric_constant);
CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation());
} else if (II == Ident__has_feature ||
II == Ident__has_builtin) {
// The argument to these two builtins should be a parenthesized identifier.
SourceLocation StartLoc = Tok.getLocation();
bool IsValid = false;
IdentifierInfo *FeatureII = 0;
// Read the '('.
Lex(Tok);
if (Tok.is(tok::l_paren)) {
// Read the identifier
Lex(Tok);
if (Tok.is(tok::identifier)) {
FeatureII = Tok.getIdentifierInfo();
// Read the ')'.
Lex(Tok);
if (Tok.is(tok::r_paren))
IsValid = true;
}
}
bool Value = false;
if (!IsValid)
Diag(StartLoc, diag::err_feature_check_malformed);
else if (II == Ident__has_builtin) {
// Check for a builtin is trivial.
Value = FeatureII->getBuiltinID() != 0;
} else {
assert(II == Ident__has_feature && "Must be feature check");
Value = HasFeature(*this, FeatureII);
}
sprintf(TmpBuffer, "%d", (int)Value);
Tok.setKind(tok::numeric_constant);
CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation());
} else {
assert(0 && "Unknown identifier!");
}

View File

@ -209,17 +209,16 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
/// extended-decl-modifier[opt]
/// extended-decl-modifier extended-decl-modifier-seq
AttributeList* Parser::ParseMicrosoftDeclSpec() {
AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) {
assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
AttributeList *CurrAttr = 0;
ConsumeToken();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"declspec")) {
SkipUntil(tok::r_paren, true); // skip until ) or ;
return CurrAttr;
}
while (Tok.is(tok::identifier) || Tok.is(tok::kw_restrict)) {
while (Tok.getIdentifierInfo()) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
if (Tok.is(tok::l_paren)) {
@ -242,8 +241,24 @@ AttributeList* Parser::ParseMicrosoftDeclSpec() {
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
SkipUntil(tok::r_paren, false);
// FIXME: Return the attributes once we have some Sema support!
return 0;
return CurrAttr;
}
AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
// Treat these like attributes
// FIXME: Allow Sema to distinguish between these and real attributes!
while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___ptr64) ||
Tok.is(tok::kw___w64)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
// FIXME: Support these properly!
continue;
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
SourceLocation(), 0, 0, CurrAttr, true);
}
return CurrAttr;
}
/// ParseDeclaration - Parse a full 'declaration', which consists of
@ -839,22 +854,22 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Microsoft declspec support.
case tok::kw___declspec:
if (!PP.getLangOptions().Microsoft)
goto DoneWithDeclSpec;
DS.AddAttributes(ParseMicrosoftDeclSpec());
continue;
// Microsoft single token adornments.
case tok::kw___forceinline:
// FIXME: Add handling here!
break;
case tok::kw___ptr64:
case tok::kw___w64:
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
if (!PP.getLangOptions().Microsoft)
goto DoneWithDeclSpec;
// Just ignore it.
break;
DS.AddAttributes(ParseMicrosoftTypeAttributes());
continue;
// storage-class-specifier
case tok::kw_typedef:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec);
@ -1213,11 +1228,12 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid,
ParseTypeofSpecifier(DS);
return true;
case tok::kw___ptr64:
case tok::kw___w64:
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
if (!PP.getLangOptions().Microsoft) return false;
ConsumeToken();
DS.AddAttributes(ParseMicrosoftTypeAttributes());
return true;
default:
@ -1671,7 +1687,9 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
return PP.getLangOptions().Microsoft;
case tok::kw___w64:
case tok::kw___ptr64:
return true;
}
}
@ -1769,7 +1787,10 @@ bool Parser::isDeclarationSpecifier() {
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
return PP.getLangOptions().Microsoft;
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___forceinline:
return true;
}
}
@ -1800,14 +1821,16 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) {
isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
getLang())*2;
break;
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
if (!PP.getLangOptions().Microsoft)
goto DoneWithTypeQuals;
// Just ignore it.
break;
if (AttributesAllowed) {
DS.AddAttributes(ParseMicrosoftTypeAttributes());
continue;
}
goto DoneWithTypeQuals;
case tok::kw___attribute:
if (AttributesAllowed) {
DS.AddAttributes(ParseAttributes());
@ -2205,9 +2228,11 @@ void Parser::ParseParenDeclarator(Declarator &D) {
RequiresArg = true;
}
// Eat any Microsoft extensions.
while ((Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) ||
(Tok.is(tok::kw___fastcall))) && PP.getLangOptions().Microsoft)
ConsumeToken();
if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) ||
Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___w64) ||
Tok.is(tok::kw___ptr64)) {
AttrList = ParseMicrosoftTypeAttributes(AttrList);
}
// If we haven't past the identifier yet (or where the identifier would be
// stored, if this is an abstract declarator), then this is probably just
@ -2445,7 +2470,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
DefArgToks = 0;
Actions.ActOnParamDefaultArgumentError(Param);
} else
Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc);
Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
(*DefArgToks)[1].getLocation());
} else {
// Consume the '='.
ConsumeToken();

View File

@ -123,8 +123,8 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
// Eat the ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
"namespace name", tok::semi);
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
"", tok::semi);
return Actions.ActOnNamespaceAliasDef(CurScope, NamespaceLoc, AliasLoc, Alias,
SS, IdentLoc, Ident);
@ -232,8 +232,9 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
AttrList ? "attributes list" : "namespace name", tok::semi);
ExpectAndConsume(tok::semi,
AttrList ? diag::err_expected_semi_after_attribute_list :
diag::err_expected_semi_after_namespace_name, "", tok::semi);
return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS,
IdentLoc, NamespcName, AttrList);
@ -409,9 +410,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Attr = ParseAttributes();
// If declspecs exist after tag, parse them.
if (Tok.is(tok::kw___declspec) && PP.getLangOptions().Microsoft)
// FIXME: Need to do something with the attributes!
ParseMicrosoftDeclSpec();
if (Tok.is(tok::kw___declspec))
Attr = ParseMicrosoftDeclSpec(Attr);
// Parse the (optional) nested-name-specifier.
CXXScopeSpec SS;

View File

@ -749,7 +749,13 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Diag(Tok, diag::err_expected_expression);
return ExprError();
}
if (SavedKind == tok::kw_typename) {
// postfix-expression: typename-specifier '(' expression-list[opt] ')'
if (!TryAnnotateTypeOrScopeToken())
return ExprError();
}
// postfix-expression: simple-type-specifier '(' expression-list[opt] ')'
//
DeclSpec DS;

View File

@ -142,33 +142,33 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
return ParseWhileStatement();
case tok::kw_do: // C99 6.8.5.2: do-statement
Res = ParseDoStatement();
SemiError = "do/while loop";
SemiError = "do/while";
break;
case tok::kw_for: // C99 6.8.5.3: for-statement
return ParseForStatement();
case tok::kw_goto: // C99 6.8.6.1: goto-statement
Res = ParseGotoStatement();
SemiError = "goto statement";
SemiError = "goto";
break;
case tok::kw_continue: // C99 6.8.6.2: continue-statement
Res = ParseContinueStatement();
SemiError = "continue statement";
SemiError = "continue";
break;
case tok::kw_break: // C99 6.8.6.3: break-statement
Res = ParseBreakStatement();
SemiError = "break statement";
SemiError = "break";
break;
case tok::kw_return: // C99 6.8.6.4: return-statement
Res = ParseReturnStatement();
SemiError = "return statement";
SemiError = "return";
break;
case tok::kw_asm: {
bool msAsm = false;
Res = ParseAsmStatement(msAsm);
if (msAsm) return move(Res);
SemiError = "asm statement";
SemiError = "asm";
break;
}
@ -180,10 +180,14 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
if (Tok.is(tok::semi)) {
ConsumeToken();
} else if (!Res.isInvalid()) {
Diag(Tok, diag::err_expected_semi_after) << SemiError;
// If the result was valid, then we do want to diagnose this. Use
// ExpectAndConsume to emit the diagnostic, even though we know it won't
// succeed.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
// Skip until we see a } or ;, but don't eat it.
SkipUntil(tok::r_brace, true, true);
}
return move(Res);
}
@ -487,8 +491,11 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
/// successfully parsed. Note that a successful parse can still have semantic
/// errors in the condition.
bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp,
bool OnlyAllowCondition) {
bool OnlyAllowCondition,
SourceLocation *LParenLocPtr,
SourceLocation *RParenLocPtr) {
SourceLocation LParenLoc = ConsumeParen();
if (LParenLocPtr) *LParenLocPtr = LParenLoc;
if (getLang().CPlusPlus)
CondExp = ParseCXXCondition();
@ -507,7 +514,8 @@ bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp,
}
// Otherwise the condition is valid or the rparen is present.
MatchRHSPunctuation(tok::r_paren, LParenLoc);
SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
if (RParenLocPtr) *RParenLocPtr = RPLoc;
return false;
}
@ -837,14 +845,16 @@ Parser::OwningStmtResult Parser::ParseDoStatement() {
// Parse the parenthesized condition.
OwningExprResult Cond(Actions);
ParseParenExprOrCondition(Cond, true);
SourceLocation LPLoc, RPLoc;
ParseParenExprOrCondition(Cond, true, &LPLoc, &RPLoc);
DoScope.Exit();
if (Cond.isInvalid() || Body.isInvalid())
return StmtError();
return Actions.ActOnDoStmt(DoLoc, move(Body), WhileLoc, move(Cond));
return Actions.ActOnDoStmt(DoLoc, move(Body), WhileLoc, LPLoc,
move(Cond), RPLoc);
}
/// ParseForStatement

View File

@ -290,11 +290,11 @@ Parser::ParseTemplateParameterList(unsigned Depth,
/// parameter-declaration
///
/// type-parameter: (see below)
/// 'class' identifier[opt]
/// 'class' ...[opt][C++0x] identifier[opt]
/// 'class' identifier[opt] '=' type-id
/// 'typename' identifier[opt]
/// 'typename' ...[opt][C++0x] identifier[opt]
/// 'typename' identifier[opt] '=' type-id
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
/// 'template' ...[opt][C++0x] '<' template-parameter-list '>' 'class' identifier[opt]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
Parser::DeclPtrTy
Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
@ -319,9 +319,9 @@ Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
/// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.
///
/// type-parameter: [C++ temp.param]
/// 'class' identifier[opt]
/// 'class' ...[opt][C++0x] identifier[opt]
/// 'class' identifier[opt] '=' type-id
/// 'typename' identifier[opt]
/// 'typename' ...[opt][C++0x] identifier[opt]
/// 'typename' identifier[opt] '=' type-id
Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
@ -331,6 +331,17 @@ Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
bool TypenameKeyword = Tok.is(tok::kw_typename);
SourceLocation KeyLoc = ConsumeToken();
// Grab the ellipsis (if given).
bool Ellipsis = false;
SourceLocation EllipsisLoc;
if (Tok.is(tok::ellipsis)) {
Ellipsis = true;
EllipsisLoc = ConsumeToken();
if (!getLang().CPlusPlus0x)
Diag(EllipsisLoc, diag::err_variadic_templates);
}
// Grab the template parameter name (if given)
SourceLocation NameLoc;
IdentifierInfo* ParamName = 0;
@ -347,6 +358,7 @@ Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
}
DeclPtrTy TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
Ellipsis, EllipsisLoc,
KeyLoc, ParamName, NameLoc,
Depth, Position);

View File

@ -655,7 +655,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
return PP.getLangOptions().Microsoft ? TPResult::True() : TPResult::False();
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___forceinline:
return TPResult::True();
// The ambiguity resides in a simple-type-specifier/typename-specifier
// followed by a '('. The '(' could either be the start of:

View File

@ -183,7 +183,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
CurrentInstantiationScope(0) {
NumSFINAEErrors(0), CurrentInstantiationScope(0) {
StdNamespace = 0;
TUScope = 0;
@ -316,7 +316,8 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() {
}
Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
this->Emit();
if (!this->Emit())
return;
// If this is not a note, and we're in a template instantiation
// that is different from the last template instantiation where

View File

@ -256,6 +256,9 @@ public:
/// unit.
bool CompleteTranslationUnit;
/// \brief The number of SFINAE diagnostics that have been trapped.
unsigned NumSFINAEErrors;
typedef llvm::DenseMap<Selector, ObjCMethodList> MethodPool;
/// Instance/Factory Method Pools - allows efficient lookup when typechecking
@ -297,11 +300,38 @@ public:
SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
: DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { }
explicit SemaDiagnosticBuilder(Sema &SemaRef)
: DiagnosticBuilder(DiagnosticBuilder::Suppress), SemaRef(SemaRef) { }
~SemaDiagnosticBuilder();
};
/// \brief Emit a diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
if (isSFINAEContext() && Diagnostic::isBuiltinSFINAEDiag(DiagID)) {
// If we encountered an error during template argument
// deduction, and that error is one of the SFINAE errors,
// suppress the diagnostic.
bool Fatal = false;
switch (Diags.getDiagnosticLevel(DiagID)) {
case Diagnostic::Ignored:
case Diagnostic::Note:
case Diagnostic::Warning:
break;
case Diagnostic::Error:
++NumSFINAEErrors;
break;
case Diagnostic::Fatal:
Fatal = true;
break;
}
if (!Fatal)
return SemaDiagnosticBuilder(*this);
}
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
return SemaDiagnosticBuilder(DB, *this, DiagID);
}
@ -349,6 +379,11 @@ public:
QualType *ParamTypes, unsigned NumParamTypes,
bool Variadic, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
QualType BuildMemberPointerType(QualType T, QualType Class,
unsigned Quals, SourceLocation Loc,
DeclarationName Entity);
QualType BuildBlockPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0,
TagDecl **OwnedDecl = 0);
DeclarationName GetNameForDeclarator(Declarator &D);
@ -409,8 +444,14 @@ public:
SourceLocation EqualLoc,
ExprArg defarg);
virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc);
SourceLocation EqualLoc,
SourceLocation ArgLoc);
virtual void ActOnParamDefaultArgumentError(DeclPtrTy param);
// Contains the locations of the beginning of unparsed default
// argument locations.
llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
virtual void AddInitializerToDecl(DeclPtrTy dcl, FullExprArg init);
void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit);
void ActOnUninitializedDecl(DeclPtrTy dcl);
@ -1194,7 +1235,9 @@ public:
virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
FullExprArg Cond, StmtArg Body);
virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
SourceLocation WhileLoc, ExprArg Cond);
SourceLocation WhileLoc,
SourceLocation CondLParen, ExprArg Cond,
SourceLocation CondRParen);
virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
SourceLocation LParenLoc,
@ -1871,7 +1914,8 @@ public:
bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl);
virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename,
virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
@ -1940,8 +1984,14 @@ public:
ClassTemplateSpecializationDecl *PrevDecl,
SourceLocation TemplateNameLoc,
SourceRange ScopeSpecifierRange,
bool PartialSpecialization,
bool ExplicitInstantiation);
bool CheckClassTemplatePartialSpecializationArgs(
TemplateParameterList *TemplateParams,
const TemplateArgumentListBuilder &TemplateArgs,
bool &MirrorsPrimaryTemplate);
virtual DeclResult
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc,
@ -1985,6 +2035,10 @@ public:
SourceLocation RAngleLoc,
TemplateArgumentListBuilder &Converted);
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
const TemplateArgument &Arg,
TemplateArgumentListBuilder &Converted);
bool CheckTemplateArgument(TemplateTypeParmDecl *Param, QualType Arg,
SourceLocation ArgLoc);
bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
@ -1992,7 +2046,7 @@ public:
bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member);
bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType InstantiatedParamType, Expr *&Arg,
TemplateArgumentListBuilder *Converted = 0);
TemplateArgument &Converted);
bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, DeclRefExpr *Arg);
bool TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
@ -2031,10 +2085,122 @@ public:
const IdentifierInfo &II,
SourceRange Range);
TemplateArgumentList *
/// \brief Describes the result of template argument deduction.
///
/// The TemplateDeductionResult enumeration describes the result of
/// template argument deduction, as returned from
/// DeduceTemplateArguments(). The separate TemplateDeductionInfo
/// structure provides additional information about the results of
/// template argument deduction, e.g., the deduced template argument
/// list (if successful) or the specific template parameters or
/// deduced arguments that were involved in the failure.
enum TemplateDeductionResult {
/// \brief Template argument deduction was successful.
TDK_Success = 0,
/// \brief Template argument deduction exceeded the maximum template
/// instantiation depth (which has already been diagnosed).
TDK_InstantiationDepth,
/// \brief Template argument deduction did not deduce a value
/// for every template parameter.
TDK_Incomplete,
/// \brief Template argument deduction produced inconsistent
/// deduced values for the given template parameter.
TDK_Inconsistent,
/// \brief Template argument deduction failed due to inconsistent
/// cv-qualifiers on a template parameter type that would
/// otherwise be deduced, e.g., we tried to deduce T in "const T"
/// but were given a non-const "X".
TDK_InconsistentQuals,
/// \brief Substitution of the deduced template argument values
/// resulted in an error.
TDK_SubstitutionFailure,
/// \brief Substitution of the deduced template argument values
/// into a non-deduced context produced a type or value that
/// produces a type that does not match the original template
/// arguments provided.
TDK_NonDeducedMismatch
};
/// \brief Provides information about an attempted template argument
/// deduction, whose success or failure was described by a
/// TemplateDeductionResult value.
class TemplateDeductionInfo {
/// \brief The context in which the template arguments are stored.
ASTContext &Context;
/// \brief The deduced template argument list.
///
TemplateArgumentList *Deduced;
// do not implement these
TemplateDeductionInfo(const TemplateDeductionInfo&);
TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
public:
TemplateDeductionInfo(ASTContext &Context) : Context(Context), Deduced(0) { }
~TemplateDeductionInfo() {
// FIXME: if (Deduced) Deduced->Destroy(Context);
}
/// \brief Take ownership of the deduced template argument list.
TemplateArgumentList *take() {
TemplateArgumentList *Result = Deduced;
Deduced = 0;
return Result;
}
/// \brief Provide a new template argument list that contains the
/// results of template argument deduction.
void reset(TemplateArgumentList *NewDeduced) {
// FIXME: if (Deduced) Deduced->Destroy(Context);
Deduced = NewDeduced;
}
/// \brief The template parameter to which a template argument
/// deduction failure refers.
///
/// Depending on the result of template argument deduction, this
/// template parameter may have different meanings:
///
/// TDK_Incomplete: this is the first template parameter whose
/// corresponding template argument was not deduced.
///
/// TDK_Inconsistent: this is the template parameter for which
/// two different template argument values were deduced.
TemplateParameter Param;
/// \brief The first template argument to which the template
/// argument deduction failure refers.
///
/// Depending on the result of the template argument deduction,
/// this template argument may have different meanings:
///
/// TDK_Inconsistent: this argument is the first value deduced
/// for the corresponding template parameter.
///
/// TDK_SubstitutionFailure: this argument is the template
/// argument we were instantiating when we encountered an error.
///
/// TDK_NonDeducedMismatch: this is the template argument
/// provided in the source code.
TemplateArgument FirstArg;
/// \brief The second template argument to which the template
/// argument deduction failure refers.
///
/// FIXME: Finish documenting this.
TemplateArgument SecondArg;
};
TemplateDeductionResult
DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs);
const TemplateArgumentList &TemplateArgs,
TemplateDeductionInfo &Info);
void MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
llvm::SmallVectorImpl<bool> &Deduced);
//===--------------------------------------------------------------------===//
// C++ Template Instantiation
//
@ -2053,7 +2219,16 @@ public:
/// parameter. The Entity is the template, and
/// TemplateArgs/NumTemplateArguments provides the template
/// arguments as specified.
DefaultTemplateArgumentInstantiation
/// FIXME: Use a TemplateArgumentList
DefaultTemplateArgumentInstantiation,
/// We are performing template argument deduction for a class
/// template partial specialization. The Entity is the class
/// template partial specialization, and
/// TemplateArgs/NumTemplateArgs provides the deduced template
/// arguments.
/// FIXME: Use a TemplateArgumentList
PartialSpecDeductionInstantiation
} Kind;
/// \brief The point of instantiation within the source code.
@ -2087,6 +2262,7 @@ public:
return true;
case DefaultTemplateArgumentInstantiation:
case PartialSpecDeductionInstantiation:
return X.TemplateArgs == Y.TemplateArgs;
}
@ -2143,6 +2319,15 @@ public:
unsigned NumTemplateArgs,
SourceRange InstantiationRange = SourceRange());
/// \brief Note that we are instantiating as part of template
/// argument deduction for a class template partial
/// specialization.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ClassTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceRange InstantiationRange = SourceRange());
/// \brief Note that we have finished instantiating this template.
void Clear();
@ -2167,6 +2352,32 @@ public:
void PrintInstantiationStack();
/// \brief Determines whether we are currently in a context where
/// template argument substitution failures are not considered
/// errors.
///
/// When this routine returns true, the emission of most diagnostics
/// will be suppressed and there will be no local error recovery.
bool isSFINAEContext() const;
/// \brief RAII class used to determine whether SFINAE has
/// trapped any errors that occur during template argument
/// deduction.
class SFINAETrap {
Sema &SemaRef;
unsigned PrevSFINAEErrors;
public:
explicit SFINAETrap(Sema &SemaRef)
: SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors) { }
~SFINAETrap() { SemaRef.NumSFINAEErrors = PrevSFINAEErrors; }
/// \brief Determine whether any SFINAE errors have been trapped.
bool hasErrorOccurred() const {
return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
}
};
/// \brief A stack-allocated class that identifies which local
/// variable declaration instantiations are present in this scope.
///
@ -2285,6 +2496,8 @@ public:
TemplateName
InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
const TemplateArgumentList &TemplateArgs);
TemplateArgument Instantiate(TemplateArgument Arg,
const TemplateArgumentList &TemplateArgs);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function);

View File

@ -416,14 +416,14 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
if (Context.BuiltinInfo.hasVAListUse(BID))
InitBuiltinVaListType();
Builtin::Context::GetBuiltinTypeError Error;
QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context, Error);
ASTContext::GetBuiltinTypeError Error;
QualType R = Context.GetBuiltinType(BID, Error);
switch (Error) {
case Builtin::Context::GE_None:
case ASTContext::GE_None:
// Okay
break;
case Builtin::Context::GE_Missing_FILE:
case ASTContext::GE_Missing_FILE:
if (ForRedeclaration)
Diag(Loc, diag::err_implicit_decl_requires_stdio)
<< Context.BuiltinInfo.GetName(BID);
@ -3208,7 +3208,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
if (!FD->getAttr<FormatAttr>())
FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1,
FormatIdx + 2));
HasVAListArg ? 0 : FormatIdx + 2));
}
// Mark const if we don't care about errno and that is the only
@ -3239,10 +3239,12 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// FIXME: We known better than our headers.
const_cast<FormatAttr *>(Format)->setType("printf");
} else
FD->addAttr(::new (Context) FormatAttr("printf", 1, 2));
FD->addAttr(::new (Context) FormatAttr("printf", 1,
Name->isStr("NSLogv") ? 0 : 2));
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
if (!FD->getAttr<FormatAttr>())
FD->addAttr(::new (Context) FormatAttr("printf", 2, 3));
FD->addAttr(::new (Context) FormatAttr("printf", 2,
Name->isStr("vasprintf") ? 0 : 3));
}
}

View File

@ -1699,6 +1699,9 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
/// the attribute applies to decls. If the attribute is a type attribute, just
/// silently ignore it.
static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
if (Attr.isDeclspecAttribute())
// FIXME: Try to deal with __declspec attributes!
return;
switch (Attr.getKind()) {
case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break;
case AttributeList::AT_address_space:

View File

@ -108,6 +108,8 @@ void
Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
ExprArg defarg) {
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
UnparsedDefaultArgLocs.erase(Param);
ExprOwningPtr<Expr> DefaultArg(this, defarg.takeAs<Expr>());
QualType ParamType = Param->getType();
@ -154,16 +156,23 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
/// because we're inside a class definition. Note that this default
/// argument will be parsed later.
void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc) {
SourceLocation EqualLoc,
SourceLocation ArgLoc) {
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
if (Param)
Param->setUnparsedDefaultArg();
UnparsedDefaultArgLocs[Param] = ArgLoc;
}
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) {
cast<ParmVarDecl>(param.getAs<Decl>())->setInvalidDecl();
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
Param->setInvalidDecl();
UnparsedDefaultArgLocs.erase(Param);
}
/// CheckExtraCXXDefaultArguments - Check for any extra default
@ -285,7 +294,7 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
// in a semantically valid state.
for (p = 0; p <= LastMissingDefaultArg; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->getDefaultArg()) {
if (Param->hasDefaultArg()) {
if (!Param->hasUnparsedDefaultArg())
Param->getDefaultArg()->Destroy(Context);
Param->setDefaultArg(0);

View File

@ -1177,7 +1177,12 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
ValueDependent = true;
// - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent
// (FIXME!).
else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) {
if (Dcl->getType().getCVRQualifiers() == QualType::Const &&
Dcl->getInit()) {
ValueDependent = Dcl->getInit()->isValueDependent();
}
}
}
return Owned(BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc,
@ -2479,9 +2484,19 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// Pass the argument.
if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
return true;
} else
} else {
if (FDecl->getParamDecl(i)->hasUnparsedDefaultArg()) {
Diag (Call->getSourceRange().getBegin(),
diag::err_use_of_default_argument_to_function_declared_later) <<
FDecl << cast<CXXRecordDecl>(FDecl->getDeclContext())->getDeclName();
Diag(UnparsedDefaultArgLocs[FDecl->getParamDecl(i)],
diag::note_default_argument_declared_here);
}
// We already type-checked the argument, so we know it works.
Arg = new (Context) CXXDefaultArgExpr(FDecl->getParamDecl(i));
}
QualType ArgType = Arg->getType();
Call->setArg(i, Arg);

View File

@ -138,6 +138,12 @@ bool Sema::LookupInBases(CXXRecordDecl *Class,
// Find the record of the base class subobjects for this type.
QualType BaseType = Context.getCanonicalType(BaseSpec->getType());
BaseType = BaseType.getUnqualifiedType();
// If a base class of the class template depends on a template-parameter,
// the base class scope is not examined during unqualified name lookup.
// [temp.dep]p3.
if (BaseType->isDependentType())
continue;
// Determine whether we need to visit this base class at all,
// updating the count of subobjects appropriately.

View File

@ -674,7 +674,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
// compatible structure or union type. In the latter case, the
// initial value of the object, including unnamed members, is
// that of the expression.
if (ElemType->isRecordType() &&
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
SemaRef.Context.hasSameUnqualifiedType(expr->getType(), ElemType)) {
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;

View File

@ -20,6 +20,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"

View File

@ -568,7 +568,8 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, StmtArg Body) {
Action::OwningStmtResult
Sema::ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
SourceLocation WhileLoc, ExprArg Cond) {
SourceLocation WhileLoc, SourceLocation CondLParen,
ExprArg Cond, SourceLocation CondRParen) {
Expr *condExpr = Cond.takeAs<Expr>();
assert(condExpr && "ActOnDoStmt(): missing expression");
@ -588,7 +589,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
Cond.release();
return Owned(new (Context) DoStmt(Body.takeAs<Stmt>(), condExpr, DoLoc,
WhileLoc));
WhileLoc, CondRParen));
}
Action::OwningStmtResult

View File

@ -140,7 +140,8 @@ TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) {
/// ParamName is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault.
Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename,
Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
@ -162,7 +163,8 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename,
TemplateTypeParmDecl *Param
= TemplateTypeParmDecl::Create(Context, CurContext, Loc,
Depth, Position, ParamName, Typename);
Depth, Position, ParamName, Typename,
Ellipsis);
if (Invalid)
Param->setInvalidDecl();
@ -185,6 +187,14 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
= cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>());
QualType Default = QualType::getFromOpaquePtr(DefaultT);
// C++0x [temp.param]p9:
// A default template-argument may be specified for any kind of
// template-parameter that is not a template parameter pack.
if (Parm->isParameterPack()) {
Diag(DefaultLoc, diag::err_template_param_pack_default_arg);
return;
}
// C++ [temp.param]p14:
// A template-parameter shall not be used in its own default argument.
// FIXME: Implement this check! Needs a recursive walk over the types.
@ -297,7 +307,9 @@ void Sema::ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParamD,
// FIXME: Implement this check! Needs a recursive walk over the types.
// Check the well-formedness of the default template argument.
if (CheckTemplateArgument(TemplateParm, TemplateParm->getType(), Default)) {
TemplateArgument Converted;
if (CheckTemplateArgument(TemplateParm, TemplateParm->getType(), Default,
Converted)) {
TemplateParm->setInvalidDecl();
return;
}
@ -579,6 +591,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
bool SawDefaultArgument = false;
SourceLocation PreviousDefaultArgLoc;
bool SawParameterPack = false;
SourceLocation ParameterPackLoc;
// Dummy initialization to avoid warnings.
TemplateParameterList::iterator OldParam = NewParams->end();
if (OldParams)
@ -595,13 +610,27 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Variables used to diagnose missing default arguments
bool MissingDefaultArg = false;
// C++0x [temp.param]p11:
// If a template parameter of a class template is a template parameter pack,
// it must be the last template parameter.
if (SawParameterPack) {
Diag(ParameterPackLoc,
diag::err_template_param_pack_must_be_last_template_parameter);
Invalid = true;
}
// Merge default arguments for template type parameters.
if (TemplateTypeParmDecl *NewTypeParm
= dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
TemplateTypeParmDecl *OldTypeParm
= OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0;
if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
if (NewTypeParm->isParameterPack()) {
assert(!NewTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
SawParameterPack = true;
ParameterPackLoc = NewTypeParm->getLocation();
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
NewTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
@ -946,6 +975,33 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
return TemplateTy::make(Context.getDependentTemplateName(Qualifier, &Name));
}
bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
const TemplateArgument &Arg,
TemplateArgumentListBuilder &Converted) {
// Check template type parameter.
if (Arg.getKind() != TemplateArgument::Type) {
// C++ [temp.arg.type]p1:
// A template-argument for a template-parameter which is a
// type shall be a type-id.
// We have a template type parameter but the template argument
// is not a type.
Diag(Arg.getLocation(), diag::err_template_arg_must_be_type);
Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
if (CheckTemplateArgument(Param, Arg.getAsType(), Arg.getLocation()))
return true;
// Add the converted template type argument.
Converted.push_back(
TemplateArgument(Arg.getLocation(),
Context.getCanonicalType(Arg.getAsType())));
return false;
}
/// \brief Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
@ -960,7 +1016,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
unsigned NumArgs = NumTemplateArgs;
bool Invalid = false;
if (NumArgs > NumParams ||
bool HasParameterPack =
NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack();
if ((NumArgs > NumParams && !HasParameterPack) ||
NumArgs < Params->getMinRequiredArguments()) {
// FIXME: point at either the first arg beyond what we can handle,
// or the '>', depending on whether we have too many or too few
@ -994,6 +1053,13 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Retrieve the default template argument from the template
// parameter.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
if (TTP->isParameterPack()) {
// We have an empty parameter pack.
Converted.BeginParameterPack();
Converted.EndParameterPack();
break;
}
if (!TTP->hasDefaultArgument())
break;
@ -1024,8 +1090,21 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (!NTTP->hasDefaultArgument())
break;
// FIXME: Instantiate default argument
Arg = TemplateArgument(NTTP->getDefaultArgument());
InstantiatingTemplate Inst(*this, TemplateLoc,
Template, Converted.getFlatArgumentList(),
Converted.flatSize(),
SourceRange(TemplateLoc, RAngleLoc));
TemplateArgumentList TemplateArgs(Context, Converted,
/*CopyArgs=*/false,
/*FlattenArgs=*/false);
Sema::OwningExprResult E = InstantiateExpr(NTTP->getDefaultArgument(),
TemplateArgs);
if (E.isInvalid())
return true;
Arg = TemplateArgument(E.takeAs<Expr>());
} else {
TemplateTemplateParmDecl *TempParm
= cast<TemplateTemplateParmDecl>(*Param);
@ -1043,27 +1122,19 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
// Check template type parameters.
if (Arg.getKind() == TemplateArgument::Type) {
if (CheckTemplateArgument(TTP, Arg.getAsType(), Arg.getLocation()))
if (TTP->isParameterPack()) {
Converted.BeginParameterPack();
// Check all the remaining arguments (if any).
for (; ArgIdx < NumArgs; ++ArgIdx) {
if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted))
Invalid = true;
}
Converted.EndParameterPack();
} else {
if (CheckTemplateTypeArgument(TTP, Arg, Converted))
Invalid = true;
// Add the converted template type argument.
Converted.push_back(
TemplateArgument(Arg.getLocation(),
Context.getCanonicalType(Arg.getAsType())));
continue;
}
// C++ [temp.arg.type]p1:
// A template-argument for a template-parameter which is a
// type shall be a type-id.
// We have a template type parameter but the template argument
// is not a type.
Diag(Arg.getLocation(), diag::err_template_arg_must_be_type);
Diag((*Param)->getLocation(), diag::note_template_param_here);
Invalid = true;
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
// Check non-type template parameters.
@ -1103,8 +1174,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Expression: {
Expr *E = Arg.getAsExpr();
if (CheckTemplateArgument(NTTP, NTTPType, E, &Converted))
TemplateArgument Result;
if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
Invalid = true;
else
Converted.push_back(Result);
break;
}
@ -1388,11 +1462,10 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
/// InstantiatedParamType is the type of the non-type template
/// parameter after it has been instantiated.
///
/// If Converted is non-NULL and no errors occur, the value
/// of this argument will be added to the end of the Converted vector.
/// If no error was detected, Converted receives the converted template argument.
bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType InstantiatedParamType, Expr *&Arg,
TemplateArgumentListBuilder *Converted) {
TemplateArgument &Converted) {
SourceLocation StartLoc = Arg->getSourceRange().getBegin();
// If either the parameter has a dependent type or the argument is
@ -1400,7 +1473,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// FIXME: Add template argument to Converted!
if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) {
// FIXME: Produce a cloned, canonical expression?
Converted->push_back(TemplateArgument(Arg));
Converted = TemplateArgument(Arg);
return false;
}
@ -1465,7 +1538,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType IntegerType = Context.getCanonicalType(ParamType);
if (const EnumType *Enum = IntegerType->getAsEnumType())
IntegerType = Enum->getDecl()->getIntegerType();
IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType());
if (!Arg->isValueDependent()) {
// Check that an unsigned parameter does not receive a negative
@ -1495,21 +1568,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Value.setIsSigned(IntegerType->isSignedIntegerType());
}
if (Converted) {
// Add the value of this argument to the list of converted
// arguments. We use the bitwidth and signedness of the template
// parameter.
if (Arg->isValueDependent()) {
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
Converted->push_back(TemplateArgument(Arg));
return false;
}
Converted->push_back(TemplateArgument(StartLoc, Value,
ParamType->isEnumeralType() ? ParamType : IntegerType));
// Add the value of this argument to the list of converted
// arguments. We use the bitwidth and signedness of the template
// parameter.
if (Arg->isValueDependent()) {
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
Converted = TemplateArgument(Arg);
return false;
}
Converted = TemplateArgument(StartLoc, Value,
ParamType->isEnumeralType() ? ParamType
: IntegerType);
return false;
}
@ -1576,11 +1647,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentPointerToMember(Arg, Member))
return true;
if (Converted) {
Member = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Member));
Converted->push_back(TemplateArgument(StartLoc, Member));
}
Member = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Member));
Converted = TemplateArgument(StartLoc, Member);
return false;
}
@ -1588,10 +1656,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
return true;
if (Converted) {
Entity = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Entity));
Converted->push_back(TemplateArgument(StartLoc, Entity));
}
Entity = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Entity));
Converted = TemplateArgument(StartLoc, Entity);
return false;
}
@ -1629,11 +1695,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
return true;
if (Converted) {
Entity = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Entity));
Converted->push_back(TemplateArgument(StartLoc, Entity));
}
Entity = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Entity));
Converted = TemplateArgument(StartLoc, Entity);
return false;
}
@ -1673,11 +1736,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
return true;
if (Converted) {
Entity = cast<NamedDecl>(Context.getCanonicalDecl(Entity));
Converted->push_back(TemplateArgument(StartLoc, Entity));
}
Entity = cast<NamedDecl>(Context.getCanonicalDecl(Entity));
Converted = TemplateArgument(StartLoc, Entity);
return false;
}
@ -1705,11 +1765,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentPointerToMember(Arg, Member))
return true;
if (Converted) {
Member = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Member));
Converted->push_back(TemplateArgument(StartLoc, Member));
}
Member = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Member));
Converted = TemplateArgument(StartLoc, Member);
return false;
}
@ -1730,7 +1787,12 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
// template template argument with the corresponding parameter;
// partial specializations are not considered even if their
// parameter lists match that of the template template parameter.
if (!isa<ClassTemplateDecl>(Template)) {
//
// Note that we also allow template template parameters here, which
// will happen when we are dealing with, e.g., class template
// partial specializations.
if (!isa<ClassTemplateDecl>(Template) &&
!isa<TemplateTemplateParmDecl>(Template)) {
assert(isa<FunctionTemplateDecl>(Template) &&
"Only function templates are possible here");
Diag(Arg->getSourceRange().getBegin(),
@ -1925,6 +1987,7 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
ClassTemplateSpecializationDecl *PrevDecl,
SourceLocation TemplateNameLoc,
SourceRange ScopeSpecifierRange,
bool PartialSpecialization,
bool ExplicitInstantiation) {
// C++ [temp.expl.spec]p2:
// An explicit specialization shall be declared in the namespace
@ -1940,8 +2003,9 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
// that encloses the one in which the explicit specialization was
// declared.
if (CurContext->getLookupContext()->isFunctionOrMethod()) {
int Kind = ExplicitInstantiation? 2 : PartialSpecialization? 1 : 0;
Diag(TemplateNameLoc, diag::err_template_spec_decl_function_scope)
<< ExplicitInstantiation << ClassTemplate;
<< Kind << ClassTemplate;
return true;
}
@ -1956,11 +2020,12 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
if (DC != TemplateContext) {
if (isa<TranslationUnitDecl>(TemplateContext))
Diag(TemplateNameLoc, diag::err_template_spec_decl_out_of_scope_global)
<< PartialSpecialization
<< ClassTemplate << ScopeSpecifierRange;
else if (isa<NamespaceDecl>(TemplateContext))
Diag(TemplateNameLoc, diag::err_template_spec_decl_out_of_scope)
<< ClassTemplate << cast<NamedDecl>(TemplateContext)
<< ScopeSpecifierRange;
<< PartialSpecialization << ClassTemplate
<< cast<NamedDecl>(TemplateContext) << ScopeSpecifierRange;
Diag(ClassTemplate->getLocation(), diag::note_template_decl_here);
}
@ -1974,16 +2039,17 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
// FIXME: In C++98, we would like to turn these errors into warnings,
// dependent on a -Wc++0x flag.
bool SuppressedDiag = false;
int Kind = ExplicitInstantiation? 2 : PartialSpecialization? 1 : 0;
if (isa<TranslationUnitDecl>(TemplateContext)) {
if (!ExplicitInstantiation || getLangOptions().CPlusPlus0x)
Diag(TemplateNameLoc, diag::err_template_spec_redecl_global_scope)
<< ExplicitInstantiation << ClassTemplate << ScopeSpecifierRange;
<< Kind << ClassTemplate << ScopeSpecifierRange;
else
SuppressedDiag = true;
} else if (isa<NamespaceDecl>(TemplateContext)) {
if (!ExplicitInstantiation || getLangOptions().CPlusPlus0x)
Diag(TemplateNameLoc, diag::err_template_spec_redecl_out_of_scope)
<< ExplicitInstantiation << ClassTemplate
<< Kind << ClassTemplate
<< cast<NamedDecl>(TemplateContext) << ScopeSpecifierRange;
else
SuppressedDiag = true;
@ -1996,6 +2062,126 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
return false;
}
/// \brief Check the non-type template arguments of a class template
/// partial specialization according to C++ [temp.class.spec]p9.
///
/// \param TemplateParams the template parameters of the primary class
/// template.
///
/// \param TemplateArg the template arguments of the class template
/// partial specialization.
///
/// \param MirrorsPrimaryTemplate will be set true if the class
/// template partial specialization arguments are identical to the
/// implicit template arguments of the primary template. This is not
/// necessarily an error (C++0x), and it is left to the caller to diagnose
/// this condition when it is an error.
///
/// \returns true if there was an error, false otherwise.
bool Sema::CheckClassTemplatePartialSpecializationArgs(
TemplateParameterList *TemplateParams,
const TemplateArgumentListBuilder &TemplateArgs,
bool &MirrorsPrimaryTemplate) {
// FIXME: the interface to this function will have to change to
// accommodate variadic templates.
MirrorsPrimaryTemplate = true;
const TemplateArgument *ArgList = TemplateArgs.getFlatArgumentList();
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
// Determine whether the template argument list of the partial
// specialization is identical to the implicit argument list of
// the primary template. The caller may need to diagnostic this as
// an error per C++ [temp.class.spec]p9b3.
if (MirrorsPrimaryTemplate) {
if (TemplateTypeParmDecl *TTP
= dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(I))) {
if (Context.getCanonicalType(Context.getTypeDeclType(TTP)) !=
Context.getCanonicalType(ArgList[I].getAsType()))
MirrorsPrimaryTemplate = false;
} else if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(
TemplateParams->getParam(I))) {
// FIXME: We should settle on either Declaration storage or
// Expression storage for template template parameters.
TemplateTemplateParmDecl *ArgDecl
= dyn_cast_or_null<TemplateTemplateParmDecl>(
ArgList[I].getAsDecl());
if (!ArgDecl)
if (DeclRefExpr *DRE
= dyn_cast_or_null<DeclRefExpr>(ArgList[I].getAsExpr()))
ArgDecl = dyn_cast<TemplateTemplateParmDecl>(DRE->getDecl());
if (!ArgDecl ||
ArgDecl->getIndex() != TTP->getIndex() ||
ArgDecl->getDepth() != TTP->getDepth())
MirrorsPrimaryTemplate = false;
}
}
NonTypeTemplateParmDecl *Param
= dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
if (!Param) {
continue;
}
Expr *ArgExpr = ArgList[I].getAsExpr();
if (!ArgExpr) {
MirrorsPrimaryTemplate = false;
continue;
}
// C++ [temp.class.spec]p8:
// A non-type argument is non-specialized if it is the name of a
// non-type parameter. All other non-type arguments are
// specialized.
//
// Below, we check the two conditions that only apply to
// specialized non-type arguments, so skip any non-specialized
// arguments.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl())) {
if (MirrorsPrimaryTemplate &&
(Param->getIndex() != NTTP->getIndex() ||
Param->getDepth() != NTTP->getDepth()))
MirrorsPrimaryTemplate = false;
continue;
}
// C++ [temp.class.spec]p9:
// Within the argument list of a class template partial
// specialization, the following restrictions apply:
// -- A partially specialized non-type argument expression
// shall not involve a template parameter of the partial
// specialization except when the argument expression is a
// simple identifier.
if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) {
Diag(ArgExpr->getLocStart(),
diag::err_dependent_non_type_arg_in_partial_spec)
<< ArgExpr->getSourceRange();
return true;
}
// -- The type of a template parameter corresponding to a
// specialized non-type argument shall not be dependent on a
// parameter of the specialization.
if (Param->getType()->isDependentType()) {
Diag(ArgExpr->getLocStart(),
diag::err_dependent_typed_non_type_arg_in_partial_spec)
<< Param->getType()
<< ArgExpr->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
MirrorsPrimaryTemplate = false;
}
return false;
}
Sema::DeclResult
Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc,
@ -2032,9 +2218,41 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
return true;
}
// FIXME: We'll need more checks, here!
if (TemplateParams->size() > 0)
if (TemplateParams->size() > 0) {
isPartialSpecialization = true;
// C++ [temp.class.spec]p10:
// The template parameter list of a specialization shall not
// contain default template argument values.
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
Decl *Param = TemplateParams->getParam(I);
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
if (TTP->hasDefaultArgument()) {
Diag(TTP->getDefaultArgumentLoc(),
diag::err_default_arg_in_partial_spec);
TTP->setDefaultArgument(QualType(), SourceLocation(), false);
}
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (Expr *DefArg = NTTP->getDefaultArgument()) {
Diag(NTTP->getDefaultArgumentLoc(),
diag::err_default_arg_in_partial_spec)
<< DefArg->getSourceRange();
NTTP->setDefaultArgument(0);
DefArg->Destroy(Context);
}
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
if (Expr *DefArg = TTP->getDefaultArgument()) {
Diag(TTP->getDefaultArgumentLoc(),
diag::err_default_arg_in_partial_spec)
<< DefArg->getSourceRange();
TTP->setDefaultArgument(0);
DefArg->Destroy(Context);
}
}
}
}
}
// Check that the specialization uses the same tag kind as the
@ -2066,7 +2284,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
// template.
TemplateArgumentListBuilder ConvertedTemplateArgs(Context);
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc,
&TemplateArgs[0], TemplateArgs.size(),
TemplateArgs.data(), TemplateArgs.size(),
RAngleLoc, ConvertedTemplateArgs))
return true;
@ -2077,11 +2295,36 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
if (isPartialSpecialization)
if (isPartialSpecialization) {
bool MirrorsPrimaryTemplate;
if (CheckClassTemplatePartialSpecializationArgs(
ClassTemplate->getTemplateParameters(),
ConvertedTemplateArgs,
MirrorsPrimaryTemplate))
return true;
if (MirrorsPrimaryTemplate) {
// C++ [temp.class.spec]p9b3:
//
// -- The argument list of the specialization shall not be identical
// to the implicit argument list of the primary template.
Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
<< (TK == TK_Definition)
<< CodeModificationHint::CreateRemoval(SourceRange(LAngleLoc,
RAngleLoc));
return ActOnClassTemplate(S, TagSpec, TK, KWLoc, SS,
ClassTemplate->getIdentifier(),
TemplateNameLoc,
Attr,
move(TemplateParameterLists),
AS_none);
}
// FIXME: Template parameter list matters, too
ClassTemplatePartialSpecializationDecl::Profile(ID,
ConvertedTemplateArgs.getFlatArgumentList(),
ConvertedTemplateArgs.flatSize());
}
else
ClassTemplateSpecializationDecl::Profile(ID,
ConvertedTemplateArgs.getFlatArgumentList(),
@ -2104,6 +2347,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
if (CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl,
TemplateNameLoc,
SS.getRange(),
isPartialSpecialization,
/*ExplicitInstantiation=*/false))
return true;
@ -2116,8 +2360,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
Specialization->setLocation(TemplateNameLoc);
PrevDecl = 0;
} else if (isPartialSpecialization) {
// FIXME: extra checking for partial specializations
// Create a new class template partial specialization declaration node.
TemplateParameterList *TemplateParams
= static_cast<TemplateParameterList*>(*TemplateParameterLists.get());
@ -2139,6 +2381,38 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
ClassTemplate->getPartialSpecializations().InsertNode(Partial, InsertPos);
}
Specialization = Partial;
// Check that all of the template parameters of the class template
// partial specialization are deducible from the template
// arguments. If not, this class template partial specialization
// will never be used.
llvm::SmallVector<bool, 8> DeducibleParams;
DeducibleParams.resize(TemplateParams->size());
MarkDeducedTemplateParameters(Partial->getTemplateArgs(), DeducibleParams);
unsigned NumNonDeducible = 0;
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I)
if (!DeducibleParams[I])
++NumNonDeducible;
if (NumNonDeducible) {
Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
<< (NumNonDeducible > 1)
<< SourceRange(TemplateNameLoc, RAngleLoc);
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
if (!DeducibleParams[I]) {
NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
if (Param->getDeclName())
Diag(Param->getLocation(),
diag::note_partial_spec_unused_parameter)
<< Param->getDeclName();
else
Diag(Param->getLocation(),
diag::note_partial_spec_unused_parameter)
<< std::string("<anonymous>");
}
}
}
} else {
// Create a new class template specialization declaration node for
// this explicit specialization.
@ -2185,7 +2459,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
// template arguments in the specialization.
QualType WrittenTy
= Context.getTemplateSpecializationType(Name,
&TemplateArgs[0],
TemplateArgs.data(),
TemplateArgs.size(),
Context.getTypeDeclType(Specialization));
Specialization->setTypeAsWritten(WrittenTy);
@ -2259,6 +2533,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
if (CheckClassTemplateSpecializationScope(ClassTemplate, 0,
TemplateNameLoc,
SS.getRange(),
/*PartialSpecialization=*/false,
/*ExplicitInstantiation=*/true))
return true;

File diff suppressed because it is too large Load Diff

View File

@ -90,6 +90,30 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
}
}
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
SourceLocation PointOfInstantiation,
ClassTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
Invalid = CheckInstantiationDepth(PointOfInstantiation,
InstantiationRange);
if (!Invalid) {
ActiveTemplateInstantiation Inst;
Inst.Kind
= ActiveTemplateInstantiation::PartialSpecDeductionInstantiation;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
Inst.TemplateArgs = TemplateArgs;
Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
Invalid = false;
}
}
void Sema::InstantiatingTemplate::Clear() {
if (!Invalid) {
SemaRef.ActiveTemplateInstantiations.pop_back();
@ -157,10 +181,52 @@ void Sema::PrintInstantiationStack() {
<< Active->InstantiationRange;
break;
}
case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation: {
ClassTemplatePartialSpecializationDecl *PartialSpec
= cast<ClassTemplatePartialSpecializationDecl>((Decl *)Active->Entity);
// FIXME: The active template instantiation's template arguments
// are interesting, too. We should add something like [with T =
// foo, U = bar, etc.] to the string.
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
diag::note_partial_spec_deduct_instantiation_here)
<< Context.getTypeDeclType(PartialSpec)
<< Active->InstantiationRange;
break;
}
}
}
}
bool Sema::isSFINAEContext() const {
using llvm::SmallVector;
for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
Active = ActiveTemplateInstantiations.rbegin(),
ActiveEnd = ActiveTemplateInstantiations.rend();
Active != ActiveEnd;
++Active) {
switch(Active->Kind) {
case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation:
// We're in a template argument deduction context, so SFINAE
// applies.
return true;
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
// A default template argument instantiation may or may not be a
// SFINAE context; look further up the stack.
break;
case ActiveTemplateInstantiation::TemplateInstantiation:
// This is a template instantiation, so there is no SFINAE.
return false;
}
}
return false;
}
//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
@ -236,9 +302,11 @@ TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T,
QualType
TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T,
unsigned Quals) const {
// FIXME: Implement this
assert(false && "Cannot instantiate BlockPointerType yet");
return QualType();
QualType PointeeType = Instantiate(T->getPointeeType());
if (PointeeType.isNull())
return QualType();
return SemaRef.BuildBlockPointerType(PointeeType, Quals, Loc, Entity);
}
QualType
@ -265,9 +333,16 @@ QualType
TemplateTypeInstantiator::
InstantiateMemberPointerType(const MemberPointerType *T,
unsigned Quals) const {
// FIXME: Implement this
assert(false && "Cannot instantiate MemberPointerType yet");
return QualType();
QualType PointeeType = Instantiate(T->getPointeeType());
if (PointeeType.isNull())
return QualType();
QualType ClassType = Instantiate(QualType(T->getClass(), 0));
if (ClassType.isNull())
return QualType();
return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Quals, Loc,
Entity);
}
QualType
@ -390,7 +465,7 @@ InstantiateFunctionProtoType(const FunctionProtoType *T,
ParamTypes.push_back(P);
}
return SemaRef.BuildFunctionType(ResultType, &ParamTypes[0],
return SemaRef.BuildFunctionType(ResultType, ParamTypes.data(),
ParamTypes.size(),
T->isVariadic(), T->getTypeQuals(),
Loc, Entity);
@ -502,37 +577,11 @@ InstantiateTemplateSpecializationType(
InstantiatedTemplateArgs.reserve(T->getNumArgs());
for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
Arg != ArgEnd; ++Arg) {
switch (Arg->getKind()) {
case TemplateArgument::Null:
assert(false && "Should never have a NULL template argument");
break;
case TemplateArgument::Type: {
QualType T = SemaRef.InstantiateType(Arg->getAsType(),
TemplateArgs,
Arg->getLocation(),
DeclarationName());
if (T.isNull())
return QualType();
TemplateArgument InstArg = SemaRef.Instantiate(*Arg, TemplateArgs);
if (InstArg.isNull())
return QualType();
InstantiatedTemplateArgs.push_back(
TemplateArgument(Arg->getLocation(), T));
break;
}
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
InstantiatedTemplateArgs.push_back(*Arg);
break;
case TemplateArgument::Expression:
Sema::OwningExprResult E
= SemaRef.InstantiateExpr(Arg->getAsExpr(), TemplateArgs);
if (E.isInvalid())
return QualType();
InstantiatedTemplateArgs.push_back(E.takeAs<Expr>());
break;
}
InstantiatedTemplateArgs.push_back(InstArg);
}
// FIXME: We're missing the locations of the template name, '<', and '>'.
@ -542,7 +591,7 @@ InstantiateTemplateSpecializationType(
TemplateArgs);
return SemaRef.CheckTemplateIdType(Name, Loc, SourceLocation(),
&InstantiatedTemplateArgs[0],
InstantiatedTemplateArgs.data(),
InstantiatedTemplateArgs.size(),
SourceLocation());
}
@ -831,8 +880,14 @@ Sema::InstantiateClassTemplateSpecialization(
const TemplateArgumentList *TemplateArgs
= &ClassTemplateSpec->getTemplateArgs();
// Determine whether any class template partial specializations
// match the given template arguments.
// C++ [temp.class.spec.match]p1:
// When a class template is used in a context that requires an
// instantiation of the class, it is necessary to determine
// whether the instantiation is to be generated using the primary
// template or one of the partial specializations. This is done by
// matching the template arguments of the class template
// specialization with the template argument lists of the partial
// specializations.
typedef std::pair<ClassTemplatePartialSpecializationDecl *,
TemplateArgumentList *> MatchResult;
llvm::SmallVector<MatchResult, 4> Matched;
@ -841,20 +896,42 @@ Sema::InstantiateClassTemplateSpecialization(
PartialEnd = Template->getPartialSpecializations().end();
Partial != PartialEnd;
++Partial) {
if (TemplateArgumentList *Deduced
TemplateDeductionInfo Info(Context);
if (TemplateDeductionResult Result
= DeduceTemplateArguments(&*Partial,
ClassTemplateSpec->getTemplateArgs()))
Matched.push_back(std::make_pair(&*Partial, Deduced));
ClassTemplateSpec->getTemplateArgs(),
Info)) {
// FIXME: Store the failed-deduction information for use in
// diagnostics, later.
(void)Result;
} else {
Matched.push_back(std::make_pair(&*Partial, Info.take()));
}
}
if (Matched.size() == 1) {
// -- If exactly one matching specialization is found, the
// instantiation is generated from that specialization.
Pattern = Matched[0].first;
TemplateArgs = Matched[0].second;
} else if (Matched.size() > 1) {
// -- If more than one matching specialization is found, the
// partial order rules (14.5.4.2) are used to determine
// whether one of the specializations is more specialized
// than the others. If none of the specializations is more
// specialized than all of the other matching
// specializations, then the use of the class template is
// ambiguous and the program is ill-formed.
// FIXME: Implement partial ordering of class template partial
// specializations.
Diag(ClassTemplateSpec->getLocation(),
diag::unsup_template_partial_spec_ordering);
} else {
// -- If no matches are found, the instantiation is generated
// from the primary template.
// Since we initialized the pattern and template arguments from
// the primary template, there is nothing more we need to do here.
}
// Note that this is an instantiation.
@ -965,7 +1042,7 @@ Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
if (T.isNull())
return 0;
if (T->isRecordType() ||
if (T->isDependentType() || T->isRecordType() ||
(getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here");
return NestedNameSpecifier::Create(Context, Prefix,
@ -1046,3 +1123,38 @@ Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
// Decl. However, this won't be needed until we implement member templates.
return Name;
}
TemplateArgument Sema::Instantiate(TemplateArgument Arg,
const TemplateArgumentList &TemplateArgs) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
assert(false && "Should never have a NULL template argument");
break;
case TemplateArgument::Type: {
QualType T = InstantiateType(Arg.getAsType(), TemplateArgs,
Arg.getLocation(), DeclarationName());
if (T.isNull())
return TemplateArgument();
return TemplateArgument(Arg.getLocation(), T);
}
case TemplateArgument::Declaration:
// FIXME: Template instantiation for template template parameters.
return Arg;
case TemplateArgument::Integral:
return Arg;
case TemplateArgument::Expression: {
Sema::OwningExprResult E = InstantiateExpr(Arg.getAsExpr(), TemplateArgs);
if (E.isInvalid())
return TemplateArgument();
return TemplateArgument(E.takeAs<Expr>());
}
}
assert(false && "Unhandled template argument kind");
return TemplateArgument();
}

View File

@ -112,6 +112,14 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
assert(NTTP->getDepth() == 0 && "No nested templates yet");
const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
// The template argument itself might be an expression, in which
// case we just return that expression.
if (Arg.getKind() == TemplateArgument::Expression)
// FIXME: Clone the expression!
return SemaRef.Owned(Arg.getAsExpr());
assert(Arg.getKind() == TemplateArgument::Integral);
QualType T = Arg.getIntegralType();
if (T->isCharType() || T->isWideCharType())
return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(

View File

@ -260,7 +260,7 @@ Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) {
return SemaRef.StmtError();
return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
move(Cond));
SourceLocation(), move(Cond), S->getRParenLoc());
}
Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) {

View File

@ -600,7 +600,93 @@ QualType Sema::BuildFunctionType(QualType T,
return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic,
Quals);
}
/// \brief Build a member pointer type \c T Class::*.
///
/// \param T the type to which the member pointer refers.
/// \param Class the class type into which the member pointer points.
/// \param Quals Qualifiers applied to the member pointer type
/// \param Loc the location where this type begins
/// \param Entity the name of the entity that will have this member pointer type
///
/// \returns a member pointer type, if successful, or a NULL type if there was
/// an error.
QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
unsigned Quals, SourceLocation Loc,
DeclarationName Entity) {
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (CheckDistantExceptionSpec(T)) {
Diag(Loc, diag::err_distant_exception_spec);
// FIXME: If we're doing this as part of template instantiation,
// we should return immediately.
// Build the type anyway, but use the canonical type so that the
// exception specifiers are stripped off.
T = Context.getCanonicalType(T);
}
// C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
// with reference type, or "cv void."
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
<< (Entity? Entity.getAsString() : "type name");
return QualType();
}
if (T->isVoidType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
<< (Entity? Entity.getAsString() : "type name");
return QualType();
}
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
<< T;
// FIXME: If we're doing this as part of template instantiation,
// we should return immediately.
Quals &= ~QualType::Restrict;
}
if (!Class->isDependentType() && !Class->isRecordType()) {
Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
return QualType();
}
return Context.getMemberPointerType(T, Class.getTypePtr())
.getQualifiedType(Quals);
}
/// \brief Build a block pointer type.
///
/// \param T The type to which we'll be building a block pointer.
///
/// \param Quals The cvr-qualifiers to be applied to the block pointer type.
///
/// \param Loc The location of the entity whose type involves this
/// block pointer type or, if there is no such entity, the location of the
/// type that will have block pointer type.
///
/// \param Entity The name of the entity that involves the block pointer
/// type, if known.
///
/// \returns A suitable block pointer type, if there are no
/// errors. Otherwise, returns a NULL type.
QualType Sema::BuildBlockPointerType(QualType T, unsigned Quals,
SourceLocation Loc,
DeclarationName Entity) {
if (!T.getTypePtr()->isFunctionType()) {
Diag(Loc, diag::err_nonfunction_block_type);
return QualType();
}
return Context.getBlockPointerType(T).getQualifiedType(Quals);
}
/// GetTypeForDeclarator - Convert the type for the specified
/// declarator to Type instances. Skip the outermost Skip type
/// objects.
@ -675,11 +761,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
if (!LangOpts.Blocks)
Diag(DeclType.Loc, diag::err_blocks_disable);
if (!T.getTypePtr()->isFunctionType())
Diag(D.getIdentifierLoc(), diag::err_nonfunction_block_type);
else
T = (Context.getBlockPointerType(T)
.getQualifiedType(DeclType.Cls.TypeQuals));
T = BuildBlockPointerType(T, DeclType.Cls.TypeQuals, D.getIdentifierLoc(),
Name);
break;
case DeclaratorChunk::Pointer:
// Verify that we're not building a pointer to pointer to function with
@ -870,57 +953,32 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
break;
}
case DeclaratorChunk::MemberPointer:
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
D.setInvalidType(true);
// Build the type anyway.
}
// The scope spec must refer to a class, or be dependent.
DeclContext *DC = computeDeclContext(DeclType.Mem.Scope());
QualType ClsType;
// FIXME: Extend for dependent types when it's actually supported.
// See ActOnCXXNestedNameSpecifier.
if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC)) {
if (isDependentScopeSpecifier(DeclType.Mem.Scope())) {
NestedNameSpecifier *NNS
= (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
assert(NNS->getAsType() && "Nested-name-specifier must name a type");
ClsType = QualType(NNS->getAsType(), 0);
} else if (CXXRecordDecl *RD
= dyn_cast_or_null<CXXRecordDecl>(
computeDeclContext(DeclType.Mem.Scope()))) {
ClsType = Context.getTagDeclType(RD);
} else {
if (DC) {
Diag(DeclType.Mem.Scope().getBeginLoc(),
diag::err_illegal_decl_mempointer_in_nonclass)
<< (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
<< DeclType.Mem.Scope().getRange();
}
Diag(DeclType.Mem.Scope().getBeginLoc(),
diag::err_illegal_decl_mempointer_in_nonclass)
<< (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
<< DeclType.Mem.Scope().getRange();
D.setInvalidType(true);
ClsType = Context.IntTy;
}
// C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
// with reference type, or "cv void."
if (T->isReferenceType()) {
Diag(DeclType.Loc, diag::err_illegal_decl_pointer_to_reference)
<< (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
if (!ClsType.isNull())
T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,
DeclType.Loc, D.getIdentifier());
if (T.isNull()) {
T = Context.IntTy;
D.setInvalidType(true);
T = Context.IntTy;
}
if (T->isVoidType()) {
Diag(DeclType.Loc, diag::err_illegal_decl_mempointer_to_void)
<< (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
T = Context.IntTy;
}
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
if ((DeclType.Mem.TypeQuals & QualType::Restrict) &&
!T->isIncompleteOrObjectType()) {
Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
<< T;
DeclType.Mem.TypeQuals &= ~QualType::Restrict;
}
T = Context.getMemberPointerType(T, ClsType.getTypePtr()).
getQualifiedType(DeclType.Mem.TypeQuals);
break;
}

View File

@ -148,3 +148,13 @@ void f15() {
if (a[1]) // no-warning
1;
}
struct s3 p[1];
// Code from postgresql.
// Current cast logic of region store mistakenly leaves the final result region
// an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
// assigns to 'a'.
void f16(struct s3 *p) {
struct s3 a = *((struct s3*) ((char*) &p[0]));
}

View File

@ -0,0 +1,11 @@
// RUN: clang-cc -verify %s
// XFAIL
void f0(void) {
inline void f1(); // expected-error {{'inline' is not allowed on block scope function declaration}}
}
// FIXME: Add test for "If the inline specifier is used in a friend declaration,
// that declaration shall be a definition or the function shall have previously
// been declared inline.

View File

@ -0,0 +1,7 @@
// RUN: clang-cc -verify %s
// XFAIL
void f0() {
}
inline void f0(); // expected-error {{function definition cannot preceed inline declaration}}

View File

@ -0,0 +1,13 @@
// RUN: clang-cc -verify %s
// XFAIL
class A {
public:
explicit A();
explicit operator int(); // expected-warning {{explicit conversion functions are a C++0x extension}}
explicit void f0(); // expected-error {{'explicit' cannot only be applied to constructor or conversion function}}
};
explicit A::A() { } // expected-error {{'explicit' cannot be specified outside class definition}}

View File

@ -0,0 +1,14 @@
// RUN: clang-cc -verify %s
// XFAIL
typedef const int T0;
typedef int& T1;
struct s0 {
mutable const int f0; // expected-error{{'mutable' and 'const' cannot be mixed}}
mutable T0 f1; // expected-error{{'mutable' and 'const' cannot be mixed}}
mutable int &f2; // expected-error{{'mutable' cannot be applied to references}}
mutable T1 f3; // expected-error{{'mutable' cannot be applied to references}}
mutable struct s1 {}; // expected-error{{'mutable' cannot be applied to non-data members}}
mutable void im0(); // expected-error{{'mutable' cannot be applied to functions}}
};

View File

@ -0,0 +1,12 @@
// RUN: clang-cc -verify %s
struct S; // expected-note {{forward declaration of 'struct S'}}
extern S a;
extern S f();
extern void g(S a); // expected-note {{candidate function}}
void h() {
// FIXME: This diagnostic could be better.
g(a); // expected-error {{no matching function for call to 'g'}}
f(); // expected-error {{return type of called function ('struct S') is incomplete}}
}

View File

@ -0,0 +1,8 @@
// RUN: clang-cc -verify %s
typedef struct s { int x; } s;
typedef int I;
typedef int I2;
typedef I2 I; // expected-note {{previous definition is here}}
typedef char I; // expected-error {{typedef redefinition with different types}}

View File

@ -0,0 +1,9 @@
// RUN: clang-cc -verify %s
// XFAIL
struct S {
typedef struct A {} A; // expected-note {{previous definition is here}}
typedef struct B B;
typedef A A; // expected-error {{redefinition of 'A'}}
};

View File

@ -0,0 +1 @@
// Paragraph 1 is descriptive, and therefore requires no tests.

View File

@ -0,0 +1,12 @@
// RUN: clang-cc -fsyntax-only -verify %s
template<typename> struct Y1;
template<typename, int> struct Y2;
template<class T1, class T2 = int> class B2;
template<class T1 = int, class T2> class B2;
template<template<class, int> class, template<class> class = Y1> class B2t;
template<template<class, int> class = Y2, template<class> class> class B2t;
template<int N, int M = 5> class B2n;
template<int N = 5, int M> class B2n;

View File

@ -0,0 +1,15 @@
// RUN: clang-cc -fsyntax-only -verify %s
template<typename> struct Y1;
template<typename, int> struct Y2;
template<class T1 = int, // expected-note{{previous default template argument defined here}}
class T2> // expected-error{{template parameter missing a default argument}}
class B1;
template<template<class> class = Y1, // expected-note{{previous default template argument defined here}}
template<class> class> // expected-error{{template parameter missing a default argument}}
class B1t;
template<int N = 5, // expected-note{{previous default template argument defined here}}
int M> // expected-error{{template parameter missing a default argument}}
class B1n;

View File

@ -0,0 +1,37 @@
// RUN: clang-cc -fsyntax-only -verify %s
template<typename> struct Y1; // expected-note{{too few template parameters in template template argument}}
template<typename, int> struct Y2;
// C++ [temp.param]p12:
template<class T1,
class T2 = int> // expected-note{{previous default template argument defined here}}
class B3;
template<class T1, typename T2> class B3;
template<class T1,
typename T2 = float> // expected-error{{template parameter redefines default argument}}
class B3;
template<template<class, int> class,
template<class> class = Y1> // expected-note{{previous default template argument defined here}}
class B3t;
template<template<class, int> class, template<class> class> class B3t;
template<template<class, int> class,
template<class> class = Y1> // expected-error{{template parameter redefines default argument}}
class B3t;
template<int N,
int M = 5> // expected-note{{previous default template argument defined here}}
class B3n;
template<int N, int M> class B3n;
template<int N,
int M = 7> // expected-error{{template parameter redefines default argument}}
class B3n;
// Check validity of default arguments
template<template<class, int> class // expected-note{{previous template template parameter is here}}
= Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
class C1;

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