Import Clang r73340.
This commit is contained in:
parent
8ba99c0032
commit
7ef7bab7e3
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 "panic" 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 "no return" 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 "no return" 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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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")
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -4,7 +4,6 @@ add_clang_library(clangAST
|
|||
APValue.cpp
|
||||
ASTConsumer.cpp
|
||||
ASTContext.cpp
|
||||
Builtins.cpp
|
||||
CFG.cpp
|
||||
DeclarationName.cpp
|
||||
DeclBase.cpp
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -527,6 +527,9 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) {
|
|||
else
|
||||
Out << "class ";
|
||||
|
||||
if (TTP->isParameterPack())
|
||||
Out << "... ";
|
||||
|
||||
Out << ParamType.getAsString(Policy);
|
||||
|
||||
if (TTP->hasDefaultArgument()) {
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
set(LLVM_NO_RTTI 1)
|
||||
|
||||
add_clang_library(clangBasic
|
||||
Builtins.cpp
|
||||
ConvertUTF.c
|
||||
Diagnostic.cpp
|
||||
FileManager.cpp
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 {"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
229
lib/Sema/Sema.h
229
lib/Sema/Sema.h
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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]));
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
// RUN: clang-cc -verify %s
|
||||
// XFAIL
|
||||
|
||||
void f0() {
|
||||
}
|
||||
|
||||
inline void f0(); // expected-error {{function definition cannot preceed inline declaration}}
|
|
@ -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}}
|
|
@ -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}}
|
||||
};
|
|
@ -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}}
|
||||
}
|
|
@ -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}}
|
|
@ -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'}}
|
||||
};
|
||||
|
|
@ -0,0 +1 @@
|
|||
// Paragraph 1 is descriptive, and therefore requires no tests.
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
Loading…
Reference in New Issue