aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEd Schouten <ed@FreeBSD.org>2009-06-14 09:24:02 +0000
committerEd Schouten <ed@FreeBSD.org>2009-06-14 09:24:02 +0000
commit7ef7bab7e3d06f660b059b903c231f100bb13cc5 (patch)
treed472a7615b5c7e413aa62a77d0777c1a9cf76478
parent8ba99c00327a4394e7568244d6cffd6e62625a7a (diff)
downloadsrc-7ef7bab7e3d06f660b059b903c231f100bb13cc5.tar.gz
src-7ef7bab7e3d06f660b059b903c231f100bb13cc5.zip
Import Clang r73340.vendor/clang/clang-r73340
Notes
Notes: svn path=/vendor/clang/dist/; revision=194179 svn path=/vendor/clang/clang-r73340/; revision=194181; tag=vendor/clang/clang-r73340
-rw-r--r--CMakeLists.txt2
-rw-r--r--clang.xcodeproj/project.pbxproj32
-rw-r--r--docs/LanguageExtensions.html87
-rw-r--r--docs/PCHInternals.html11
-rw-r--r--docs/UsersManual.html44
-rw-r--r--include/clang/AST/ASTContext.h29
-rw-r--r--include/clang/AST/ASTDiagnostic.h2
-rw-r--r--include/clang/AST/Attr.h8
-rw-r--r--include/clang/AST/DeclBase.h6
-rw-r--r--include/clang/AST/DeclTemplate.h51
-rw-r--r--include/clang/AST/Stmt.h13
-rw-r--r--include/clang/Analysis/AnalysisDiagnostic.h2
-rw-r--r--include/clang/Basic/Builtins.def (renamed from include/clang/AST/Builtins.def)0
-rw-r--r--include/clang/Basic/Builtins.h (renamed from include/clang/AST/Builtins.h)31
-rw-r--r--include/clang/Basic/BuiltinsPPC.def (renamed from include/clang/AST/PPCBuiltins.def)4
-rw-r--r--include/clang/Basic/BuiltinsX86.def (renamed from include/clang/AST/X86Builtins.def)4
-rw-r--r--include/clang/Basic/Diagnostic.h55
-rw-r--r--include/clang/Basic/Diagnostic.td3
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td9
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td72
-rw-r--r--include/clang/Basic/SourceManager.h6
-rw-r--r--include/clang/Basic/TargetBuiltins.h (renamed from include/clang/AST/TargetBuiltins.h)10
-rw-r--r--include/clang/Driver/DriverDiagnostic.h2
-rw-r--r--include/clang/Driver/Options.def2
-rw-r--r--include/clang/Frontend/FrontendDiagnostic.h2
-rw-r--r--include/clang/Lex/LexDiagnostic.h2
-rw-r--r--include/clang/Lex/Preprocessor.h11
-rw-r--r--include/clang/Parse/Action.h20
-rw-r--r--include/clang/Parse/ParseDiagnostic.h2
-rw-r--r--include/clang/Parse/Parser.h7
-rw-r--r--include/clang/Sema/SemaDiagnostic.h2
-rw-r--r--lib/AST/ASTContext.cpp217
-rw-r--r--lib/AST/Builtins.cpp290
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/Decl.cpp1
-rw-r--r--lib/AST/DeclBase.cpp7
-rw-r--r--lib/AST/DeclCXX.cpp7
-rw-r--r--lib/AST/DeclPrinter.cpp3
-rw-r--r--lib/AST/DeclTemplate.cpp27
-rw-r--r--lib/AST/Expr.cpp1
-rw-r--r--lib/AST/ExprConstant.cpp38
-rw-r--r--lib/Analysis/CFRefCount.cpp76
-rw-r--r--lib/Analysis/GRExprEngine.cpp1
-rw-r--r--lib/Analysis/RegionStore.cpp9
-rw-r--r--lib/Basic/Builtins.cpp92
-rw-r--r--lib/Basic/CMakeLists.txt1
-rw-r--r--lib/Basic/Diagnostic.cpp25
-rw-r--r--lib/Basic/Targets.cpp16
-rw-r--r--lib/CodeGen/CGBuiltin.cpp2
-rw-r--r--lib/CodeGen/CGCall.cpp40
-rw-r--r--lib/CodeGen/CGExpr.cpp3
-rw-r--r--lib/CodeGen/CGExprComplex.cpp48
-rw-r--r--lib/CodeGen/CGExprConstant.cpp1
-rw-r--r--lib/CodeGen/CGObjCMac.cpp2
-rw-r--r--lib/CodeGen/CodeGenModule.cpp13
-rw-r--r--lib/CodeGen/Mangle.cpp27
-rw-r--r--lib/CodeGen/TargetABIInfo.cpp38
-rw-r--r--lib/Driver/Tools.cpp16
-rw-r--r--lib/Frontend/Backend.cpp8
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp1
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp2
-rw-r--r--lib/Frontend/PrintParserCallbacks.cpp7
-rw-r--r--lib/Headers/xmmintrin.h3
-rw-r--r--lib/Lex/LiteralSupport.cpp5
-rw-r--r--lib/Lex/PPMacroExpansion.cpp95
-rw-r--r--lib/Parse/ParseDecl.cpp74
-rw-r--r--lib/Parse/ParseDeclCXX.cpp14
-rw-r--r--lib/Parse/ParseExpr.cpp8
-rw-r--r--lib/Parse/ParseStmt.cpp32
-rw-r--r--lib/Parse/ParseTemplate.cpp22
-rw-r--r--lib/Parse/ParseTentative.cpp5
-rw-r--r--lib/Sema/Sema.cpp5
-rw-r--r--lib/Sema/Sema.h229
-rw-r--r--lib/Sema/SemaDecl.cpp16
-rw-r--r--lib/Sema/SemaDeclAttr.cpp3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp15
-rw-r--r--lib/Sema/SemaExpr.cpp19
-rw-r--r--lib/Sema/SemaInherit.cpp6
-rw-r--r--lib/Sema/SemaInit.cpp2
-rw-r--r--lib/Sema/SemaLookup.cpp1
-rw-r--r--lib/Sema/SemaStmt.cpp5
-rw-r--r--lib/Sema/SemaTemplate.cpp439
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp756
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp200
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp8
-rw-r--r--lib/Sema/SemaTemplateInstantiateStmt.cpp2
-rw-r--r--lib/Sema/SemaType.cpp154
-rw-r--r--test/Analysis/array-struct.c10
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp11
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp7
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp13
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp14
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp12
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p3.cpp8
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp9
-rw-r--r--test/CXX/temp/temp.param/p1.cpp1
-rw-r--r--test/CXX/temp/temp.param/p10.cpp12
-rw-r--r--test/CXX/temp/temp.param/p11.cpp15
-rw-r--r--test/CXX/temp/temp.param/p12.cpp37
-rw-r--r--test/CXX/temp/temp.param/p13.cpp14
-rw-r--r--test/CXX/temp/temp.param/p14.cpp5
-rw-r--r--test/CXX/temp/temp.param/p15-cxx0x.cpp (renamed from test/SemaTemplate/right-angle-brackets-0x.cpp)0
-rw-r--r--test/CXX/temp/temp.param/p15.cpp (renamed from test/SemaTemplate/right-angle-brackets-98.cpp)0
-rw-r--r--test/CXX/temp/temp.param/p2.cpp16
-rw-r--r--test/CXX/temp/temp.param/p3.cpp28
-rw-r--r--test/CXX/temp/temp.param/p4.cpp20
-rw-r--r--test/CXX/temp/temp.param/p7.cpp15
-rw-r--r--test/CXX/temp/temp.param/p8.cpp6
-rw-r--r--test/CodeGen/always_inline.c9
-rw-r--r--test/CodeGen/lineno-dbginfo.c7
-rw-r--r--test/CodeGen/target-data.c7
-rw-r--r--test/CodeGen/x86_32-arguments.c5
-rw-r--r--test/CodeGenCXX/static-assert.cpp3
-rw-r--r--test/CodeGenObjC/property-complex.m61
-rw-r--r--test/Driver/clang_f_opts.c3
-rw-r--r--test/Frontend/cpp-output.c15
-rw-r--r--test/Lexer/char-escapes.c21
-rw-r--r--test/Makefile33
-rw-r--r--test/Parser/statements.c3
-rw-r--r--test/Preprocessor/feature_tests.c31
-rw-r--r--test/Sema/const-eval.c2
-rw-r--r--test/Sema/init-vector.c17
-rw-r--r--test/SemaCXX/default2.cpp10
-rw-r--r--test/SemaCXX/member-pointer.cpp3
-rw-r--r--test/SemaTemplate/default-arguments.cpp9
-rw-r--r--test/SemaTemplate/dependent-names.cpp16
-rw-r--r--test/SemaTemplate/example-typelist.cpp98
-rw-r--r--test/SemaTemplate/instantiate-declref-ice.cpp7
-rw-r--r--test/SemaTemplate/instantiate-dependent-nested-name.cpp7
-rw-r--r--test/SemaTemplate/instantiate-function-1.cpp8
-rw-r--r--test/SemaTemplate/instantiate-member-pointers.cpp27
-rw-r--r--test/SemaTemplate/metafun-apply.cpp6
-rw-r--r--test/SemaTemplate/temp_class_spec.cpp127
-rw-r--r--test/SemaTemplate/temp_class_spec_blocks.cpp34
-rw-r--r--test/SemaTemplate/temp_class_spec_neg.cpp45
-rw-r--r--test/SemaTemplate/temp_param.cpp90
-rw-r--r--test/SemaTemplate/typename-specifier-3.cpp19
-rw-r--r--test/SemaTemplate/variadic-class-template-1.cpp4
-rw-r--r--test/SemaTemplate/variadic-class-template-2.cpp19
-rw-r--r--test/SemaTemplate/variadic-parse.cpp6
-rw-r--r--test/SemaTemplate/variadic-unsupported.cpp5
-rw-r--r--test/cxx-sections.data1954
-rwxr-xr-xtest/make_test_dirs.pl27
-rw-r--r--tools/clang-cc/clang-cc.cpp17
-rw-r--r--www/OpenProjects.html17
-rw-r--r--www/StaticAnalysis.html139
-rw-r--r--www/StaticAnalysisUsage.html259
-rw-r--r--www/analyzer/annotations.html386
-rw-r--r--www/analyzer/available_checks.html34
-rw-r--r--www/analyzer/content.css31
-rw-r--r--www/analyzer/filing_bugs.html62
-rw-r--r--www/analyzer/index.html186
-rw-r--r--www/analyzer/installation.html113
-rw-r--r--www/analyzer/latest_checker.html.incl (renamed from www/latest_checker.html.incl)0
-rw-r--r--www/analyzer/menu.css40
-rw-r--r--www/analyzer/menu.html.incl28
-rw-r--r--www/analyzer/scan-build.html257
-rw-r--r--www/cxx_status.html34
-rw-r--r--www/menu.html.incl2
160 files changed, 6771 insertions, 1498 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 45f3d0c56b91..2f63051a0da4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index b9b966eb57cc..73ef1beeca37 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -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;
};
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index c486562b1009..c855a5057a62 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -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,12 +46,73 @@ td {
<!-- ======================================================================= -->
<p>This document describes the language extensions provided by Clang. In
-addition to the langauge extensions listed here, Clang aims to support a broad
+addition to the language extensions listed here, Clang aims to support a broad
range of GCC extensions. Please see the <a
href="http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html">GCC manual</a> for
more information on these extensions.</p>
<!-- ======================================================================= -->
+<h2 id="feature_check">Feature Checking Macros</h2>
+<!-- ======================================================================= -->
+
+<p>Language extensions can be very useful, but only if you know you can depend
+on them. In order to allow fine-grain features checks, we support two builtin
+function-like macros. This allows you to directly test for a feature in your
+code without having to resort to something like autoconf or fragile "compiler
+version checks".</p>
+
+<!-- ======================================================================= -->
+<h3 id="__has_builtin">__has_builtin</h3>
+<!-- ======================================================================= -->
+
+<p>This function-like macro takes a single identifier argument that is the name
+of a builtin function. It evaluates to 1 if the builtin is supported or 0 if
+not. It can be used like this:</p>
+
+<blockquote>
+<pre>
+#ifndef __has_builtin // Optional of course.
+ #define __has_builtin(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+...
+#if __has_builtin(__builtin_trap)
+ __builtin_trap();
+#else
+ abort();
+#endif
+...
+</pre>
+</blockquote>
+
+
+<!-- ======================================================================= -->
+<h3 id="__has_feature">__has_feature</h3>
+<!-- ======================================================================= -->
+
+<p>This function-like macro takes a single identifier argument that is the name
+of a feature. It evaluates to 1 if the feature is supported or 0 if not. It
+can be used like this:</p>
+
+<blockquote>
+<pre>
+#ifndef __has_feature // Optional of course.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+...
+#if __has_feature(attribute_overloadable) || \
+ __has_feature(blocks)
+...
+#endif
+...
+</pre>
+</blockquote>
+
+<p>The feature tag is described along with the language feature below.</p>
+
+
+<!-- ======================================================================= -->
<h2 id="builtinmacros">Builtin Macros</h2>
<!-- ======================================================================= -->
@@ -64,6 +126,8 @@ more information on these extensions.</p>
with V.xyzw syntax and other tidbits. See also <a
href="#__builtin_shufflevector">__builtin_shufflevector</a>.</p>
+<p>Query for this feature with __has_feature(attribute_ext_vector_type).</p>
+
<!-- ======================================================================= -->
<h2 id="blocks">Blocks</h2>
<!-- ======================================================================= -->
@@ -73,6 +137,9 @@ href="BlockLanguageSpec.txt">BlockLanguageSpec.txt</a>. Implementation and ABI
details for the clang implementation are in <a
href="BlockImplementation.txt">BlockImplementation.txt</a>.</p>
+
+<p>Query for this feature with __has_feature(blocks).</p>
+
<!-- ======================================================================= -->
<h2 id="overloading-in-c">Function Overloading in C</h2>
<!-- ======================================================================= -->
@@ -171,6 +238,9 @@ caveats to this use of name mangling:</p>
C.</li>
</ul>
+<p>Query for this feature with __has_feature(attribute_overloadable).</p>
+
+
<!-- ======================================================================= -->
<h2 id="builtins">Builtin Functions</h2>
<!-- ======================================================================= -->
@@ -306,11 +376,11 @@ positives due to false paths) by marking their own &quot;panic&quot; functions
with this attribute.</p>
<p>While useful, <tt>noreturn</tt> is not applicable in all cases. Sometimes
-there are special functions that for all intensive purposes should be considered
-panic functions (i.e., they are only called when an internal program error
-occurs) but may actually return so that the program can fail gracefully. The
-<tt>analyzer_noreturn</tt> attribute allows one to annotate such functions as
-being interpreted as &quot;no return&quot; functions by the analyzer (thus
+there are special functions that for all intents and purposes should be
+considered panic functions (i.e., they are only called when an internal program
+error occurs) but may actually return so that the program can fail gracefully.
+The <tt>analyzer_noreturn</tt> attribute allows one to annotate such functions
+as being interpreted as &quot;no return&quot; functions by the analyzer (thus
pruning bogus paths) but will not affect compilation (as in the case of
<tt>noreturn</tt>).</p>
@@ -320,7 +390,10 @@ placed at the end of function prototypes:</p>
<pre>
void foo() <b>__attribute__((analyzer_noreturn))</b>;
-</p>
+</pre>
+
+<p>Query for this feature with __has_feature(attribute_analyzer_noreturn).</p>
+
</div>
</body>
diff --git a/docs/PCHInternals.html b/docs/PCHInternals.html
index 6ea1692773ab..b34b6a29ccbc 100644
--- a/docs/PCHInternals.html
+++ b/docs/PCHInternals.html
@@ -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
diff --git a/docs/UsersManual.html b/docs/UsersManual.html
index 221e07cdfd52..65415eea48d5 100644
--- a/docs/UsersManual.html
+++ b/docs/UsersManual.html
@@ -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>
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index b02faa8ff378..f4313f4dbfff 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -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;
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 244ca9e10f3a..e9f150574b05 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -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
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 0427f0003a3a..a5b7ad4ca382 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -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.
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index c061b857063a..5c9fd342fa96 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -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; }
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index d1899006cc82..a480f54394c6 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -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);
}
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 3656333d7423..a8688f62e2d9 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -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;
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
index e82dc9ed9f3f..3ee733518595 100644
--- a/include/clang/Analysis/AnalysisDiagnostic.h
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -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
diff --git a/include/clang/AST/Builtins.def b/include/clang/Basic/Builtins.def
index c2f4061c5d78..c2f4061c5d78 100644
--- a/include/clang/AST/Builtins.def
+++ b/include/clang/Basic/Builtins.def
diff --git a/include/clang/AST/Builtins.h b/include/clang/Basic/Builtins.h
index b16d3bf34139..6463a4f6e51b 100644
--- a/include/clang/AST/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -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;
};
diff --git a/include/clang/AST/PPCBuiltins.def b/include/clang/Basic/BuiltinsPPC.def
index b8c791286e55..817a032d9237 100644
--- a/include/clang/AST/PPCBuiltins.def
+++ b/include/clang/Basic/BuiltinsPPC.def
@@ -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")
diff --git a/include/clang/AST/X86Builtins.def b/include/clang/Basic/BuiltinsX86.def
index 85381c0762d5..2af95808b281 100644
--- a/include/clang/AST/X86Builtins.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -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.
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 22e7fb3f85ea..207710bdff31 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -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;
}
};
diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td
index 67d8eaafc9ec..6aa3b438abd8 100644
--- a/include/clang/Basic/Diagnostic.td
+++ b/include/clang/Basic/Diagnostic.td
@@ -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"
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 3d1f9320cd41..6ca50db50a8a 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.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<
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 81afac9a602e..e2b9eb7a20b8 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4b9b7037e161..fa4f430591b2 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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 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">;
+ "class template %select{|partial }0specialization of %1 must occur in the "
+ "global scope">;
def err_template_spec_decl_out_of_scope : Error<
- "class template specialization of %0 not in namespace %1">;
+ "class template %select{|partial }0specialization of %1 not in namespace %2">;
def err_template_spec_decl_function_scope : Error<
- "%select{class template specialization|explicit instantiation}0 of %1 "
- "in function scope">;
+ "%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|explicit instantiation}0 of %1 "
- "not in a namespace enclosing %2">;
+ "%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|explicit instantiation}0 of %1 must "
- "occur at global scope">;
+ "%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">;
// 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">;
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 43369829387d..57ae9a45114d 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -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
//===--------------------------------------------------------------------===//
diff --git a/include/clang/AST/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index d425a9b8ecad..d2e949501748 100644
--- a/include/clang/AST/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -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
};
}
diff --git a/include/clang/Driver/DriverDiagnostic.h b/include/clang/Driver/DriverDiagnostic.h
index 2a4413c24e07..705c3422cda3 100644
--- a/include/clang/Driver/DriverDiagnostic.h
+++ b/include/clang/Driver/DriverDiagnostic.h
@@ -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
diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def
index 742a04a5e344..7045f145ee51 100644
--- a/include/clang/Driver/Options.def
+++ b/include/clang/Driver/Options.def
@@ -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)
diff --git a/include/clang/Frontend/FrontendDiagnostic.h b/include/clang/Frontend/FrontendDiagnostic.h
index 02432ca3a55c..079abae3eee1 100644
--- a/include/clang/Frontend/FrontendDiagnostic.h
+++ b/include/clang/Frontend/FrontendDiagnostic.h
@@ -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
diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h
index 1502efb55e63..03d9b7b3bbb8 100644
--- a/include/clang/Lex/LexDiagnostic.h
+++ b/include/clang/Lex/LexDiagnostic.h
@@ -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
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 5b9959c32a2d..f229881bfc44 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -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
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 579fe6cb038c..f1207e4f0f73 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -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,
diff --git a/include/clang/Parse/ParseDiagnostic.h b/include/clang/Parse/ParseDiagnostic.h
index a85c6ad6ca7a..fa600ddadfab 100644
--- a/include/clang/Parse/ParseDiagnostic.h
+++ b/include/clang/Parse/ParseDiagnostic.h
@@ -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
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 6125fc633d07..d613ae132935 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -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
diff --git a/include/clang/Sema/SemaDiagnostic.h b/include/clang/Sema/SemaDiagnostic.h
index e215ed48fbe5..de92844f4d6a 100644
--- a/include/clang/Sema/SemaDiagnostic.h
+++ b/include/clang/Sema/SemaDiagnostic.h
@@ -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
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index fb28fd436700..7ed9e45fcee9 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -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);
+}
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
deleted file mode 100644
index 8368febe5a05..000000000000
--- a/lib/AST/Builtins.cpp
+++ /dev/null
@@ -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);
-}
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 19ab9f650eda..ac4cbb2d296e 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -4,7 +4,6 @@ add_clang_library(clangAST
APValue.cpp
ASTConsumer.cpp
ASTContext.cpp
- Builtins.cpp
CFG.cpp
DeclarationName.cpp
DeclBase.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index dfec1061c25a..a3e406b2452e 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.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>
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index fd7de715db7f..a39a506de0ae 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 94daf484458a..8430da2be6b1 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -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();
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index f231abf89e01..2b06e93295bc 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -527,6 +527,9 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) {
else
Out << "class ";
+ if (TTP->isParameterPack())
+ Out << "... ";
+
Out << ParamType.getAsString(Policy);
if (TTP->hasDefaultArgument()) {
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index a53416433e03..5b1bf9b3afc5 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index c12dd6747c6d..309be4175ffa 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -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;
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 8e3c3ce2d309..4815ae5c3b94 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -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();
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 532d16da0f0e..f5ca322b6884 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -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);
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index e8c5be51d6ac..7a8fef58bb21 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -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"
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 02d3d1f885f9..eae3aefe218f 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -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()),
diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
new file mode 100644
index 000000000000..ebe0514fa008
--- /dev/null
+++ b/lib/Basic/Builtins.cpp
@@ -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;
+}
+
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index 1cbf11c2bfbb..e0e9a10e5195 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -1,6 +1,7 @@
set(LLVM_NO_RTTI 1)
add_clang_library(clangBasic
+ Builtins.cpp
ConvertUTF.c
Diagnostic.cpp
FileManager.cpp
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 3b3d61b08d0d..323f7a7d4afd 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.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;
}
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index b4e32e9d9f37..13758ad18308 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -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 {"
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index f9c44c89656e..a919dfa2e32c 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -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;
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index b10b9c2d9de1..4037f32ac186 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -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
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index c52e6bd0c5c7..eb0db611159b 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -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(),
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 41fb725fdf72..e1332ff29080 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -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.
- EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified());
- // And now return the LHS
+
+ // 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());
+ }
+
+ // 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) {
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index b30bafb51051..0e21a00f30fe 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -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"
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 75755ece76f1..bd5b05acf94a 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -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
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 5c12c81b36be..82156e9ffa5c 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -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.
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 6ee1223a0059..14392ab6e79f 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -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";
diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp
index 6f7bea2340a9..361e5c0005cc 100644
--- a/lib/CodeGen/TargetABIInfo.cpp
+++ b/lib/CodeGen/TargetABIInfo.cpp
@@ -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());
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 6b082c8bdf74..bfc247a015ff 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -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.
diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp
index 9560b61e1ba1..d8f8625d6740 100644
--- a/lib/Frontend/Backend.cpp
+++ b/lib/Frontend/Backend.cpp
@@ -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;
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index 10059f609b10..e6871e3a0eb6 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -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;
}
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index b7caee5e5510..73dea1061c28 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -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;
}
diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp
index b9fe0680afd0..170ab5e33f5a 100644
--- a/lib/Frontend/PrintParserCallbacks.cpp
+++ b/lib/Frontend/PrintParserCallbacks.cpp
@@ -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";
}
diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h
index 4938399063cd..5d2bcbb98ca0 100644
--- a/lib/Headers/xmmintrin.h
+++ b/lib/Headers/xmmintrin.h
@@ -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__ */
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index 4d10974df2c6..37ea52b46f9d 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -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;
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 55222c944a2b..286705181cce 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -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!");
}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 9aab3b9e790d..9073c6dbd193 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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();
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 0e8eebce5c7c..498eaf19cd66 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -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;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index cd62c64276b3..3fee78bb719f 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -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;
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index f041d7dfd790..955f00d7a0b5 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -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
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 2a79b99d29c9..a9f75d8be17d 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -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);
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 81696d6a6101..f31855b751fc 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -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:
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index e3cea5be4283..a5f243816abd 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -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
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index c5582935db7f..0607a893da86 100644
--- a/lib/Sema/Sema.h
+++ b/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);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c67af295c18c..b995717ac87c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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));
}
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 99b4d77fad42..1afdb6011dff 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -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:
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b59ac879d190..8f64e78c522b 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index da32d4ec1061..c01c812be601 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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);
diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp
index 1b968f0fbcce..28ca5f64ef59 100644
--- a/lib/Sema/SemaInherit.cpp
+++ b/lib/Sema/SemaInherit.cpp
@@ -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.
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 4e0eb1d431fe..45085962d488 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -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;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 6212449744ca..1d26845fd8e4 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -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"
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 15262e9c3ac2..aa9b8db0c9f2 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -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
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index f9176ca470c0..b2a82ed74d51 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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;
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index db7e622f7f68..84d802d1bf89 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -20,6 +20,14 @@
#include "llvm/Support/Compiler.h"
using namespace clang;
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(ASTContext &Context,
+ TemplateParameterList *TemplateParams,
+ const TemplateArgument &Param,
+ const TemplateArgument &Arg,
+ Sema::TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced);
+
/// \brief If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
/// non-type template parameter.
@@ -35,12 +43,12 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
/// \brief Deduce the value of the given non-type template parameter
/// from the given constant.
-///
-/// \returns true if deduction succeeded, false otherwise.
-static bool DeduceNonTypeTemplateArgument(ASTContext &Context,
- NonTypeTemplateParmDecl *NTTP,
- llvm::APInt Value,
- llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(ASTContext &Context,
+ NonTypeTemplateParmDecl *NTTP,
+ llvm::APInt Value,
+ Sema::TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
@@ -48,25 +56,41 @@ static bool DeduceNonTypeTemplateArgument(ASTContext &Context,
Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(),
llvm::APSInt(Value),
NTTP->getType());
- return true;
+ return Sema::TDK_Success;
}
- if (Deduced[NTTP->getIndex()].getKind() != TemplateArgument::Integral)
- return false;
+ assert(Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral);
// If the template argument was previously deduced to a negative value,
// then our deduction fails.
const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral();
- assert(PrevValuePtr && "Not an integral template argument?");
- if (PrevValuePtr->isSigned() && PrevValuePtr->isNegative())
- return false;
-
+ if (PrevValuePtr->isSigned() && PrevValuePtr->isNegative()) {
+ // FIXME: This is wacky; we should be dealing with APSInts and
+ // checking the actual signs.
+ Info.Param = NTTP;
+ Info.FirstArg = Deduced[NTTP->getIndex()];
+ Info.SecondArg = TemplateArgument(SourceLocation(),
+ llvm::APSInt(Value),
+ NTTP->getType());
+ return Sema::TDK_Inconsistent;
+ }
+
llvm::APInt PrevValue = *PrevValuePtr;
if (Value.getBitWidth() > PrevValue.getBitWidth())
PrevValue.zext(Value.getBitWidth());
else if (Value.getBitWidth() < PrevValue.getBitWidth())
Value.zext(PrevValue.getBitWidth());
- return Value == PrevValue;
+
+ if (Value != PrevValue) {
+ Info.Param = NTTP;
+ Info.FirstArg = Deduced[NTTP->getIndex()];
+ Info.SecondArg = TemplateArgument(SourceLocation(),
+ llvm::APSInt(Value),
+ NTTP->getType());
+ return Sema::TDK_Inconsistent;
+ }
+
+ return Sema::TDK_Success;
}
/// \brief Deduce the value of the given non-type template parameter
@@ -74,10 +98,12 @@ static bool DeduceNonTypeTemplateArgument(ASTContext &Context,
///
/// \returns true if deduction succeeded, false otherwise.
-static bool DeduceNonTypeTemplateArgument(ASTContext &Context,
- NonTypeTemplateParmDecl *NTTP,
- Expr *Value,
- llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(ASTContext &Context,
+ NonTypeTemplateParmDecl *NTTP,
+ Expr *Value,
+ Sema::TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
assert((Value->isTypeDependent() || Value->isValueDependent()) &&
@@ -86,35 +112,73 @@ static bool DeduceNonTypeTemplateArgument(ASTContext &Context,
if (Deduced[NTTP->getIndex()].isNull()) {
// FIXME: Clone the Value?
Deduced[NTTP->getIndex()] = TemplateArgument(Value);
- return true;
+ return Sema::TDK_Success;
}
if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral) {
// Okay, we deduced a constant in one case and a dependent expression
// in another case. FIXME: Later, we will check that instantiating the
// dependent expression gives us the constant value.
- return true;
+ return Sema::TDK_Success;
}
// FIXME: Compare the expressions for equality!
- return true;
+ return Sema::TDK_Success;
}
-static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
- QualType Arg,
- llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(ASTContext &Context,
+ TemplateName Param,
+ TemplateName Arg,
+ Sema::TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+ // FIXME: Implement template argument deduction for template
+ // template parameters.
+
+ // FIXME: this routine does not have enough information to produce
+ // good diagnostics.
+
+ TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
+ TemplateDecl *ArgDecl = Arg.getAsTemplateDecl();
+
+ if (!ParamDecl || !ArgDecl) {
+ // FIXME: fill in Info.Param/Info.FirstArg
+ return Sema::TDK_Inconsistent;
+ }
+
+ ParamDecl = cast<TemplateDecl>(Context.getCanonicalDecl(ParamDecl));
+ ArgDecl = cast<TemplateDecl>(Context.getCanonicalDecl(ArgDecl));
+ if (ParamDecl != ArgDecl) {
+ // FIXME: fill in Info.Param/Info.FirstArg
+ return Sema::TDK_Inconsistent;
+ }
+
+ return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(ASTContext &Context,
+ TemplateParameterList *TemplateParams,
+ QualType ParamIn, QualType ArgIn,
+ Sema::TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
- Param = Context.getCanonicalType(Param);
- Arg = Context.getCanonicalType(Arg);
+ QualType Param = Context.getCanonicalType(ParamIn);
+ QualType Arg = Context.getCanonicalType(ArgIn);
// If the parameter type is not dependent, just compare the types
// directly.
- if (!Param->isDependentType())
- return Param == Arg;
+ if (!Param->isDependentType()) {
+ if (Param == Arg)
+ return Sema::TDK_Success;
+
+ Info.FirstArg = TemplateArgument(SourceLocation(), ParamIn);
+ Info.SecondArg = TemplateArgument(SourceLocation(), ArgIn);
+ return Sema::TDK_NonDeducedMismatch;
+ }
// C++ [temp.deduct.type]p9:
- //
// A template type argument T, a template template argument TT or a
// template non-type argument i can be deduced if P and A have one of
// the following forms:
@@ -123,16 +187,21 @@ static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
// cv-list T
if (const TemplateTypeParmType *TemplateTypeParm
= Param->getAsTemplateTypeParmType()) {
+ unsigned Index = TemplateTypeParm->getIndex();
+
// The argument type can not be less qualified than the parameter
// type.
- if (Param.isMoreQualifiedThan(Arg))
- return false;
+ if (Param.isMoreQualifiedThan(Arg)) {
+ Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+ Info.FirstArg = Deduced[Index];
+ Info.SecondArg = TemplateArgument(SourceLocation(), Arg);
+ return Sema::TDK_InconsistentQuals;
+ }
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers();
QualType DeducedType = Arg.getQualifiedType(Quals);
- unsigned Index = TemplateTypeParm->getIndex();
if (Deduced[Index].isNull())
Deduced[Index] = TemplateArgument(SourceLocation(), DeducedType);
@@ -143,55 +212,63 @@ static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
// deduced values, or if different pairs yield different deduced
// values, or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
- if (Deduced[Index].getAsType() != DeducedType)
- return false;
+ if (Deduced[Index].getAsType() != DeducedType) {
+ Info.Param
+ = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+ Info.FirstArg = Deduced[Index];
+ Info.SecondArg = TemplateArgument(SourceLocation(), Arg);
+ return Sema::TDK_Inconsistent;
+ }
}
- return true;
+ return Sema::TDK_Success;
}
+ // Set up the template argument deduction information for a failure.
+ Info.FirstArg = TemplateArgument(SourceLocation(), ParamIn);
+ Info.SecondArg = TemplateArgument(SourceLocation(), ArgIn);
+
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
- return false;
+ return Sema::TDK_NonDeducedMismatch;
switch (Param->getTypeClass()) {
// No deduction possible for these types
case Type::Builtin:
- return false;
-
+ return Sema::TDK_NonDeducedMismatch;
// T *
case Type::Pointer: {
const PointerType *PointerArg = Arg->getAsPointerType();
if (!PointerArg)
- return false;
+ return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context,
+ return DeduceTemplateArguments(Context, TemplateParams,
cast<PointerType>(Param)->getPointeeType(),
PointerArg->getPointeeType(),
- Deduced);
+ Info, Deduced);
}
// T &
case Type::LValueReference: {
const LValueReferenceType *ReferenceArg = Arg->getAsLValueReferenceType();
if (!ReferenceArg)
- return false;
+ return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context,
+ return DeduceTemplateArguments(Context, TemplateParams,
cast<LValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
- Deduced);
+ Info, Deduced);
}
// T && [C++0x]
case Type::RValueReference: {
const RValueReferenceType *ReferenceArg = Arg->getAsRValueReferenceType();
if (!ReferenceArg)
- return false;
+ return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context,
+ return DeduceTemplateArguments(Context, TemplateParams,
cast<RValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
- Deduced);
+ Info, Deduced);
}
// T [] (implied, but not stated explicitly)
@@ -199,12 +276,12 @@ static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
const IncompleteArrayType *IncompleteArrayArg =
Context.getAsIncompleteArrayType(Arg);
if (!IncompleteArrayArg)
- return false;
+ return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context,
+ return DeduceTemplateArguments(Context, TemplateParams,
Context.getAsIncompleteArrayType(Param)->getElementType(),
IncompleteArrayArg->getElementType(),
- Deduced);
+ Info, Deduced);
}
// T [integer-constant]
@@ -212,39 +289,40 @@ static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
const ConstantArrayType *ConstantArrayArg =
Context.getAsConstantArrayType(Arg);
if (!ConstantArrayArg)
- return false;
+ return Sema::TDK_NonDeducedMismatch;
const ConstantArrayType *ConstantArrayParm =
Context.getAsConstantArrayType(Param);
if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
- return false;
+ return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context,
+ return DeduceTemplateArguments(Context, TemplateParams,
ConstantArrayParm->getElementType(),
ConstantArrayArg->getElementType(),
- Deduced);
+ Info, Deduced);
}
// type [i]
case Type::DependentSizedArray: {
const ArrayType *ArrayArg = dyn_cast<ArrayType>(Arg);
if (!ArrayArg)
- return false;
+ return Sema::TDK_NonDeducedMismatch;
// Check the element type of the arrays
const DependentSizedArrayType *DependentArrayParm
= cast<DependentSizedArrayType>(Param);
- if (!DeduceTemplateArguments(Context,
- DependentArrayParm->getElementType(),
- ArrayArg->getElementType(),
- Deduced))
- return false;
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ DependentArrayParm->getElementType(),
+ ArrayArg->getElementType(),
+ Info, Deduced))
+ return Result;
// Determine the array bound is something we can deduce.
NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
if (!NTTP)
- return true;
+ return Sema::TDK_Success;
// We can perform template argument deduction for the given non-type
// template parameter.
@@ -254,59 +332,209 @@ static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
= dyn_cast<ConstantArrayType>(ArrayArg))
return DeduceNonTypeTemplateArgument(Context, NTTP,
ConstantArrayArg->getSize(),
- Deduced);
+ Info, Deduced);
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
return DeduceNonTypeTemplateArgument(Context, NTTP,
DependentArrayArg->getSizeExpr(),
- Deduced);
+ Info, Deduced);
// Incomplete type does not match a dependently-sized array type
- return false;
+ return Sema::TDK_NonDeducedMismatch;
}
+ // type(*)(T)
+ // T(*)()
+ // T(*)(T)
case Type::FunctionProto: {
const FunctionProtoType *FunctionProtoArg =
dyn_cast<FunctionProtoType>(Arg);
if (!FunctionProtoArg)
- return false;
+ return Sema::TDK_NonDeducedMismatch;
const FunctionProtoType *FunctionProtoParam =
cast<FunctionProtoType>(Param);
-
- // Check return types.
- if (!DeduceTemplateArguments(Context,
- FunctionProtoParam->getResultType(),
- FunctionProtoArg->getResultType(),
- Deduced))
- return false;
+
+ if (FunctionProtoParam->getTypeQuals() !=
+ FunctionProtoArg->getTypeQuals())
+ return Sema::TDK_NonDeducedMismatch;
if (FunctionProtoParam->getNumArgs() != FunctionProtoArg->getNumArgs())
- return false;
+ return Sema::TDK_NonDeducedMismatch;
+
+ if (FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Check return types.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ FunctionProtoParam->getResultType(),
+ FunctionProtoArg->getResultType(),
+ Info, Deduced))
+ return Result;
for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
// Check argument types.
- if (!DeduceTemplateArguments(Context,
- FunctionProtoParam->getArgType(I),
- FunctionProtoArg->getArgType(I),
- Deduced))
- return false;
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ FunctionProtoParam->getArgType(I),
+ FunctionProtoArg->getArgType(I),
+ Info, Deduced))
+ return Result;
}
- return true;
+ return Sema::TDK_Success;
}
+
+ // template-name<T> (wheretemplate-name refers to a class template)
+ // template-name<i>
+ // TT<T> (TODO)
+ // TT<i> (TODO)
+ // TT<> (TODO)
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *SpecParam
+ = cast<TemplateSpecializationType>(Param);
+
+ // Check whether the template argument is a dependent template-id.
+ // FIXME: This is untested code; it can be tested when we implement
+ // partial ordering of class template partial specializations.
+ if (const TemplateSpecializationType *SpecArg
+ = dyn_cast<TemplateSpecializationType>(Arg)) {
+ // Perform template argument deduction for the template name.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context,
+ SpecParam->getTemplateName(),
+ SpecArg->getTemplateName(),
+ Info, Deduced))
+ return Result;
+
+ unsigned NumArgs = SpecParam->getNumArgs();
+
+ // FIXME: When one of the template-names refers to a
+ // declaration with default template arguments, do we need to
+ // fill in those default template arguments here? Most likely,
+ // the answer is "yes", but I don't see any references. This
+ // issue may be resolved elsewhere, because we may want to
+ // instantiate default template arguments when
+ if (SpecArg->getNumArgs() != NumArgs)
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Perform template argument deduction on each template
+ // argument.
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ SpecParam->getArg(I),
+ SpecArg->getArg(I),
+ Info, Deduced))
+ return Result;
+
+ return Sema::TDK_Success;
+ }
+
+ // If the argument type is a class template specialization, we
+ // perform template argument deduction using its template
+ // arguments.
+ const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
+ if (!RecordArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ ClassTemplateSpecializationDecl *SpecArg
+ = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
+ if (!SpecArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Perform template argument deduction for the template name.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context,
+ SpecParam->getTemplateName(),
+ TemplateName(SpecArg->getSpecializedTemplate()),
+ Info, Deduced))
+ return Result;
+
+ // FIXME: Can the # of arguments in the parameter and the argument differ?
+ unsigned NumArgs = SpecParam->getNumArgs();
+ const TemplateArgumentList &ArgArgs = SpecArg->getTemplateArgs();
+ if (NumArgs != ArgArgs.size())
+ return Sema::TDK_NonDeducedMismatch;
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ SpecParam->getArg(I),
+ ArgArgs.get(I),
+ Info, Deduced))
+ return Result;
+ return Sema::TDK_Success;
+ }
+
+ // T type::*
+ // T T::*
+ // T (type::*)()
+ // type (T::*)()
+ // type (type::*)(T)
+ // type (T::*)(T)
+ // T (type::*)(T)
+ // T (T::*)()
+ // T (T::*)(T)
+ case Type::MemberPointer: {
+ const MemberPointerType *MemPtrParam = cast<MemberPointerType>(Param);
+ const MemberPointerType *MemPtrArg = dyn_cast<MemberPointerType>(Arg);
+ if (!MemPtrArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ MemPtrParam->getPointeeType(),
+ MemPtrArg->getPointeeType(),
+ Info, Deduced))
+ return Result;
+
+ return DeduceTemplateArguments(Context, TemplateParams,
+ QualType(MemPtrParam->getClass(), 0),
+ QualType(MemPtrArg->getClass(), 0),
+ Info, Deduced);
+ }
+
+ // (clang extension)
+ //
+ // type(^)(T)
+ // T(^)()
+ // T(^)(T)
+ case Type::BlockPointer: {
+ const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(Param);
+ const BlockPointerType *BlockPtrArg = dyn_cast<BlockPointerType>(Arg);
+
+ if (!BlockPtrArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ return DeduceTemplateArguments(Context, TemplateParams,
+ BlockPtrParam->getPointeeType(),
+ BlockPtrArg->getPointeeType(), Info,
+ Deduced);
+ }
+
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Typename:
+ // No template argument deduction for these types
+ return Sema::TDK_Success;
+
default:
break;
}
// FIXME: Many more cases to go (to go).
- return false;
+ return Sema::TDK_NonDeducedMismatch;
}
-static bool
-DeduceTemplateArguments(ASTContext &Context, const TemplateArgument &Param,
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(ASTContext &Context,
+ TemplateParameterList *TemplateParams,
+ const TemplateArgument &Param,
const TemplateArgument &Arg,
+ Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
switch (Param.getKind()) {
case TemplateArgument::Null:
@@ -315,24 +543,38 @@ DeduceTemplateArguments(ASTContext &Context, const TemplateArgument &Param,
case TemplateArgument::Type:
assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch");
- return DeduceTemplateArguments(Context, Param.getAsType(),
- Arg.getAsType(), Deduced);
+ return DeduceTemplateArguments(Context, TemplateParams,
+ Param.getAsType(),
+ Arg.getAsType(), Info, Deduced);
case TemplateArgument::Declaration:
// FIXME: Implement this check
assert(false && "Unimplemented template argument deduction case");
- return false;
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::Integral:
if (Arg.getKind() == TemplateArgument::Integral) {
// FIXME: Zero extension + sign checking here?
- return *Param.getAsIntegral() == *Arg.getAsIntegral();
+ if (*Param.getAsIntegral() == *Arg.getAsIntegral())
+ return Sema::TDK_Success;
+
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
}
- if (Arg.getKind() == TemplateArgument::Expression)
- return false;
assert(false && "Type/value mismatch");
- return false;
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::Expression: {
if (NonTypeTemplateParmDecl *NTTP
@@ -340,70 +582,114 @@ DeduceTemplateArguments(ASTContext &Context, const TemplateArgument &Param,
if (Arg.getKind() == TemplateArgument::Integral)
// FIXME: Sign problems here
return DeduceNonTypeTemplateArgument(Context, NTTP,
- *Arg.getAsIntegral(), Deduced);
+ *Arg.getAsIntegral(),
+ Info, Deduced);
if (Arg.getKind() == TemplateArgument::Expression)
return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(),
- Deduced);
+ Info, Deduced);
assert(false && "Type/value mismatch");
- return false;
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
}
// Can't deduce anything, but that's okay.
- return true;
+ return Sema::TDK_Success;
}
}
- return true;
+ return Sema::TDK_Success;
}
-static bool
+static Sema::TemplateDeductionResult
DeduceTemplateArguments(ASTContext &Context,
+ TemplateParameterList *TemplateParams,
const TemplateArgumentList &ParamList,
const TemplateArgumentList &ArgList,
+ Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
assert(ParamList.size() == ArgList.size());
for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
- if (!DeduceTemplateArguments(Context, ParamList[I], ArgList[I], Deduced))
- return false;
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ ParamList[I], ArgList[I],
+ Info, Deduced))
+ return Result;
}
- return true;
+ return Sema::TDK_Success;
}
-
-TemplateArgumentList *
+/// \brief Perform template argument deduction to determine whether
+/// the given template arguments match the given class template
+/// partial specialization per C++ [temp.class.spec.match].
+Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
- const TemplateArgumentList &TemplateArgs) {
- // Deduce the template arguments for the partial specialization
+ const TemplateArgumentList &TemplateArgs,
+ TemplateDeductionInfo &Info) {
+ // C++ [temp.class.spec.match]p2:
+ // A partial specialization matches a given actual template
+ // argument list if the template arguments of the partial
+ // specialization can be deduced from the actual template argument
+ // list (14.8.2).
+ SFINAETrap Trap(*this);
llvm::SmallVector<TemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
- if (! ::DeduceTemplateArguments(Context, Partial->getTemplateArgs(),
- TemplateArgs, Deduced))
- return 0;
-
- // FIXME: Substitute the deduced template arguments into the template
- // arguments of the class template partial specialization; the resulting
- // template arguments should match TemplateArgs exactly.
-
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(Context,
+ Partial->getTemplateParameters(),
+ Partial->getTemplateArgs(),
+ TemplateArgs, Info, Deduced))
+ return Result;
+
+ InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
+ Deduced.data(), Deduced.size());
+ if (Inst)
+ return TDK_InstantiationDepth;
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ TemplateArgumentListBuilder Builder(Context);
for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
- TemplateArgument &Arg = Deduced[I];
+ if (Deduced[I].isNull()) {
+ Decl *Param
+ = const_cast<Decl *>(Partial->getTemplateParameters()->getParam(I));
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ Info.Param = TTP;
+ else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ Info.Param = NTTP;
+ else
+ Info.Param = cast<TemplateTemplateParmDecl>(Param);
+ return TDK_Incomplete;
+ }
- // FIXME: If this template argument was not deduced, but the corresponding
- // template parameter has a default argument, instantiate the default
- // argument.
- if (Arg.isNull()) // FIXME: Result->Destroy(Context);
- return 0;
-
+ Builder.push_back(Deduced[I]);
+ }
+
+ // Form the template argument list from the deduced template arguments.
+ TemplateArgumentList *DeducedArgumentList
+ = new (Context) TemplateArgumentList(Context, Builder, /*CopyArgs=*/true,
+ /*FlattenArgs=*/true);
+ Info.reset(DeducedArgumentList);
+
+ // Now that we have all of the deduced template arguments, take
+ // another pass through them to convert any integral template
+ // arguments to the appropriate type.
+ for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+ TemplateArgument &Arg = Deduced[I];
if (Arg.getKind() == TemplateArgument::Integral) {
- // FIXME: Instantiate the type, but we need some context!
const NonTypeTemplateParmDecl *Parm
= cast<NonTypeTemplateParmDecl>(Partial->getTemplateParameters()
->getParam(I));
- // QualType T = InstantiateType(Parm->getType(), *Result,
- // Parm->getLocation(), Parm->getDeclName());
- // if (T.isNull()) // FIXME: Result->Destroy(Context);
- // return 0;
- QualType T = Parm->getType();
+ QualType T = InstantiateType(Parm->getType(), *DeducedArgumentList,
+ Parm->getLocation(), Parm->getDeclName());
+ if (T.isNull()) {
+ Info.Param = const_cast<NonTypeTemplateParmDecl*>(Parm);
+ Info.FirstArg = TemplateArgument(Parm->getLocation(), Parm->getType());
+ return TDK_SubstitutionFailure;
+ }
// FIXME: Make sure we didn't overflow our data type!
llvm::APSInt &Value = *Arg.getAsIntegral();
@@ -413,14 +699,220 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
Value.setIsSigned(T->isSignedIntegerType());
Arg.setIntegralType(T);
}
+
+ (*DeducedArgumentList)[I] = Arg;
}
-
- // FIXME: This is terrible. DeduceTemplateArguments should use a
- // TemplateArgumentListBuilder directly.
- TemplateArgumentListBuilder Builder(Context);
- for (unsigned I = 0, N = Deduced.size(); I != N; ++I)
- Builder.push_back(Deduced[I]);
-
- return new (Context) TemplateArgumentList(Context, Builder, /*CopyArgs=*/true,
- /*FlattenArgs=*/true);
+
+ // Substitute the deduced template arguments into the template
+ // arguments of the class template partial specialization, and
+ // verify that the instantiated template arguments are both valid
+ // and are equivalent to the template arguments originally provided
+ // to the class template.
+ ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
+ const TemplateArgumentList &PartialTemplateArgs = Partial->getTemplateArgs();
+ for (unsigned I = 0, N = PartialTemplateArgs.flat_size(); I != N; ++I) {
+ Decl *Param = const_cast<Decl *>(
+ ClassTemplate->getTemplateParameters()->getParam(I));
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ TemplateArgument InstArg = Instantiate(PartialTemplateArgs[I],
+ *DeducedArgumentList);
+ if (InstArg.getKind() != TemplateArgument::Type) {
+ Info.Param = TTP;
+ Info.FirstArg = PartialTemplateArgs[I];
+ return TDK_SubstitutionFailure;
+ }
+
+ if (Context.getCanonicalType(InstArg.getAsType())
+ != Context.getCanonicalType(TemplateArgs[I].getAsType())) {
+ Info.Param = TTP;
+ Info.FirstArg = TemplateArgs[I];
+ Info.SecondArg = InstArg;
+ return TDK_NonDeducedMismatch;
+ }
+
+ continue;
+ }
+
+ // FIXME: Check template template arguments?
+ }
+
+ if (Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+
+ return TDK_Success;
+}
+
+static void
+MarkDeducedTemplateParameters(Sema &SemaRef,
+ const TemplateArgument &TemplateArg,
+ llvm::SmallVectorImpl<bool> &Deduced);
+
+/// \brief Mark the template arguments that are deduced by the given
+/// expression.
+static void
+MarkDeducedTemplateParameters(Expr *E, llvm::SmallVectorImpl<bool> &Deduced) {
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+ if (!E)
+ return;
+
+ NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+ if (!NTTP)
+ return;
+
+ Deduced[NTTP->getIndex()] = true;
+}
+
+/// \brief Mark the template parameters that are deduced by the given
+/// type.
+static void
+MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ // Non-dependent types have nothing deducible
+ if (!T->isDependentType())
+ return;
+
+ T = SemaRef.Context.getCanonicalType(T);
+ switch (T->getTypeClass()) {
+ case Type::ExtQual:
+ MarkDeducedTemplateParameters(SemaRef,
+ QualType(cast<ExtQualType>(T.getTypePtr())->getBaseType(), 0),
+ Deduced);
+ break;
+
+ case Type::Pointer:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<PointerType>(T.getTypePtr())->getPointeeType(),
+ Deduced);
+ break;
+
+ case Type::BlockPointer:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<BlockPointerType>(T.getTypePtr())->getPointeeType(),
+ Deduced);
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<ReferenceType>(T.getTypePtr())->getPointeeType(),
+ Deduced);
+ break;
+
+ case Type::MemberPointer: {
+ const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
+ MarkDeducedTemplateParameters(SemaRef, MemPtr->getPointeeType(), Deduced);
+ MarkDeducedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0),
+ Deduced);
+ break;
+ }
+
+ case Type::DependentSizedArray:
+ MarkDeducedTemplateParameters(
+ cast<DependentSizedArrayType>(T.getTypePtr())->getSizeExpr(),
+ Deduced);
+ // Fall through to check the element type
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<ArrayType>(T.getTypePtr())->getElementType(),
+ Deduced);
+ break;
+
+ case Type::Vector:
+ case Type::ExtVector:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<VectorType>(T.getTypePtr())->getElementType(),
+ Deduced);
+ break;
+
+ case Type::FunctionProto: {
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T.getTypePtr());
+ MarkDeducedTemplateParameters(SemaRef, Proto->getResultType(), Deduced);
+ for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
+ MarkDeducedTemplateParameters(SemaRef, Proto->getArgType(I), Deduced);
+ break;
+ }
+
+ case Type::TemplateTypeParm:
+ Deduced[cast<TemplateTypeParmType>(T.getTypePtr())->getIndex()] = true;
+ break;
+
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *Spec
+ = cast<TemplateSpecializationType>(T.getTypePtr());
+ if (TemplateDecl *Template = Spec->getTemplateName().getAsTemplateDecl())
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template))
+ Deduced[TTP->getIndex()] = true;
+
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ MarkDeducedTemplateParameters(SemaRef, Spec->getArg(I), Deduced);
+
+ break;
+ }
+
+ // None of these types have any deducible parts.
+ case Type::Builtin:
+ case Type::FixedWidthInt:
+ case Type::Complex:
+ case Type::VariableArray:
+ case Type::FunctionNoProto:
+ case Type::Record:
+ case Type::Enum:
+ case Type::Typename:
+ case Type::ObjCInterface:
+ case Type::ObjCQualifiedInterface:
+ case Type::ObjCQualifiedId:
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ break;
+ }
+}
+
+/// \brief Mark the template parameters that are deduced by this
+/// template argument.
+static void
+MarkDeducedTemplateParameters(Sema &SemaRef,
+ const TemplateArgument &TemplateArg,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ switch (TemplateArg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ break;
+
+ case TemplateArgument::Type:
+ MarkDeducedTemplateParameters(SemaRef, TemplateArg.getAsType(), Deduced);
+ break;
+
+ case TemplateArgument::Declaration:
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl()))
+ Deduced[TTP->getIndex()] = true;
+ break;
+
+ case TemplateArgument::Expression:
+ MarkDeducedTemplateParameters(TemplateArg.getAsExpr(), Deduced);
+ break;
+ }
+}
+
+/// \brief Mark the template parameters can be deduced by the given
+/// template argument list.
+///
+/// \param TemplateArgs the template argument list from which template
+/// parameters will be deduced.
+///
+/// \param Deduced a bit vector whose elements will be set to \c true
+/// to indicate when the corresponding template parameter will be
+/// deduced.
+void
+Sema::MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ ::MarkDeducedTemplateParameters(*this, TemplateArgs[I], Deduced);
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 562749e18fef..18b2d75accbc 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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,8 +181,50 @@ 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;
}
//===----------------------------------------------------------------------===/
@@ -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();
-
- InstantiatedTemplateArgs.push_back(
- TemplateArgument(Arg->getLocation(), T));
- break;
- }
-
- case TemplateArgument::Declaration:
- case TemplateArgument::Integral:
- InstantiatedTemplateArgs.push_back(*Arg);
- break;
+ TemplateArgument InstArg = SemaRef.Instantiate(*Arg, TemplateArgs);
+ if (InstArg.isNull())
+ return QualType();
- 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();
+}
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index fa5fdee2c13c..3c67f2ad0d30 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -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(
diff --git a/lib/Sema/SemaTemplateInstantiateStmt.cpp b/lib/Sema/SemaTemplateInstantiateStmt.cpp
index fd349df27edd..efdcec81afff 100644
--- a/lib/Sema/SemaTemplateInstantiateStmt.cpp
+++ b/lib/Sema/SemaTemplateInstantiateStmt.cpp
@@ -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) {
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index cd19d97c5be9..70a92706071d 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -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");
- D.setInvalidType(true);
+ if (!ClsType.isNull())
+ T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,
+ DeclType.Loc, D.getIdentifier());
+ if (T.isNull()) {
T = Context.IntTy;
+ D.setInvalidType(true);
}
- 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;
}
diff --git a/test/Analysis/array-struct.c b/test/Analysis/array-struct.c
index c0e1d8b7e39f..0ad7ae7e8283 100644
--- a/test/Analysis/array-struct.c
+++ b/test/Analysis/array-struct.c
@@ -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]));
+}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp
new file mode 100644
index 000000000000..3b0e345f0172
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp
@@ -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.
+
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
new file mode 100644
index 000000000000..0142dcbb055c
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -verify %s
+// XFAIL
+
+void f0() {
+}
+
+inline void f0(); // expected-error {{function definition cannot preceed inline declaration}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
new file mode 100644
index 000000000000..c5f0a51b22e5
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
@@ -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}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp
new file mode 100644
index 000000000000..62ae7bfded14
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp
@@ -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}}
+};
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp
new file mode 100644
index 000000000000..5d9f9e7a51c5
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp
@@ -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}}
+}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p3.cpp
new file mode 100644
index 000000000000..867b4f03d41f
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p3.cpp
@@ -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}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp
new file mode 100644
index 000000000000..f1413f9b41b8
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp
@@ -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'}}
+};
+
diff --git a/test/CXX/temp/temp.param/p1.cpp b/test/CXX/temp/temp.param/p1.cpp
new file mode 100644
index 000000000000..488c3a07429a
--- /dev/null
+++ b/test/CXX/temp/temp.param/p1.cpp
@@ -0,0 +1 @@
+// Paragraph 1 is descriptive, and therefore requires no tests.
diff --git a/test/CXX/temp/temp.param/p10.cpp b/test/CXX/temp/temp.param/p10.cpp
new file mode 100644
index 000000000000..56e7f3281eb6
--- /dev/null
+++ b/test/CXX/temp/temp.param/p10.cpp
@@ -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;
diff --git a/test/CXX/temp/temp.param/p11.cpp b/test/CXX/temp/temp.param/p11.cpp
new file mode 100644
index 000000000000..9e7fd39c0a46
--- /dev/null
+++ b/test/CXX/temp/temp.param/p11.cpp
@@ -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;
diff --git a/test/CXX/temp/temp.param/p12.cpp b/test/CXX/temp/temp.param/p12.cpp
new file mode 100644
index 000000000000..5511224ebe94
--- /dev/null
+++ b/test/CXX/temp/temp.param/p12.cpp
@@ -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;
diff --git a/test/CXX/temp/temp.param/p13.cpp b/test/CXX/temp/temp.param/p13.cpp
new file mode 100644
index 000000000000..559b892d0fd2
--- /dev/null
+++ b/test/CXX/temp/temp.param/p13.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// The scope of atemplate-parameterextends from its point of
+// declaration until the end of its template. In particular, a
+// template-parameter can be used in the declaration of subsequent
+// template-parameters and their default arguments.
+
+template<class T, T* p, class U = T> class X { /* ... */ };
+// FIXME: template<class T> void f(T* p = new T);
+
+// Check for bogus template parameter shadow warning.
+template<template<class T> class,
+ template<class T> class>
+ class B1noshadow;
diff --git a/test/CXX/temp/temp.param/p14.cpp b/test/CXX/temp/temp.param/p14.cpp
new file mode 100644
index 000000000000..07e6bfe40983
--- /dev/null
+++ b/test/CXX/temp/temp.param/p14.cpp
@@ -0,0 +1,5 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// XFAIL
+
+// A template-parameter shall not be used in its own default argument.
+template<typename T = typename T::type> struct X; // expected-error{{default}}
diff --git a/test/SemaTemplate/right-angle-brackets-0x.cpp b/test/CXX/temp/temp.param/p15-cxx0x.cpp
index 57b6ee22410c..57b6ee22410c 100644
--- a/test/SemaTemplate/right-angle-brackets-0x.cpp
+++ b/test/CXX/temp/temp.param/p15-cxx0x.cpp
diff --git a/test/SemaTemplate/right-angle-brackets-98.cpp b/test/CXX/temp/temp.param/p15.cpp
index 764bb7bae073..764bb7bae073 100644
--- a/test/SemaTemplate/right-angle-brackets-98.cpp
+++ b/test/CXX/temp/temp.param/p15.cpp
diff --git a/test/CXX/temp/temp.param/p2.cpp b/test/CXX/temp/temp.param/p2.cpp
new file mode 100644
index 000000000000..a402cf6f888d
--- /dev/null
+++ b/test/CXX/temp/temp.param/p2.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// There is no semantic difference between class and typename in a
+// template-parameter. typename followed by an unqualified-id names a
+// template type parameter.
+template<class T> struct X;
+template<typename T> struct X;
+
+// typename followed by aqualified-id denotes the type in a non-type
+// parameter-declaration.
+// FIXME: template<typename T, typename T::type Value> struct Y;
+
+// A storage class shall not be specified in a template-parameter declaration.
+template<static int Value> struct Z; // FIXME: expect an error
+
+// FIXME: add the example from p2
diff --git a/test/CXX/temp/temp.param/p3.cpp b/test/CXX/temp/temp.param/p3.cpp
new file mode 100644
index 000000000000..6a76fe20b81a
--- /dev/null
+++ b/test/CXX/temp/temp.param/p3.cpp
@@ -0,0 +1,28 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// A type-parameter defines its identifier to be a type-name (if
+// declared with class or typename) or template-name (if declared with
+// template) in the scope of the template declaration.
+template<typename T> struct X0 {
+ T* value;
+};
+
+template<template<class T> class Y> struct X1 {
+ Y<int> value;
+};
+
+// [Note: because of the name lookup rules, a template-parameter that
+// could be interpreted as either a non-type template-parameter or a
+// type-parameter (because its identifier is the name of an already
+// existing class) is taken as a type-parameter. For example,
+class T { /* ... */ };
+int i;
+
+template<class T, T i> struct X2 {
+ void f(T t)
+ {
+ T t1 = i; //template-parameters T and i
+ ::T t2 = ::i; // global namespace members T and i \
+ // expected-error{{cannot initialize}}
+ }
+};
diff --git a/test/CXX/temp/temp.param/p4.cpp b/test/CXX/temp/temp.param/p4.cpp
new file mode 100644
index 000000000000..3efff1243600
--- /dev/null
+++ b/test/CXX/temp/temp.param/p4.cpp
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+class X;
+
+// C++ [temp.param]p4
+typedef int INT;
+enum E { enum1, enum2 };
+template<int N> struct A1;
+template<INT N, INT M> struct A2;
+template<enum E x, E y> struct A3;
+template<int &X> struct A4;
+template<int *Ptr> struct A5;
+template<int (&f)(int, int)> struct A6;
+template<int (*fp)(float, double)> struct A7;
+template<int X::*pm> struct A8;
+template<float (X::*pmf)(float, int)> struct A9;
+template<typename T, T x> struct A10;
+
+template<float f> struct A11; // expected-error{{a non-type template parameter cannot have type 'float'}}
+
+template<void *Ptr> struct A12; // expected-error{{a non-type template parameter cannot have type 'void *'}}
diff --git a/test/CXX/temp/temp.param/p7.cpp b/test/CXX/temp/temp.param/p7.cpp
new file mode 100644
index 000000000000..ccc869ae0fbe
--- /dev/null
+++ b/test/CXX/temp/temp.param/p7.cpp
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// A non-type template-parameter shall not be declared to have
+// floating point, class, or void type.
+struct A;
+
+template<double d> class X; // expected-error{{cannot have type}}
+template<double* pd> class Y; //OK
+template<double& rd> class Z; //OK
+
+template<A a> class X0; // expected-error{{cannot have type}}
+
+typedef void VOID;
+template<VOID a> class X01; // expected-error{{cannot have type}}
+
diff --git a/test/CXX/temp/temp.param/p8.cpp b/test/CXX/temp/temp.param/p8.cpp
new file mode 100644
index 000000000000..dd4af17d79fa
--- /dev/null
+++ b/test/CXX/temp/temp.param/p8.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<int X[10]> struct A;
+template<int *X> struct A;
+template<int f(float, double)> struct B;
+typedef float FLOAT;
+template<int (*f)(FLOAT, double)> struct B;
diff --git a/test/CodeGen/always_inline.c b/test/CodeGen/always_inline.c
index cb32e3b62181..c12b45404d2d 100644
--- a/test/CodeGen/always_inline.c
+++ b/test/CodeGen/always_inline.c
@@ -1,5 +1,6 @@
// RUN: clang -emit-llvm -S -o %t %s &&
-// RUN: grep '@f0' %t | count 0 &&
+// RUN: not grep '@f0' %t &&
+// RUN: not grep 'call ' %t &&
// RUN: clang -mllvm -disable-llvm-optzns -emit-llvm -S -o %t %s &&
// RUN: grep '@f0' %t | count 2
@@ -11,3 +12,9 @@ static int __attribute__((always_inline)) f0() {
int f1() {
return f0();
}
+
+// PR4372
+inline int f2() __attribute__((always_inline));
+int f2() { return 7; }
+int f3(void) { return f2(); }
+
diff --git a/test/CodeGen/lineno-dbginfo.c b/test/CodeGen/lineno-dbginfo.c
index fe9e59ac2d70..12c32ce9dd4b 100644
--- a/test/CodeGen/lineno-dbginfo.c
+++ b/test/CodeGen/lineno-dbginfo.c
@@ -1,5 +1,6 @@
-// RUN: echo "#include <stdio.h>" > %t.h
-// RUN: clang -S -save-temps -g -include %t.h %s -emit-llvm -o %t.ll
-// RUN: grep "i32 5" %t.ll
+// RUN: echo "#include <stdio.h>" > %t.h &&
+// RUN: clang -S -save-temps -g -include %t.h %s -emit-llvm -o %t.ll &&
+// RUN: grep "i32 5" %t.ll &&
+// RUN: rm -f lineno-dbginfo.i
// outer is at line number 5.
int outer = 42;
diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c
new file mode 100644
index 000000000000..9d73d5c6300d
--- /dev/null
+++ b/test/CodeGen/target-data.c
@@ -0,0 +1,7 @@
+// RUN: clang-cc -triple i686-unknown-unknown -emit-llvm -o %t %s &&
+// RUN: grep 'target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"' %t &&
+// RUN: clang-cc -triple i686-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: grep 'target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"' %t &&
+// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s &&
+// RUN: grep 'target datalayout = "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-s0:64:64-f80:128:128"' %t &&
+// RUN: true
diff --git a/test/CodeGen/x86_32-arguments.c b/test/CodeGen/x86_32-arguments.c
index 8980c66b2072..43a3ab246c71 100644
--- a/test/CodeGen/x86_32-arguments.c
+++ b/test/CodeGen/x86_32-arguments.c
@@ -154,4 +154,9 @@ struct s37 { float c[1][1]; } f37(void) {}
// RUN: grep 'define void @f38(.struct.s38. noalias sret .agg.result)' %t &&
struct s38 { char a[3]; short b; } f38(void) {}
+// RUN: grep 'define void @f39(.struct.s39. byval align 16 .x)' %t &&
+typedef int v39 __attribute((vector_size(16)));
+struct s39 { v39 x; };
+void f39(struct s39 x) {}
+
// RUN: true
diff --git a/test/CodeGenCXX/static-assert.cpp b/test/CodeGenCXX/static-assert.cpp
new file mode 100644
index 000000000000..7757acd83887
--- /dev/null
+++ b/test/CodeGenCXX/static-assert.cpp
@@ -0,0 +1,3 @@
+// RUN: clang-cc %s -emit-llvm -o - -std=c++0x
+
+static_assert(true, "");
diff --git a/test/CodeGenObjC/property-complex.m b/test/CodeGenObjC/property-complex.m
new file mode 100644
index 000000000000..2e23ca410559
--- /dev/null
+++ b/test/CodeGenObjC/property-complex.m
@@ -0,0 +1,61 @@
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -S -o - %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -S -o - %s
+
+@interface I0 {
+@public
+ _Complex float iv0;
+}
+
+@property(assign) _Complex float p0;
+
+-(_Complex float) im0;
+-(void) setIm0: (_Complex float) a0;
+@end
+
+@implementation I0
+@dynamic p0;
+
+-(id) init {
+ self->iv0 = 5.0 + 2.0i;
+ return self;
+}
+
+-(_Complex float) im0 {
+ printf("im0: %.2f + %.2fi\n", __real iv0, __imag iv0);
+ return iv0 + (.1 + .2i);
+}
+-(void) setIm0: (_Complex float) a0 {
+ printf("setIm0: %.2f + %.2fi\n", __real a0, __imag a0);
+ iv0 = a0 + (.3 + .4i);
+}
+
+-(_Complex float) p0 {
+ printf("p0: %.2f + %.2fi\n", __real iv0, __imag iv0);
+ return iv0 + (.5 + .6i);
+}
+-(void) setP0: (_Complex float) a0 {
+ printf("setP0: %.2f + %.2fi\n", __real a0, __imag a0);
+ iv0 = a0 + (.7 + .8i);
+}
+@end
+
+void f0(I0 *a0) {
+ float l0 = __real a0.im0;
+ float l1 = __imag a0->iv0;
+ _Complex float l2 = (a0.im0 = a0.im0);
+ _Complex float l3 = a0->iv0;
+ _Complex float l4 = (a0->iv0 = a0->iv0);
+ _Complex float l5 = a0->iv0;
+ _Complex float l6 = (a0.p0 = a0.p0);
+ _Complex float l7 = a0->iv0;
+ _Complex float l8 = [a0 im0];
+ printf("l0: %.2f + %.2fi\n", __real l0, __imag l0);
+ printf("l1: %.2f + %.2fi\n", __real l1, __imag l1);
+ printf("l2: %.2f + %.2fi\n", __real l2, __imag l2);
+ printf("l3: %.2f + %.2fi\n", __real l3, __imag l3);
+ printf("l4: %.2f + %.2fi\n", __real l4, __imag l4);
+ printf("l5: %.2f + %.2fi\n", __real l5, __imag l5);
+ printf("l6: %.2f + %.2fi\n", __real l6, __imag l6);
+ printf("l7: %.2f + %.2fi\n", __real l7, __imag l7);
+ printf("l8: %.2f + %.2fi\n", __real l8, __imag l8);
+}
diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c
index 9dc8f63db8de..8266f7762398 100644
--- a/test/Driver/clang_f_opts.c
+++ b/test/Driver/clang_f_opts.c
@@ -2,9 +2,10 @@
// RUN: grep -F '"-fblocks"' %t &&
// RUN: grep -F '"--fmath-errno=1"' %t &&
// RUN: grep -F '"-fpascal-strings"' %t &&
-// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings %s 2> %t &&
+// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fno-show-source-location %s 2> %t &&
// RUN: grep -F '"-fblocks=0"' %t &&
// RUN: grep -F '"-fbuiltin=0"' %t &&
// RUN: grep -F '"-fno-common"' %t &&
// RUN: grep -F '"--fmath-errno=0"' %t &&
+// RUN: grep -F '"-fno-show-source-location"' %t &&
// RUN: true
diff --git a/test/Frontend/cpp-output.c b/test/Frontend/cpp-output.c
new file mode 100644
index 000000000000..ee37f4cd6853
--- /dev/null
+++ b/test/Frontend/cpp-output.c
@@ -0,0 +1,15 @@
+// RUN: clang -E -o %t -C %s &&
+// RUN: grep '^int x; // comment' %t &&
+// RUN: grep '^x x' %t &&
+// RUN: clang -E -o %t -CC %s &&
+// RUN: grep '^int x; // comment' %t &&
+// RUN: grep '^x /\* comment \*/ x /\* comment \*/' %t &&
+// RUN: true
+
+int x; // comment
+
+#define A(foo, bar) foo bar
+#define B x // comment
+
+A(B, B)
+
diff --git a/test/Lexer/char-escapes.c b/test/Lexer/char-escapes.c
new file mode 100644
index 000000000000..ef665fe84a5b
--- /dev/null
+++ b/test/Lexer/char-escapes.c
@@ -0,0 +1,21 @@
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+
+int test['\\' == 92 ? 1 : -1];
+int test['\"' == 34 ? 1 : -1];
+int test['\'' == 39 ? 1 : -1];
+int test['\?' == 63 ? 1 : -1];
+int test['\a' == 7 ? 1 : -1];
+int test['\b' == 8 ? 1 : -1];
+int test['\e' == 27 ? 1 : -1]; // expected-warning {{non-standard escape}}
+int test['\E' == 27 ? 1 : -1]; // expected-warning {{non-standard escape}}
+int test['\f' == 12 ? 1 : -1];
+int test['\n' == 10 ? 1 : -1];
+int test['\r' == 13 ? 1 : -1];
+int test['\t' == 9 ? 1 : -1];
+int test['\v' == 11 ? 1 : -1];
+int test['\xa' == 10 ? 1 : -1];
+int test['\1' == 1 ? 1 : -1];
+int test['\(' == 40 ? 1 : -1]; // expected-warning {{non-standard escape}}
+int test['\{' == 123 ? 1 : -1]; // expected-warning {{non-standard escape}}
+int test['\[' == 91 ? 1 : -1]; // expected-warning {{non-standard escape}}
+int test['\%' == 37 ? 1 : -1]; // expected-warning {{non-standard escape}}
diff --git a/test/Makefile b/test/Makefile
index 1ebaedd6b7da..271f46fdd6dc 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -4,42 +4,17 @@ include $(LEVEL)/Makefile.common
# Test in all immediate subdirectories if unset.
TESTDIRS ?= $(shell echo $(PROJ_SRC_DIR)/*/)
-# Only run rewriter tests on darwin.
-ifeq ($(OS),Darwin)
-TESTDIRS +=
-endif
-
+ifndef TESTARGS
ifdef VERBOSE
-ifeq ($(VERBOSE),0)
-PROGRESS = :
-REPORTFAIL = echo 'FAIL: clang' $(TARGET_TRIPLE) $(subst $(LLVM_SRC_ROOT)/tools/clang/,,$<)
-DONE = $(LLVMToolDir)/clang -v
+TESTARGS = -v
else
-PROGRESS = echo $<
-REPORTFAIL = cat $@
-DONE = true
+TESTARGS = -s
endif
-else
-PROGRESS = printf '.'
-REPORTFAIL = (echo; echo '----' $< 'failed ----')
-DONE = echo
endif
-TESTS := $(addprefix Output/, $(addsuffix .testresults, $(shell find $(TESTDIRS) \( -name '*.c' -or -name '*.cpp' -or -name '*.m' -or -name '*.mm' -or -name '*.S' \) | grep -v "Output/")))
-Output/%.testresults: %
- @ $(PROGRESS)
- @ PATH=$(ToolDir):$(LLVM_SRC_ROOT)/test/Scripts:$$PATH VG=$(VG) $(PROJ_SRC_DIR)/TestRunner.sh $< > $@ || $(REPORTFAIL)
-
all::
- @ mkdir -p $(addprefix Output/, $(TESTDIRS))
- @ rm -f $(TESTS)
@ echo '--- Running clang tests for $(TARGET_TRIPLE) ---'
- @ $(MAKE) $(TESTS)
- @ $(DONE)
- @ !(cat $(TESTS) | grep -q " FAILED! ")
-
-report: $(TESTS)
- @ cat $^
+ @ PATH=$(ToolDir):$(LLVM_SRC_ROOT)/test/Scripts:$$PATH VG=$(VG) ../utils/test/MultiTestRunner.py $(TESTARGS) $(TESTDIRS)
clean::
@ rm -rf Output/
diff --git a/test/Parser/statements.c b/test/Parser/statements.c
index c5923bc0641b..b95c23fb28b0 100644
--- a/test/Parser/statements.c
+++ b/test/Parser/statements.c
@@ -54,3 +54,6 @@ void test6(void) {
while (0);
}
+int test7() {
+ return 4 // expected-error {{expected ';' after return statement}}
+}
diff --git a/test/Preprocessor/feature_tests.c b/test/Preprocessor/feature_tests.c
new file mode 100644
index 000000000000..9a29ab96c93e
--- /dev/null
+++ b/test/Preprocessor/feature_tests.c
@@ -0,0 +1,31 @@
+// RUN: clang-cc %s --triple=i686-apple-darwin9 &&
+// RUN: clang-cc %s -E --triple=i686-apple-darwin9
+#ifndef __has_feature
+#error Should have __has_feature
+#endif
+
+
+#if __has_feature(something_we_dont_have)
+#error Bad
+#endif
+
+#if !__has_builtin(__builtin_huge_val) || \
+ !__has_builtin(__builtin_shufflevector) || \
+ !__has_builtin(__builtin_trap) || \
+ !__has_feature(attribute_analyzer_noreturn) || \
+ !__has_feature(attribute_overloadable)
+#error Clang should have these
+#endif
+
+#if __has_builtin(__builtin_insanity)
+#error Clang should not have this
+#endif
+
+
+
+// Make sure we have x86 builtins only (forced with target triple).
+
+#if !__has_builtin(__builtin_ia32_emms) || \
+ __has_builtin(__builtin_altivec_abs_v4sf)
+#error Broken handling of target-specific builtins
+#endif
diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c
index 971986b2d3af..72db14c82053 100644
--- a/test/Sema/const-eval.c
+++ b/test/Sema/const-eval.c
@@ -66,3 +66,5 @@ EVAL_EXPR(30, (int)(_Complex float)((1<<30)-1) == (1<<30) ? 1 : -1)
EVAL_EXPR(31, (int*)0 == (int*)0 ? 1 : -1)
EVAL_EXPR(32, (int*)0 != (int*)0 ? -1 : 1)
EVAL_EXPR(33, (void*)0 - (void*)0 == 0 ? 1 : -1)
+void foo(void) {}
+EVAL_EXPR(34, (foo == (void *)0) ? -1 : 1)
diff --git a/test/Sema/init-vector.c b/test/Sema/init-vector.c
new file mode 100644
index 000000000000..691ea97268fd
--- /dev/null
+++ b/test/Sema/init-vector.c
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef float __attribute__((vector_size (16))) v4f_t;
+
+typedef union {
+ struct {
+ float x, y, z, w;
+ }s;
+ v4f_t v;
+} vector_t;
+
+
+vector_t foo(v4f_t p)
+{
+ vector_t v = {.v = p};
+ return v;
+}
diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp
index f99e45415dc4..edbd6b3e206a 100644
--- a/test/SemaCXX/default2.cpp
+++ b/test/SemaCXX/default2.cpp
@@ -115,9 +115,15 @@ void test_Z(const Z& z) {
}
struct ZZ {
- void f(ZZ z = g()); // expected-error{{no matching constructor for initialization}}
-
static ZZ g(int = 17);
+ void f(ZZ z = g()); // expected-error{{no matching constructor for initialization}}
+
ZZ(ZZ&, int = 17); // expected-note{{candidate function}}
};
+
+// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#325
+class C2 {
+ static void g(int = f()); // expected-error{{use of default argument to function 'f' that is declared later in class 'C2'}}
+ static int f(int = 10); // expected-note{{default argument declared here}}
+};
diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp
index cfe4f75dd17d..d2df5eb317a0 100644
--- a/test/SemaCXX/member-pointer.cpp
+++ b/test/SemaCXX/member-pointer.cpp
@@ -12,7 +12,8 @@ int A::*pdi1;
int (::A::*pdi2);
int (A::*pfi)(int);
-int B::*pbi; // expected-error {{expected a class or namespace}}
+int B::*pbi; // expected-error {{expected a class or namespace}} \
+ // expected-error{{does not point into a class}}
int C::*pci; // expected-error {{'pci' does not point into a class}}
void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}}
int& A::*pdr; // expected-error {{'pdr' declared as a pointer to a reference}}
diff --git a/test/SemaTemplate/default-arguments.cpp b/test/SemaTemplate/default-arguments.cpp
index 5b6ab7d1552c..f9bb44ecb9c0 100644
--- a/test/SemaTemplate/default-arguments.cpp
+++ b/test/SemaTemplate/default-arguments.cpp
@@ -13,3 +13,12 @@ X<> *x4;
template<typename T = int> struct Z { };
template struct Z<>;
+
+// PR4362
+template<class T> struct a { };
+template<> struct a<int> { static const bool v = true; };
+
+template<class T, bool = a<T>::v> struct p { }; // expected-error {{no member named 'v'}}
+
+template struct p<bool>; // expected-note {{in instantiation of default argument for 'p<bool>' required here}}
+template struct p<int>;
diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp
new file mode 100644
index 000000000000..95ee2d2b9d1f
--- /dev/null
+++ b/test/SemaTemplate/dependent-names.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef double A;
+template<typename T> class B {
+ typedef int A;
+};
+
+template<typename T> struct X : B<T> {
+ static A a;
+};
+
+int a0[sizeof(X<int>::a) == sizeof(double) ? 1 : -1];
+
+// PR4365.
+template<class T> class Q;
+template<class T> class R : Q<T> {T current;};
diff --git a/test/SemaTemplate/example-typelist.cpp b/test/SemaTemplate/example-typelist.cpp
new file mode 100644
index 000000000000..4a2aeb20e730
--- /dev/null
+++ b/test/SemaTemplate/example-typelist.cpp
@@ -0,0 +1,98 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// A simple cons-style typelist
+struct nil { };
+
+template<typename Head, typename Tail = nil>
+struct cons {
+ typedef Head head;
+ typedef Tail tail;
+};
+
+// is_same trait, for testing
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+// metaprogram that computes the length of a list
+template<typename T> struct length;
+
+template<typename Head, typename Tail>
+struct length<cons<Head, Tail> > {
+ static const unsigned value = length<Tail>::value + 1;
+};
+
+template<>
+struct length<nil> {
+ static const unsigned value = 0;
+};
+
+typedef cons<unsigned char,
+ cons<unsigned short,
+ cons<unsigned int,
+ cons<unsigned long> > > > unsigned_inttypes;
+int length0[length<unsigned_inttypes>::value == 4? 1 : -1];
+
+// metaprogram that reverses a list
+
+// FIXME: I would prefer that this be a partial specialization, but
+// that requires partial ordering of class template partial
+// specializations.
+template<typename T>
+class reverse {
+ typedef typename reverse<typename T::tail>::type reversed_tail;
+
+ typedef typename reverse<typename reversed_tail::tail>::type most_of_tail;
+
+public:
+ typedef cons<typename reversed_tail::head,
+ typename reverse<cons<typename T::head, most_of_tail> >::type> type;
+};
+
+template<typename Head>
+class reverse<cons<Head> > {
+public:
+ typedef cons<Head> type;
+};
+
+template<>
+class reverse<nil> {
+public:
+ typedef nil type;
+};
+
+int reverse0[is_same<reverse<unsigned_inttypes>::type,
+ cons<unsigned long,
+ cons<unsigned int,
+ cons<unsigned short,
+ cons<unsigned char> > > > >::value? 1 : -1];
+
+// metaprogram that finds a type within a list
+
+// FIXME: I would prefer that this be a partial specialization, but
+// that requires partial ordering of class template partial
+// specializations.
+template<typename List, typename T>
+struct find : find<typename List::tail, T> { };
+
+template<typename Tail, typename T>
+struct find<cons<T, Tail>, T> {
+ typedef cons<T, Tail> type;
+};
+
+template<typename T>
+struct find<nil, T> {
+ typedef nil type;
+};
+
+int find0[is_same<find<unsigned_inttypes, unsigned int>::type,
+ cons<unsigned int, cons<unsigned long> > >::value?
+ 1 : -1];
+int find1[is_same<find<unsigned_inttypes, int>::type, nil>::value? 1 : -1];
+
diff --git a/test/SemaTemplate/instantiate-declref-ice.cpp b/test/SemaTemplate/instantiate-declref-ice.cpp
new file mode 100644
index 000000000000..21ee87202797
--- /dev/null
+++ b/test/SemaTemplate/instantiate-declref-ice.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<int i> struct x {
+ static const int j = i;
+ x<j>* y;
+};
+
diff --git a/test/SemaTemplate/instantiate-dependent-nested-name.cpp b/test/SemaTemplate/instantiate-dependent-nested-name.cpp
new file mode 100644
index 000000000000..2b1d29878a54
--- /dev/null
+++ b/test/SemaTemplate/instantiate-dependent-nested-name.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// PR4382
+template<typename T> struct X { static const T A = 1; };
+template<typename T, bool = X<T>::A> struct Y { typedef T A; };
+template<typename T> struct Z { typedef typename Y<T>::A A; };
+extern int x;
+extern Z<int>::A x;
diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp
index 5b3a6d998404..023cc5437f69 100644
--- a/test/SemaTemplate/instantiate-function-1.cpp
+++ b/test/SemaTemplate/instantiate-function-1.cpp
@@ -140,7 +140,7 @@ template<typename T> struct Member0 {
tp->f;
this->f;
- this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}}
+ this.f; // expected-error{{member reference base type 'Member0<T> *const' is not a structure or union}}
}
};
@@ -209,3 +209,9 @@ struct Abstract {
template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}
+
+// PR4383
+template<typename T> struct X;
+template<typename T> struct Y : public X<T> {
+ Y& x() { return *this; }
+};
diff --git a/test/SemaTemplate/instantiate-member-pointers.cpp b/test/SemaTemplate/instantiate-member-pointers.cpp
new file mode 100644
index 000000000000..b3ddb3fafa31
--- /dev/null
+++ b/test/SemaTemplate/instantiate-member-pointers.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct Y {
+ int x;
+};
+
+template<typename T>
+struct X1 {
+ int f(T* ptr, int T::*pm) { // expected-error{{member pointer}}
+ return ptr->*pm;
+ }
+};
+
+template struct X1<Y>;
+template struct X1<int>; // expected-note{{instantiation}}
+
+template<typename T, typename Class>
+struct X2 {
+ T f(Class &obj, T Class::*pm) { // expected-error{{to a reference}} \
+ // expected-error{{member pointer to void}}
+ return obj.*pm;
+ }
+};
+
+template struct X2<int, Y>;
+template struct X2<int&, Y>; // expected-note{{instantiation}}
+template struct X2<const void, Y>; // expected-note{{instantiation}}
diff --git a/test/SemaTemplate/metafun-apply.cpp b/test/SemaTemplate/metafun-apply.cpp
index 7bc971f24b59..9261ed6a6c96 100644
--- a/test/SemaTemplate/metafun-apply.cpp
+++ b/test/SemaTemplate/metafun-apply.cpp
@@ -23,8 +23,7 @@ struct bogus {
template<typename MetaFun, typename T>
struct apply1 {
typedef typename MetaFun::template apply<T>::type type; // expected-note{{in instantiation of template class 'struct add_reference::apply<void>' requested here}} \
- // expected-error{{'apply' following the 'template' keyword does not refer to a template}} \
- // FIXME: expected-error{{type 'MetaFun::template apply<int>' cannot be used prior to '::' because it has no members}}
+ // expected-error{{'apply' following the 'template' keyword does not refer to a template}}
};
int i;
@@ -36,8 +35,7 @@ void test() {
apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} \
// FIXME: expected-error{{unexpected type name 'type': expected expression}}
- apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} \
- // FIXME: expected-error{{unexpected type name 'type': expected expression}}
+ apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}}
}
diff --git a/test/SemaTemplate/temp_class_spec.cpp b/test/SemaTemplate/temp_class_spec.cpp
index 4e4f5560aef3..1a534236c8eb 100644
--- a/test/SemaTemplate/temp_class_spec.cpp
+++ b/test/SemaTemplate/temp_class_spec.cpp
@@ -134,3 +134,130 @@ int is_unary_function6[is_unary_function_with_same_return_type_as_argument_type<
int is_unary_function7[is_unary_function_with_same_return_type_as_argument_type<int (*)(int, bool)>::value ? -1 : 1];
int is_unary_function8[is_unary_function_with_same_return_type_as_argument_type<int (*)(bool)>::value ? -1 : 1];
int is_unary_function9[is_unary_function_with_same_return_type_as_argument_type<int (*)(int)>::value ? 1 : -1];
+int is_unary_function10[is_unary_function_with_same_return_type_as_argument_type<int (*)(int, ...)>::value ? -1 : 1];
+int is_unary_function11[is_unary_function_with_same_return_type_as_argument_type<int (* const)(int)>::value ? -1 : 1];
+
+template<typename T>
+struct is_binary_function {
+ static const bool value = false;
+};
+
+template<typename R, typename T1, typename T2>
+struct is_binary_function<R(T1, T2)> {
+ static const bool value = true;
+};
+
+int is_binary_function0[is_binary_function<int(float, double)>::value? 1 : -1];
+
+template<typename T>
+struct is_member_pointer {
+ static const bool value = false;
+};
+
+template<typename T, typename Class>
+struct is_member_pointer<T Class::*> {
+ static const bool value = true;
+};
+
+struct X { };
+
+int is_member_pointer0[is_member_pointer<int X::*>::value? 1 : -1];
+int is_member_pointer1[is_member_pointer<const int X::*>::value? 1 : -1];
+int is_member_pointer2[is_member_pointer<int (X::*)()>::value? 1 : -1];
+int is_member_pointer3[is_member_pointer<int (X::*)(int) const>::value? 1 : -1];
+int is_member_pointer4[is_member_pointer<int (X::**)(int) const>::value? -1 : 1];
+int is_member_pointer5[is_member_pointer<int>::value? -1 : 1];
+
+template<typename T>
+struct is_member_function_pointer {
+ static const bool value = false;
+};
+
+template<typename T, typename Class>
+struct is_member_function_pointer<T (Class::*)()> {
+ static const bool value = true;
+};
+
+template<typename T, typename Class>
+struct is_member_function_pointer<T (Class::*)() const> {
+ static const bool value = true;
+};
+
+template<typename T, typename Class>
+struct is_member_function_pointer<T (Class::*)() volatile> {
+ static const bool value = true;
+};
+
+template<typename T, typename Class>
+struct is_member_function_pointer<T (Class::*)() const volatile> {
+ static const bool value = true;
+};
+
+template<typename T, typename Class, typename A1>
+struct is_member_function_pointer<T (Class::*)(A1)> {
+ static const bool value = true;
+};
+
+template<typename T, typename Class, typename A1>
+struct is_member_function_pointer<T (Class::*)(A1) const> {
+ static const bool value = true;
+};
+
+template<typename T, typename Class, typename A1>
+struct is_member_function_pointer<T (Class::*)(A1) volatile> {
+ static const bool value = true;
+};
+
+template<typename T, typename Class, typename A1>
+struct is_member_function_pointer<T (Class::*)(A1) const volatile> {
+ static const bool value = true;
+};
+
+int is_member_function_pointer0[
+ is_member_function_pointer<int X::*>::value? -1 : 1];
+int is_member_function_pointer1[
+ is_member_function_pointer<int (X::*)()>::value? 1 : -1];
+int is_member_function_pointer2[
+ is_member_function_pointer<X (X::*)(X&)>::value? 1 : -1];
+int is_member_function_pointer3[
+ is_member_function_pointer<int (X::*)() const>::value? 1 : -1];
+int is_member_function_pointer4[
+ is_member_function_pointer<int (X::*)(float) const>::value? 1 : -1];
+
+// Test substitution of non-dependent arguments back into the template
+// argument list of the class template partial specialization.
+template<typename T, typename ValueType = T>
+struct is_nested_value_type_identity {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_nested_value_type_identity<T, typename T::value_type> {
+ static const bool value = true;
+};
+
+template<typename T>
+struct HasValueType {
+ typedef T value_type;
+};
+
+struct HasIdentityValueType {
+ typedef HasIdentityValueType value_type;
+};
+
+struct NoValueType { };
+
+int is_nested_value_type_identity0[
+ is_nested_value_type_identity<HasValueType<int> >::value? -1 : 1];
+int is_nested_value_type_identity1[
+ is_nested_value_type_identity<HasIdentityValueType>::value? 1 : -1];
+int is_nested_value_type_identity2[
+ is_nested_value_type_identity<NoValueType>::value? -1 : 1];
+
+
+// C++ [temp.class.spec]p4:
+template<class T1, class T2, int I> class A { }; //#1
+template<class T, int I> class A<T, T*, I> { }; //#2
+template<class T1, class T2, int I> class A<T1*, T2, I> { }; //#3
+template<class T> class A<int, T*, 5> { }; //#4
+template<class T1, class T2, int I> class A<T1, T2*, I> { }; //#5
diff --git a/test/SemaTemplate/temp_class_spec_blocks.cpp b/test/SemaTemplate/temp_class_spec_blocks.cpp
new file mode 100644
index 000000000000..920d9c8b0cbd
--- /dev/null
+++ b/test/SemaTemplate/temp_class_spec_blocks.cpp
@@ -0,0 +1,34 @@
+// RUN: clang-cc -fsyntax-only -verify %s -fblocks
+template<typename T>
+struct is_unary_block {
+ static const bool value = false;
+};
+
+template<typename T, typename U>
+struct is_unary_block<T (^)(U)> {
+ static const bool value = true;
+};
+
+int is_unary_block0[is_unary_block<int>::value ? -1 : 1];
+int is_unary_block1[is_unary_block<int (^)()>::value ? -1 : 1];
+int is_unary_block2[is_unary_block<int (^)(int, bool)>::value ? -1 : 1];
+int is_unary_block3[is_unary_block<int (^)(bool)>::value ? 1 : -1];
+int is_unary_block4[is_unary_block<int (^)(int)>::value ? 1 : -1];
+
+template<typename T>
+struct is_unary_block_with_same_return_type_as_argument_type {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_unary_block_with_same_return_type_as_argument_type<T (^)(T)> {
+ static const bool value = true;
+};
+
+int is_unary_block5[is_unary_block_with_same_return_type_as_argument_type<int>::value ? -1 : 1];
+int is_unary_block6[is_unary_block_with_same_return_type_as_argument_type<int (^)()>::value ? -1 : 1];
+int is_unary_block7[is_unary_block_with_same_return_type_as_argument_type<int (^)(int, bool)>::value ? -1 : 1];
+int is_unary_block8[is_unary_block_with_same_return_type_as_argument_type<int (^)(bool)>::value ? -1 : 1];
+int is_unary_block9[is_unary_block_with_same_return_type_as_argument_type<int (^)(int)>::value ? 1 : -1];
+int is_unary_block10[is_unary_block_with_same_return_type_as_argument_type<int (^)(int, ...)>::value ? -1 : 1];
+int is_unary_block11[is_unary_block_with_same_return_type_as_argument_type<int (^ const)(int)>::value ? -1 : 1];
diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp
new file mode 100644
index 000000000000..b50bd8f634aa
--- /dev/null
+++ b/test/SemaTemplate/temp_class_spec_neg.cpp
@@ -0,0 +1,45 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T> struct vector;
+
+// C++ [temp.class.spec]p6:
+namespace N {
+ namespace M {
+ template<typename T> struct A; // expected-note{{here}}
+ }
+}
+
+template<typename T>
+struct N::M::A<T*> { }; // expected-error{{not in namespace}}
+
+// C++ [temp.class.spec]p9
+// bullet 1
+template <int I, int J> struct A {};
+template <int I> struct A<I+5, I*2> {}; // expected-error{{depends on}}
+template <int I, int J> struct B {};
+template <int I> struct B<I, I> {}; //OK
+
+// bullet 2
+template <class T, T t> struct C {}; // expected-note{{declared here}}
+template <class T> struct C<T, 1>; // expected-error{{specializes}}
+template <class T, T* t> struct C<T*, t>; // okay
+
+template< int X, int (*array_ptr)[X] > class A2 {}; // expected-note{{here}}
+int array[5];
+template< int X > class A2<X,&array> { }; // expected-error{{specializes}}
+
+template<typename T, int N, template<typename X> class TT>
+struct Test0;
+
+// bullet 3
+template<typename T, int N, template<typename X> class TT>
+struct Test0<T, N, TT>; // expected-error{{does not specialize}}
+
+// C++ [temp.class.spec]p10
+template<typename T = int, // expected-error{{default template argument}}
+ int N = 17, // expected-error{{default template argument}}
+ template<typename X> class TT = ::vector> // expected-error{{default template argument}}
+ struct Test0<T*, N, TT> { };
+
+template<typename T> struct Test1;
+template<typename T, typename U> // expected-note{{non-deducible}}
+ struct Test1<T*> { }; // expected-warning{{never be used}}
diff --git a/test/SemaTemplate/temp_param.cpp b/test/SemaTemplate/temp_param.cpp
deleted file mode 100644
index c042f0849a04..000000000000
--- a/test/SemaTemplate/temp_param.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// RUN: clang-cc -fsyntax-only -verify %s
-
-class X;
-
-// C++ [temp.param]p4
-typedef int INT;
-enum E { enum1, enum2 };
-template<int N> struct A1;
-template<INT N, INT M> struct A2;
-template<enum E x, E y> struct A3;
-template<int &X> struct A4;
-template<int *Ptr> struct A5;
-template<int (&f)(int, int)> struct A6;
-template<int (*fp)(float, double)> struct A7;
-template<int X::*pm> struct A8;
-template<float (X::*pmf)(float, int)> struct A9;
-template<typename T, T x> struct A10;
-
-template<float f> struct A11; // expected-error{{a non-type template parameter cannot have type 'float'}}
-
-template<void *Ptr> struct A12; // expected-error{{a non-type template parameter cannot have type 'void *'}}
-
-// C++ [temp.param]p8
-template<int X[10]> struct A5;
-template<int f(float, double)> struct A7;
-
-// C++ [temp.param]p11:
-template<typename> struct Y1; // expected-note{{too few template parameters in template template argument}}
-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;
-
-// Check for bogus template parameter shadow warning.
-template<template<class T> class,
- template<class T> class>
- class B1noshadow;
-
-// C++ [temp.param]p10:
-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;
-
-// 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;
diff --git a/test/SemaTemplate/typename-specifier-3.cpp b/test/SemaTemplate/typename-specifier-3.cpp
new file mode 100644
index 000000000000..8dde6095e533
--- /dev/null
+++ b/test/SemaTemplate/typename-specifier-3.cpp
@@ -0,0 +1,19 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// PR4364
+template<class T> struct a {
+ T b() {
+ return typename T::x();
+ }
+};
+struct B {
+ typedef B x;
+};
+B c() {
+ a<B> x;
+ return x.b();
+}
+
+// Some extra tests for invalid cases
+template<class T> struct test2 { T b() { return typename T::a; } }; // expected-error{{expected '(' for function-style cast or type construction}}
+template<class T> struct test3 { T b() { return typename a; } }; // expected-error{{expected a qualified name after 'typename'}}
diff --git a/test/SemaTemplate/variadic-class-template-1.cpp b/test/SemaTemplate/variadic-class-template-1.cpp
new file mode 100644
index 000000000000..6df905006692
--- /dev/null
+++ b/test/SemaTemplate/variadic-class-template-1.cpp
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+template<typename ... Args = int> struct S1 { }; // expected-error{{template parameter pack cannot have a default argument}}
+template<typename ... Args, typename T> struct S2 { }; // expected-error{{template parameter pack must be the last template parameter}}
diff --git a/test/SemaTemplate/variadic-class-template-2.cpp b/test/SemaTemplate/variadic-class-template-2.cpp
new file mode 100644
index 000000000000..eadea901c7fe
--- /dev/null
+++ b/test/SemaTemplate/variadic-class-template-2.cpp
@@ -0,0 +1,19 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+// Type parameters packs
+template <typename ...> struct TS1 {}; // expected-note{{template parameter is declared here}}
+template struct TS1<>;
+template struct TS1<int>;
+template struct TS1<int, int>;
+template struct TS1<int, 10>; // expected-error{{template argument for template type parameter must be a type}}
+
+template <typename, typename ...> struct TS2 {}; // expected-note{{template is declared here}}
+template struct TS2<>; // expected-error{{too few template arguments for class template 'TS2'}}
+template struct TS2<int>;
+template struct TS2<int, int>;
+
+template <typename = int, typename ...> struct TS3 {}; // expected-note{{template parameter is declared here}}
+template struct TS3<>; // expected-note{{previous explicit instantiation is here}}
+template struct TS3<int>; // expected-error{{duplicate explicit instantiation of 'TS3<>'}}
+template struct TS3<int, int>;
+template struct TS3<10>; // expected-error{{template argument for template type parameter must be a type}}
diff --git a/test/SemaTemplate/variadic-parse.cpp b/test/SemaTemplate/variadic-parse.cpp
new file mode 100644
index 000000000000..e1d1b1f98db2
--- /dev/null
+++ b/test/SemaTemplate/variadic-parse.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+// Parsing type parameter packs.
+template <typename ... Args> struct T1 {};
+template <typename ... > struct T2 {};
+
diff --git a/test/SemaTemplate/variadic-unsupported.cpp b/test/SemaTemplate/variadic-unsupported.cpp
new file mode 100644
index 000000000000..98f217c76891
--- /dev/null
+++ b/test/SemaTemplate/variadic-unsupported.cpp
@@ -0,0 +1,5 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Type parameter packs.
+template <typename ... > struct T1 {}; // expected-error{{variadic templates are only allowed in C++0x}}
+
diff --git a/test/cxx-sections.data b/test/cxx-sections.data
new file mode 100644
index 000000000000..b4501ea286ca
--- /dev/null
+++ b/test/cxx-sections.data
@@ -0,0 +1,1954 @@
+1 [intro]
+ 1.1 [intro.scope]
+ 1.2 [intro.refs]
+ 1.3 [intro.defs]
+ 1.3.1 [defns.argument]
+ 1.3.2 [defns.cond.supp]
+ 1.3.3 [defns.diagnostic]
+ 1.3.4 [defns.dynamic.type]
+ 1.3.5 [defns.ill.formed]
+ 1.3.6 [defns.impl.defined]
+ 1.3.7 [defns.impl.limits]
+ 1.3.8 [defns.locale.specific]
+ 1.3.9 [defns.multibyte]
+ 1.3.10 [defns.parameter]
+ 1.3.11 [defns.signature]
+ 1.3.12 [defns.static.type]
+ 1.3.13 [defns.undefined]
+ 1.3.14 [defns.unspecified]
+ 1.3.15 [defns.well.formed]
+ 1.4 [intro.compliance]
+ 1.5 [intro.structure]
+ 1.6 [syntax]
+ 1.7 [intro.memory]
+ 1.8 [intro.object]
+ 1.9 [intro.execution]
+ 1.10 [intro.multithread]
+ 1.11 [intro.ack]
+2 [lex]
+ 2.1 [lex.phases]
+ 2.2 [lex.charset]
+ 2.3 [lex.trigraph]
+ 2.4 [lex.pptoken]
+ 2.5 [lex.digraph]
+ 2.6 [lex.token]
+ 2.7 [lex.comment]
+ 2.8 [lex.header]
+ 2.9 [lex.ppnumber]
+ 2.10 [lex.name]
+ 2.11 [lex.key]
+ 2.12 [lex.operators]
+ 2.13 [lex.literal]
+ 2.13.1 [lex.icon]
+ 2.13.2 [lex.ccon]
+ 2.13.3 [lex.fcon]
+ 2.13.4 [lex.string]
+ 2.13.5 [lex.bool]
+ 2.13.6 [lex.nullptr]
+ 2.13.7 [lex.ext]
+3 [basic]
+ 3.1 [basic.def]
+ 3.2 [basic.def.odr]
+ 3.3 [basic.scope]
+ 3.3.1 [basic.scope.pdecl]
+ 3.3.2 [basic.scope.local]
+ 3.3.3 [basic.scope.proto]
+ 3.3.4 [basic.funscope]
+ 3.3.5 [basic.scope.namespace]
+ 3.3.6 [basic.scope.class]
+ 3.3.7 [basic.scope.concept]
+ 3.3.8 [basic.scope.req]
+ 3.3.9 [basic.scope.enum]
+ 3.3.10 [basic.scope.hiding]
+ 3.4 [basic.lookup]
+ 3.4.1 [basic.lookup.unqual]
+ 3.4.2 [basic.lookup.argdep]
+ 3.4.3 [basic.lookup.qual]
+ 3.4.3.1 [class.qual]
+ 3.4.3.2 [namespace.qual]
+ 3.4.3.3 [concept.qual]
+ 3.4.4 [basic.lookup.elab]
+ 3.4.5 [basic.lookup.classref]
+ 3.4.6 [basic.lookup.udir]
+ 3.5 [basic.link]
+ 3.6 [basic.start]
+ 3.6.1 [basic.start.main]
+ 3.6.2 [basic.start.init]
+ 3.6.3 [basic.start.term]
+ 3.7 [basic.stc]
+ 3.7.1 [basic.stc.static]
+ 3.7.2 [basic.stc.thread]
+ 3.7.3 [basic.stc.auto]
+ 3.7.4 [basic.stc.dynamic]
+ 3.7.4.1 [basic.stc.dynamic.allocation]
+ 3.7.4.2 [basic.stc.dynamic.deallocation]
+ 3.7.4.3 [basic.stc.dynamic.safety]
+ 3.7.5 [basic.stc.inherit]
+ 3.8 [basic.life]
+ 3.9 [basic.types]
+ 3.9.1 [basic.fundamental]
+ 3.9.2 [basic.compound]
+ 3.9.3 [basic.type.qualifier]
+ 3.10 [basic.lval]
+ 3.11 [basic.align]
+4 [conv]
+ 4.1 [conv.lval]
+ 4.2 [conv.array]
+ 4.3 [conv.func]
+ 4.4 [conv.qual]
+ 4.5 [conv.prom]
+ 4.6 [conv.fpprom]
+ 4.7 [conv.integral]
+ 4.8 [conv.double]
+ 4.9 [conv.fpint]
+ 4.10 [conv.ptr]
+ 4.11 [conv.mem]
+ 4.12 [conv.bool]
+ 4.13 [conv.rank]
+5 [expr]
+ 5.1 [expr.prim]
+ 5.1.1 [expr.prim.lambda]
+ 5.2 [expr.post]
+ 5.2.1 [expr.sub]
+ 5.2.2 [expr.call]
+ 5.2.3 [expr.type.conv]
+ 5.2.4 [expr.pseudo]
+ 5.2.5 [expr.ref]
+ 5.2.6 [expr.post.incr]
+ 5.2.7 [expr.dynamic.cast]
+ 5.2.8 [expr.typeid]
+ 5.2.9 [expr.static.cast]
+ 5.2.10 [expr.reinterpret.cast]
+ 5.2.11 [expr.const.cast]
+ 5.3 [expr.unary]
+ 5.3.1 [expr.unary.op]
+ 5.3.2 [expr.pre.incr]
+ 5.3.3 [expr.sizeof]
+ 5.3.4 [expr.new]
+ 5.3.5 [expr.delete]
+ 5.3.6 [expr.alignof]
+ 5.4 [expr.cast]
+ 5.5 [expr.mptr.oper]
+ 5.6 [expr.mul]
+ 5.7 [expr.add]
+ 5.8 [expr.shift]
+ 5.9 [expr.rel]
+ 5.10 [expr.eq]
+ 5.11 [expr.bit.and]
+ 5.12 [expr.xor]
+ 5.13 [expr.or]
+ 5.14 [expr.log.and]
+ 5.15 [expr.log.or]
+ 5.16 [expr.cond]
+ 5.17 [expr.ass]
+ 5.18 [expr.comma]
+ 5.19 [expr.const]
+6 [stmt.stmt]
+ 6.1 [stmt.label]
+ 6.2 [stmt.expr]
+ 6.3 [stmt.block]
+ 6.4 [stmt.select]
+ 6.4.1 [stmt.if]
+ 6.4.2 [stmt.switch]
+ 6.5 [stmt.iter]
+ 6.5.1 [stmt.while]
+ 6.5.2 [stmt.do]
+ 6.5.3 [stmt.for]
+ 6.5.4 [stmt.ranged]
+ 6.6 [stmt.jump]
+ 6.6.1 [stmt.break]
+ 6.6.2 [stmt.cont]
+ 6.6.3 [stmt.return]
+ 6.6.4 [stmt.goto]
+ 6.7 [stmt.dcl]
+ 6.8 [stmt.ambig]
+ 6.9 [stmt.late]
+7 [dcl.dcl]
+ 7.1 [dcl.spec]
+ 7.1.1 [dcl.stc]
+ 7.1.2 [dcl.fct.spec]
+ 7.1.3 [dcl.typedef]
+ 7.1.4 [dcl.friend]
+ 7.1.5 [dcl.constexpr]
+ 7.1.6 [dcl.type]
+ 7.1.6.1 [dcl.type.cv]
+ 7.1.6.2 [dcl.type.simple]
+ 7.1.6.3 [dcl.type.elab]
+ 7.1.6.4 [dcl.spec.auto]
+ 7.2 [dcl.enum]
+ 7.3 [basic.namespace]
+ 7.3.1 [namespace.def]
+ 7.3.1.1 [namespace.unnamed]
+ 7.3.1.2 [namespace.memdef]
+ 7.3.2 [namespace.alias]
+ 7.3.3 [namespace.udecl]
+ 7.3.4 [namespace.udir]
+ 7.4 [dcl.asm]
+ 7.5 [dcl.link]
+ 7.6 [dcl.attr]
+ 7.6.1 [dcl.attr.grammar]
+ 7.6.2 [dcl.align]
+ 7.6.3 [dcl.attr.noreturn]
+ 7.6.4 [dcl.attr.final]
+ 7.6.5 [dcl.attr.depend]
+8 [dcl.decl]
+ 8.1 [dcl.name]
+ 8.2 [dcl.ambig.res]
+ 8.3 [dcl.meaning]
+ 8.3.1 [dcl.ptr]
+ 8.3.2 [dcl.ref]
+ 8.3.3 [dcl.mptr]
+ 8.3.4 [dcl.array]
+ 8.3.5 [dcl.fct]
+ 8.3.6 [dcl.fct.default]
+ 8.4 [dcl.fct.def]
+ 8.5 [dcl.init]
+ 8.5.1 [dcl.init.aggr]
+ 8.5.2 [dcl.init.string]
+ 8.5.3 [dcl.init.ref]
+ 8.5.4 [dcl.init.list]
+9 [class]
+ 9.1 [class.name]
+ 9.2 [class.mem]
+ 9.3 [class.mfct]
+ 9.3.1 [class.mfct.non-static]
+ 9.3.2 [class.this]
+ 9.4 [class.static]
+ 9.4.1 [class.static.mfct]
+ 9.4.2 [class.static.data]
+ 9.5 [class.union]
+ 9.6 [class.bit]
+ 9.7 [class.nest]
+ 9.8 [class.local]
+ 9.9 [class.nested.type]
+10 [class.derived]
+ 10.1 [class.mi]
+ 10.2 [class.member.lookup]
+ 10.3 [class.virtual]
+ 10.4 [class.abstract]
+11 [class.access]
+ 11.1 [class.access.spec]
+ 11.2 [class.access.base]
+ 11.3 [class.access.dcl]
+ 11.4 [class.friend]
+ 11.5 [class.protected]
+ 11.6 [class.access.virt]
+ 11.7 [class.paths]
+ 11.8 [class.access.nest]
+12 [special]
+ 12.1 [class.ctor]
+ 12.2 [class.temporary]
+ 12.3 [class.conv]
+ 12.3.1 [class.conv.ctor]
+ 12.3.2 [class.conv.fct]
+ 12.4 [class.dtor]
+ 12.5 [class.free]
+ 12.6 [class.init]
+ 12.6.1 [class.expl.init]
+ 12.6.2 [class.base.init]
+ 12.7 [class.cdtor]
+ 12.8 [class.copy]
+ 12.9 [class.inhctor]
+13 [over]
+ 13.1 [over.load]
+ 13.2 [over.dcl]
+ 13.3 [over.match]
+ 13.3.1 [over.match.funcs]
+ 13.3.1.1 [over.match.call]
+ 13.3.1.1.1 [over.call.func]
+ 13.3.1.1.2 [over.call.object]
+ 13.3.1.2 [over.match.oper]
+ 13.3.1.3 [over.match.ctor]
+ 13.3.1.4 [over.match.copy]
+ 13.3.1.5 [over.match.conv]
+ 13.3.1.6 [over.match.ref]
+ 13.3.1.7 [over.match.list]
+ 13.3.2 [over.match.viable]
+ 13.3.3 [over.match.best]
+ 13.3.3.1 [over.best.ics]
+ 13.3.3.1.1 [over.ics.scs]
+ 13.3.3.1.2 [over.ics.user]
+ 13.3.3.1.3 [over.ics.ellipsis]
+ 13.3.3.1.4 [over.ics.ref]
+ 13.3.3.1.5 [over.ics.list]
+ 13.3.3.2 [over.ics.rank]
+ 13.4 [over.over]
+ 13.5 [over.oper]
+ 13.5.1 [over.unary]
+ 13.5.2 [over.binary]
+ 13.5.3 [over.ass]
+ 13.5.4 [over.call]
+ 13.5.5 [over.sub]
+ 13.5.6 [over.ref]
+ 13.5.7 [over.inc]
+ 13.5.8 [over.literal]
+ 13.6 [over.built]
+14 [temp]
+ 14.1 [temp.param]
+ 14.2 [temp.names]
+ 14.3 [temp.arg]
+ 14.3.1 [temp.arg.type]
+ 14.3.2 [temp.arg.nontype]
+ 14.3.3 [temp.arg.template]
+ 14.4 [temp.type]
+ 14.5 [temp.decls]
+ 14.5.1 [temp.class]
+ 14.5.1.1 [temp.mem.func]
+ 14.5.1.2 [temp.mem.class]
+ 14.5.1.3 [temp.static]
+ 14.5.2 [temp.mem]
+ 14.5.3 [temp.variadic]
+ 14.5.4 [temp.friend]
+ 14.5.5 [temp.class.spec]
+ 14.5.5.1 [temp.class.spec.match]
+ 14.5.5.2 [temp.class.order]
+ 14.5.5.3 [temp.class.spec.mfunc]
+ 14.5.6 [temp.fct]
+ 14.5.6.1 [temp.over.link]
+ 14.5.6.2 [temp.func.order]
+ 14.5.7 [temp.alias]
+ 14.5.8 [temp.concept.map]
+ 14.6 [temp.res]
+ 14.6.1 [temp.local]
+ 14.6.2 [temp.dep]
+ 14.6.2.1 [temp.dep.type]
+ 14.6.2.2 [temp.dep.expr]
+ 14.6.2.3 [temp.dep.constexpr]
+ 14.6.2.4 [temp.dep.temp]
+ 14.6.3 [temp.nondep]
+ 14.6.4 [temp.dep.res]
+ 14.6.4.1 [temp.point]
+ 14.6.4.2 [temp.dep.candidate]
+ 14.6.5 [temp.inject]
+ 14.7 [temp.spec]
+ 14.7.1 [temp.inst]
+ 14.7.2 [temp.explicit]
+ 14.7.3 [temp.expl.spec]
+ 14.8 [temp.fct.spec]
+ 14.8.1 [temp.arg.explicit]
+ 14.8.2 [temp.deduct]
+ 14.8.2.1 [temp.deduct.call]
+ 14.8.2.2 [temp.deduct.funcaddr]
+ 14.8.2.3 [temp.deduct.conv]
+ 14.8.2.4 [temp.deduct.partial]
+ 14.8.2.5 [temp.deduct.type]
+ 14.8.3 [temp.over]
+ 14.9 [concept]
+ 14.9.1 [concept.def]
+ 14.9.1.1 [concept.fct]
+ 14.9.1.2 [concept.assoc]
+ 14.9.1.3 [concept.req]
+ 14.9.1.4 [concept.axiom]
+ 14.9.2 [concept.map]
+ 14.9.2.1 [concept.map.fct]
+ 14.9.2.2 [concept.map.assoc]
+ 14.9.3 [concept.refine]
+ 14.9.3.1 [concept.member.lookup]
+ 14.9.3.2 [concept.refine.maps]
+ 14.9.4 [concept.support]
+ 14.10 [temp.constrained]
+ 14.10.1 [temp.req]
+ 14.10.1.1 [temp.req.sat]
+ 14.10.1.2 [temp.req.impl]
+ 14.10.2 [temp.archetype]
+ 14.10.2.1 [temp.archetype.assemble]
+ 14.10.3 [temp.constrained.set]
+ 14.10.4 [temp.constrained.inst]
+15 [except]
+ 15.1 [except.throw]
+ 15.2 [except.ctor]
+ 15.3 [except.handle]
+ 15.4 [except.spec]
+ 15.5 [except.special]
+ 15.5.1 [except.terminate]
+ 15.5.2 [except.unexpected]
+ 15.5.3 [except.uncaught]
+ 15.6 [except.access]
+16 [cpp]
+ 16.1 [cpp.cond]
+ 16.2 [cpp.include]
+ 16.3 [cpp.replace]
+ 16.3.1 [cpp.subst]
+ 16.3.2 [cpp.stringize]
+ 16.3.3 [cpp.concat]
+ 16.3.4 [cpp.rescan]
+ 16.3.5 [cpp.scope]
+ 16.4 [cpp.line]
+ 16.5 [cpp.error]
+ 16.6 [cpp.pragma]
+ 16.7 [cpp.null]
+ 16.8 [cpp.predefined]
+ 16.9 [cpp.pragma.op]
+17 [library]
+ 17.1 [library.general]
+ 17.2 [library.overview]
+ 17.3 [definitions]
+ 17.3.1 [defns.arbitrary.stream]
+ 17.3.2 [defns.blocked]
+ 17.3.3 [defns.character]
+ 17.3.4 [defns.character.container]
+ 17.3.5 [defns.comparison]
+ 17.3.6 [defns.component]
+ 17.3.7 [defns.deadlock]
+ 17.3.8 [defns.default.behavior]
+ 17.3.9 [defns.handler]
+ 17.3.10 [defns.iostream.templates]
+ 17.3.11 [defns.modifier]
+ 17.3.12 [defns.obj.state]
+ 17.3.13 [defns.ntcts]
+ 17.3.14 [defns.narrow.iostream]
+ 17.3.15 [defns.observer]
+ 17.3.16 [defns.replacement]
+ 17.3.17 [defns.repositional.stream]
+ 17.3.18 [defns.required.behavior]
+ 17.3.19 [defns.reserved.function]
+ 17.3.20 [defns.stable]
+ 17.3.21 [defns.traits]
+ 17.3.22 [defns.wide.iostream]
+ 17.4 [defns.additional]
+ 17.5 [description]
+ 17.5.1 [description.general]
+ 17.5.2 [structure]
+ 17.5.2.1 [structure.elements]
+ 17.5.2.2 [structure.summary]
+ 17.5.2.3 [structure.requirements]
+ 17.5.2.4 [structure.specifications]
+ 17.5.2.5 [structure.see.also]
+ 17.5.3 [conventions]
+ 17.5.3.1 [conventions.general]
+ 17.5.3.2 [type.descriptions]
+ 17.5.3.2.1 [type.descriptions.general]
+ 17.5.3.2.2 [enumerated.types]
+ 17.5.3.2.3 [bitmask.types]
+ 17.5.3.2.4 [character.seq]
+ 17.5.3.2.4.1 [character.seq.general]
+ 17.5.3.2.4.2 [byte.strings]
+ 17.5.3.2.4.3 [multibyte.strings]
+ 17.5.3.2.4.4 [char16_t.seq]
+ 17.5.3.2.4.5 [char32_t.seq]
+ 17.5.3.2.4.6 [wide.characters]
+ 17.5.3.3 [functions.within.classes]
+ 17.5.3.4 [objects.within.classes]
+ 17.6 [requirements]
+ 17.6.1 [requirements.general]
+ 17.6.2 [organization]
+ 17.6.2.1 [organization.general]
+ 17.6.2.2 [contents]
+ 17.6.2.3 [headers]
+ 17.6.2.4 [compliance]
+ 17.6.3 [using]
+ 17.6.3.1 [using.overview]
+ 17.6.3.2 [using.headers]
+ 17.6.3.3 [using.linkage]
+ 17.6.4 [constraints]
+ 17.6.4.1 [constraints.overview]
+ 17.6.4.2 [namespace.constraints]
+ 17.6.4.2.1 [namespace.std]
+ 17.6.4.2.2 [namespace.posix]
+ 17.6.4.3 [reserved.names]
+ 17.6.4.3.1 [reserved.names.general]
+ 17.6.4.3.2 [macro.names]
+ 17.6.4.3.3 [global.names]
+ 17.6.4.3.4 [extern.names]
+ 17.6.4.3.5 [extern.types]
+ 17.6.4.3.6 [usrlit.suffix]
+ 17.6.4.4 [alt.headers]
+ 17.6.4.5 [derived.classes]
+ 17.6.4.6 [replacement.functions]
+ 17.6.4.7 [handler.functions]
+ 17.6.4.8 [res.on.functions]
+ 17.6.4.9 [res.on.arguments]
+ 17.6.4.10 [res.on.objects]
+ 17.6.4.11 [res.on.required]
+ 17.6.5 [conforming]
+ 17.6.5.1 [conforming.overview]
+ 17.6.5.2 [res.on.headers]
+ 17.6.5.3 [res.on.macro.definitions]
+ 17.6.5.4 [global.functions]
+ 17.6.5.5 [member.functions]
+ 17.6.5.6 [reentrancy]
+ 17.6.5.7 [res.on.data.races]
+ 17.6.5.8 [protection.within.classes]
+ 17.6.5.9 [derivation]
+ 17.6.5.10 [res.on.exception.handling]
+ 17.6.5.11 [res.on.pointer.storage]
+ 17.6.5.12 [value.error.codes]
+18 [language.support]
+ 18.1 [support.types]
+ 18.2 [support.limits]
+ 18.2.1 [limits]
+ 18.2.1.1 [numeric.limits]
+ 18.2.1.2 [numeric.limits.members]
+ 18.2.1.3 [round.style]
+ 18.2.1.4 [denorm.style]
+ 18.2.1.5 [numeric.special]
+ 18.2.2 [c.limits]
+ 18.3 [cstdint]
+ 18.3.1 [cstdint.syn]
+ 18.3.2 [stdinth]
+ 18.4 [support.start.term]
+ 18.5 [support.dynamic]
+ 18.5.1 [new.delete]
+ 18.5.1.1 [new.delete.single]
+ 18.5.1.2 [new.delete.array]
+ 18.5.1.3 [new.delete.placement]
+ 18.5.1.4 [new.delete.dataraces]
+ 18.5.2 [alloc.errors]
+ 18.5.2.1 [bad.alloc]
+ 18.5.2.2 [new.handler]
+ 18.5.2.3 [set.new.handler]
+ 18.6 [support.rtti]
+ 18.6.1 [type.info]
+ 18.6.2 [type.index]
+ 18.6.2.1 [type.index.overview]
+ 18.6.2.2 [type.index.members]
+ 18.6.2.3 [type.index.templ]
+ 18.6.3 [bad.cast]
+ 18.6.4 [bad.typeid]
+ 18.7 [support.exception]
+ 18.7.1 [exception]
+ 18.7.2 [exception.unexpected]
+ 18.7.2.1 [bad.exception]
+ 18.7.2.2 [unexpected.handler]
+ 18.7.2.3 [set.unexpected]
+ 18.7.2.4 [unexpected]
+ 18.7.3 [exception.terminate]
+ 18.7.3.1 [terminate.handler]
+ 18.7.3.2 [set.terminate]
+ 18.7.3.3 [terminate]
+ 18.7.4 [uncaught]
+ 18.7.5 [propagation]
+ 18.7.6 [except.nested]
+ 18.8 [support.initlist]
+ 18.8.1 [support.initlist.cons]
+ 18.8.2 [support.initlist.access]
+ 18.8.3 [support.initlist.concept]
+ 18.9 [support.runtime]
+19 [diagnostics]
+ 19.1 [std.exceptions]
+ 19.1.1 [logic.error]
+ 19.1.2 [domain.error]
+ 19.1.3 [invalid.argument]
+ 19.1.4 [length.error]
+ 19.1.5 [out.of.range]
+ 19.1.6 [runtime.error]
+ 19.1.7 [range.error]
+ 19.1.8 [overflow.error]
+ 19.1.9 [underflow.error]
+ 19.2 [assertions]
+ 19.3 [errno]
+ 19.4 [syserr]
+ 19.4.1 [syserr.errcat]
+ 19.4.1.1 [syserr.errcat.overview]
+ 19.4.1.2 [syserr.errcat.virtuals]
+ 19.4.1.3 [syserr.errcat.nonvirtuals]
+ 19.4.1.4 [syserr.errcat.derived]
+ 19.4.1.5 [syserr.errcat.objects]
+ 19.4.2 [syserr.errcode]
+ 19.4.2.1 [syserr.errcodeenum]
+ 19.4.2.2 [syserr.errcode.overview]
+ 19.4.2.3 [syserr.errcode.constructors]
+ 19.4.2.4 [syserr.errcode.modifiers]
+ 19.4.2.5 [syserr.errcode.observers]
+ 19.4.2.6 [syserr.errcode.nonmembers]
+ 19.4.3 [syserr.errcondition]
+ 19.4.3.1 [syserr.errcondenum]
+ 19.4.3.2 [syserr.errcondition.overview]
+ 19.4.3.3 [syserr.errcondition.constructors]
+ 19.4.3.4 [syserr.errcondition.modifiers]
+ 19.4.3.5 [syserr.errcondition.observers]
+ 19.4.3.6 [syserr.errcondition.nonmembers]
+ 19.4.4 [syserr.compare]
+ 19.4.5 [syserr.syserr]
+ 19.4.5.1 [syserr.syserr.overview]
+ 19.4.5.2 [syserr.syserr.members]
+20 [utilities]
+ 20.1 [utility.requirements]
+ 20.1.1 [utility.arg.requirements]
+ 20.1.2 [allocator.requirements]
+ 20.2 [utility.concepts]
+ 20.2.1 [concept.transform]
+ 20.2.2 [concept.true]
+ 20.2.3 [concept.operator]
+ 20.2.4 [concept.predicate]
+ 20.2.5 [concept.comparison]
+ 20.2.6 [concept.construct]
+ 20.2.7 [concept.destruct]
+ 20.2.8 [concept.copymove]
+ 20.2.9 [concept.memory]
+ 20.2.10 [concept.regular]
+ 20.2.11 [concept.convertible]
+ 20.2.12 [concept.arithmetic]
+ 20.3 [utility]
+ 20.3.1 [operators]
+ 20.3.2 [forward]
+ 20.3.3 [pairs]
+ 20.3.4 [pair.astuple]
+ 20.3.5 [pair.concepts]
+ 20.3.6 [template.bitset]
+ 20.3.6.1 [bitset.cons]
+ 20.3.6.2 [bitset.members]
+ 20.3.6.3 [bitset.operators]
+ 20.4 [ratio]
+ 20.4.1 [ratio.ratio]
+ 20.4.2 [ratio.arithmetic]
+ 20.4.3 [ratio.comparison]
+ 20.4.4 [ratio.si]
+ 20.5 [tuple]
+ 20.5.1 [tuple.general]
+ 20.5.2 [tuple.tuple]
+ 20.5.2.1 [tuple.traits]
+ 20.5.2.2 [tuple.cnstr]
+ 20.5.2.3 [tuple.creation]
+ 20.5.2.4 [tuple.helper]
+ 20.5.2.5 [tuple.elem]
+ 20.5.2.6 [tuple.rel]
+ 20.5.2.7 [tuple.swap]
+ 20.5.2.8 [tuple.special]
+ 20.5.2.9 [tuple.concepts]
+ 20.6 [meta]
+ 20.6.1 [meta.rqmts]
+ 20.6.2 [meta.type.synop]
+ 20.6.3 [meta.help]
+ 20.6.4 [meta.unary]
+ 20.6.4.1 [meta.unary.cat]
+ 20.6.4.2 [meta.unary.comp]
+ 20.6.4.3 [meta.unary.prop]
+ 20.6.5 [meta.rel]
+ 20.6.6 [meta.trans]
+ 20.6.6.1 [meta.trans.cv]
+ 20.6.6.2 [meta.trans.ref]
+ 20.6.6.3 [meta.trans.sign]
+ 20.6.6.4 [meta.trans.arr]
+ 20.6.6.5 [meta.trans.ptr]
+ 20.6.7 [meta.trans.other]
+ 20.7 [function.objects]
+ 20.7.1 [func.def]
+ 20.7.2 [func.require]
+ 20.7.3 [base]
+ 20.7.4 [func.ret]
+ 20.7.5 [refwrap]
+ 20.7.5.1 [refwrap.const]
+ 20.7.5.2 [refwrap.assign]
+ 20.7.5.3 [refwrap.access]
+ 20.7.5.4 [refwrap.invoke]
+ 20.7.5.5 [refwrap.helpers]
+ 20.7.6 [identity.operation]
+ 20.7.7 [arithmetic.operations]
+ 20.7.8 [comparisons]
+ 20.7.9 [logical.operations]
+ 20.7.10 [bitwise.operations]
+ 20.7.11 [negators]
+ 20.7.12 [bind]
+ 20.7.12.1 [func.bind]
+ 20.7.12.1.1 [func.bind.isbind]
+ 20.7.12.1.2 [func.bind.isplace]
+ 20.7.12.1.3 [func.bind.bind]
+ 20.7.12.1.4 [func.bind.place]
+ 20.7.13 [function.pointer.adaptors]
+ 20.7.14 [member.pointer.adaptors]
+ 20.7.15 [func.memfn]
+ 20.7.16 [func.wrap]
+ 20.7.16.1 [func.wrap.badcall]
+ 20.7.16.1.1 [func.wrap.badcall.const]
+ 20.7.16.2 [func.wrap.func]
+ 20.7.16.2.1 [func.wrap.func.con]
+ 20.7.16.2.2 [func.wrap.func.mod]
+ 20.7.16.2.3 [func.wrap.func.cap]
+ 20.7.16.2.4 [func.wrap.func.inv]
+ 20.7.16.2.5 [func.wrap.func.targ]
+ 20.7.16.2.6 [func.wrap.func.nullptr]
+ 20.7.16.2.7 [func.wrap.func.alg]
+ 20.7.17 [unord.hash]
+ 20.7.18 [func.referenceclosure]
+ 20.7.18.1 [func.referenceclosure.cons]
+ 20.7.18.2 [func.referenceclosure.obs]
+ 20.7.18.3 [func.referenceclosure.invoke]
+ 20.7.18.4 [func.referenceclosure.compare]
+ 20.8 [memory]
+ 20.8.1 [allocator.tag]
+ 20.8.2 [allocator]
+ 20.8.2.1 [allocator.general]
+ 20.8.2.2 [allocator.concepts]
+ 20.8.3 [allocator.element.concepts]
+ 20.8.4 [allocator.propagation]
+ 20.8.5 [allocator.propagation.map]
+ 20.8.6 [default.allocator]
+ 20.8.6.1 [allocator.members]
+ 20.8.6.2 [allocator.globals]
+ 20.8.7 [allocator.adaptor]
+ 20.8.7.1 [allocator.adaptor.cntr]
+ 20.8.7.2 [allocator.adaptor.members]
+ 20.8.7.3 [allocator.adaptor.globals]
+ 20.8.8 [storage.iterator]
+ 20.8.9 [temporary.buffer]
+ 20.8.10 [construct.element]
+ 20.8.11 [specialized.algorithms]
+ 20.8.11.1 [object.addressof]
+ 20.8.11.2 [uninitialized.copy]
+ 20.8.11.3 [uninitialized.fill]
+ 20.8.11.4 [uninitialized.fill.n]
+ 20.8.12 [unique.ptr]
+ 20.8.12.1 [unique.ptr.dltr]
+ 20.8.12.1.1 [unique.ptr.dltr.dflt]
+ 20.8.12.1.2 [unique.ptr.dltr.dflt1]
+ 20.8.12.1.3 [unique.ptr.dltr.dflt2]
+ 20.8.12.2 [unique.ptr.single]
+ 20.8.12.2.1 [unique.ptr.single.ctor]
+ 20.8.12.2.2 [unique.ptr.single.dtor]
+ 20.8.12.2.3 [unique.ptr.single.asgn]
+ 20.8.12.2.4 [unique.ptr.single.observers]
+ 20.8.12.2.5 [unique.ptr.single.modifiers]
+ 20.8.12.3 [unique.ptr.runtime]
+ 20.8.12.3.1 [unique.ptr.runtime.ctor]
+ 20.8.12.3.2 [unique.ptr.runtime.observers]
+ 20.8.12.3.3 [unique.ptr.runtime.modifiers]
+ X [unique.ptr.compiletime]
+ 20.8.12.4 [unique.ptr.special]
+ 20.8.13 [util.smartptr]
+ 20.8.13.1 [util.smartptr.weakptr]
+ 20.8.13.2 [util.smartptr.shared]
+ 20.8.13.2.1 [util.smartptr.shared.const]
+ 20.8.13.2.2 [util.smartptr.shared.dest]
+ 20.8.13.2.3 [util.smartptr.shared.assign]
+ 20.8.13.2.4 [util.smartptr.shared.mod]
+ 20.8.13.2.5 [util.smartptr.shared.obs]
+ 20.8.13.2.6 [util.smartptr.shared.create]
+ 20.8.13.2.7 [util.smartptr.shared.cmp]
+ 20.8.13.2.8 [util.smartptr.shared.io]
+ 20.8.13.2.9 [util.smartptr.shared.spec]
+ 20.8.13.2.10 [util.smartptr.shared.cast]
+ 20.8.13.2.11 [util.smartptr.getdeleter]
+ 20.8.13.3 [util.smartptr.weak]
+ 20.8.13.3.1 [util.smartptr.weak.const]
+ 20.8.13.3.2 [util.smartptr.weak.dest]
+ 20.8.13.3.3 [util.smartptr.weak.assign]
+ 20.8.13.3.4 [util.smartptr.weak.mod]
+ 20.8.13.3.5 [util.smartptr.weak.obs]
+ 20.8.13.3.6 [util.smartptr.weak.cmp]
+ 20.8.13.3.7 [util.smartptr.weak.spec]
+ 20.8.13.4 [util.smartptr.ownerless]
+ 20.8.13.5 [util.smartptr.enab]
+ 20.8.13.6 [util.smartptr.shared.atomic]
+ 20.8.13.7 [util.dynamic.safety]
+ 20.8.14 [ptr.align]
+ 20.8.15 [c.malloc]
+ 20.9 [time]
+ 20.9.1 [time.clock.req]
+ 20.9.2 [time.traits]
+ 20.9.2.1 [time.traits.is_fp]
+ 20.9.2.2 [time.traits.duration_values]
+ 20.9.2.3 [time.traits.specializations]
+ 20.9.3 [time.duration]
+ 20.9.3.1 [time.duration.cons]
+ 20.9.3.2 [time.duration.observer]
+ 20.9.3.3 [time.duration.arithmetic]
+ 20.9.3.4 [time.duration.special]
+ 20.9.3.5 [time.duration.nonmember]
+ 20.9.3.6 [time.duration.comparisons]
+ 20.9.3.7 [time.duration.cast]
+ 20.9.4 [time.point]
+ 20.9.4.1 [time.point.cons]
+ 20.9.4.2 [time.point.observer]
+ 20.9.4.3 [time.point.arithmetic]
+ 20.9.4.4 [time.point.special]
+ 20.9.4.5 [time.point.nonmember]
+ 20.9.4.6 [time.point.comparisons]
+ 20.9.4.7 [time.point.cast]
+ 20.9.5 [time.clock]
+ 20.9.5.1 [time.clock.system]
+ 20.9.5.2 [time.clock.monotonic]
+ 20.9.5.3 [time.clock.hires]
+ 20.10 [date.time]
+21 [strings]
+ 21.1 [char.traits]
+ 21.1.1 [char.traits.require]
+ 21.1.2 [char.traits.typedefs]
+ 21.1.3 [char.traits.specializations]
+ 21.1.3.1 [char.traits.specializations.char]
+ 21.1.3.2 [char.traits.specializations.char16_t]
+ 21.1.3.3 [char.traits.specializations.char32_t]
+ 21.1.3.4 [char.traits.specializations.wchar.t]
+ 21.2 [string.classes]
+ 21.3 [basic.string]
+ 21.3.1 [string.require]
+ 21.3.2 [string.cons]
+ 21.3.3 [string.iterators]
+ 21.3.4 [string.capacity]
+ 21.3.5 [string.access]
+ 21.3.6 [string.modifiers]
+ 21.3.6.1 [string::op+=]
+ 21.3.6.2 [string::append]
+ 21.3.6.3 [string::assign]
+ 21.3.6.4 [string::insert]
+ 21.3.6.5 [string::erase]
+ 21.3.6.6 [string::replace]
+ 21.3.6.7 [string::copy]
+ 21.3.6.8 [string::swap]
+ 21.3.7 [string.ops]
+ 21.3.7.1 [string.accessors]
+ 21.3.7.2 [string::find]
+ 21.3.7.3 [string::rfind]
+ 21.3.7.4 [string::find.first.of]
+ 21.3.7.5 [string::find.last.of]
+ 21.3.7.6 [string::find.first.not.of]
+ 21.3.7.7 [string::find.last.not.of]
+ 21.3.7.8 [string::substr]
+ 21.3.7.9 [string::compare]
+ 21.3.8 [string.nonmembers]
+ 21.3.8.1 [string::op+]
+ 21.3.8.2 [string::operator==]
+ 21.3.8.3 [string::op!=]
+ 21.3.8.4 [string::op&lt;]
+ 21.3.8.5 [string::op&gt;]
+ 21.3.8.6 [string::op&lt;=]
+ 21.3.8.7 [string::op&gt;=]
+ 21.3.8.8 [string.special]
+ 21.3.8.9 [string.io]
+ 21.4 [string.conversions]
+ 21.5 [c.strings]
+22 [localization]
+ 22.1 [locales]
+ 22.1.1 [locale]
+ 22.1.1.1 [locale.types]
+ 22.1.1.1.1 [locale.category]
+ 22.1.1.1.2 [locale.facet]
+ 22.1.1.1.3 [locale.id]
+ 22.1.1.2 [locale.cons]
+ 22.1.1.3 [locale.members]
+ 22.1.1.4 [locale.operators]
+ 22.1.1.5 [locale.statics]
+ 22.1.2 [locale.global.templates]
+ 22.1.3 [locale.convenience]
+ 22.1.3.1 [classification]
+ 22.1.3.2 [conversions]
+ 22.1.3.2.1 [conversions.character]
+ 22.1.3.2.2 [conversions.string]
+ 22.1.3.2.3 [conversions.buffer]
+ 22.2 [locale.categories]
+ 22.2.1 [category.ctype]
+ 22.2.1.1 [locale.ctype]
+ 22.2.1.1.1 [locale.ctype.members]
+ 22.2.1.1.2 [locale.ctype.virtuals]
+ 22.2.1.2 [locale.ctype.byname]
+ 22.2.1.3 [facet.ctype.special]
+ 22.2.1.3.1 [facet.ctype.char.dtor]
+ 22.2.1.3.2 [facet.ctype.char.members]
+ 22.2.1.3.3 [facet.ctype.char.statics]
+ 22.2.1.3.4 [facet.ctype.char.virtuals]
+ 22.2.1.4 [locale.codecvt]
+ 22.2.1.4.1 [locale.codecvt.members]
+ 22.2.1.4.2 [locale.codecvt.virtuals]
+ 22.2.1.5 [locale.codecvt.byname]
+ 22.2.2 [category.numeric]
+ 22.2.2.1 [locale.num.get]
+ 22.2.2.1.1 [facet.num.get.members]
+ 22.2.2.1.2 [facet.num.get.virtuals]
+ 22.2.2.2 [locale.nm.put]
+ 22.2.2.2.1 [facet.num.put.members]
+ 22.2.2.2.2 [facet.num.put.virtuals]
+ 22.2.3 [facet.numpunct]
+ 22.2.3.1 [locale.numpunct]
+ 22.2.3.1.1 [facet.numpunct.members]
+ 22.2.3.1.2 [facet.numpunct.virtuals]
+ 22.2.3.2 [locale.numpunct.byname]
+ 22.2.4 [category.collate]
+ 22.2.4.1 [locale.collate]
+ 22.2.4.1.1 [locale.collate.members]
+ 22.2.4.1.2 [locale.collate.virtuals]
+ 22.2.4.2 [locale.collate.byname]
+ 22.2.5 [category.time]
+ 22.2.5.1 [locale.time.get]
+ 22.2.5.1.1 [locale.time.get.members]
+ 22.2.5.1.2 [locale.time.get.virtuals]
+ 22.2.5.2 [locale.time.get.byname]
+ 22.2.5.3 [locale.time.put]
+ 22.2.5.3.1 [locale.time.put.members]
+ 22.2.5.3.2 [locale.time.put.virtuals]
+ 22.2.5.4 [locale.time.put.byname]
+ 22.2.6 [category.monetary]
+ 22.2.6.1 [locale.money.get]
+ 22.2.6.1.1 [locale.money.get.members]
+ 22.2.6.1.2 [locale.money.get.virtuals]
+ 22.2.6.2 [locale.money.put]
+ 22.2.6.2.1 [locale.money.put.members]
+ 22.2.6.2.2 [locale.money.put.virtuals]
+ 22.2.6.3 [locale.moneypunct]
+ 22.2.6.3.1 [locale.moneypunct.members]
+ 22.2.6.3.2 [locale.moneypunct.virtuals]
+ 22.2.6.4 [locale.moneypunct.byname]
+ 22.2.7 [category.messages]
+ 22.2.7.1 [locale.messages]
+ 22.2.7.1.1 [locale.messages.members]
+ 22.2.7.1.2 [locale.messages.virtuals]
+ 22.2.7.2 [locale.messages.byname]
+ 22.2.8 [facets.examples]
+ 22.3 [locale.stdcvt]
+ 22.4 [c.locales]
+23 [containers]
+ 23.1 [container.requirements]
+ 23.1.1 [container.requirements.general]
+ 23.1.2 [container.requirements.dataraces]
+ 23.1.3 [sequence.reqmts]
+ 23.1.4 [associative.reqmts]
+ 23.1.4.1 [associative.reqmts.except]
+ 23.1.5 [unord.req]
+ 23.1.5.1 [unord.req.except]
+ 23.1.6 [container.concepts]
+ 23.1.6.1 [container.concepts.free]
+ 23.1.6.2 [container.concepts.member]
+ 23.1.6.3 [container.concepts.maps]
+ 23.2 [sequences]
+ 23.2.1 [array]
+ 23.2.1.1 [array.cons]
+ 23.2.1.2 [array.special]
+ 23.2.1.3 [array.size]
+ 23.2.1.4 [array.data]
+ 23.2.1.5 [array.fill]
+ 23.2.1.6 [array.zero]
+ 23.2.1.7 [array.tuple]
+ 23.2.2 [deque]
+ 23.2.2.1 [deque.cons]
+ 23.2.2.2 [deque.capacity]
+ 23.2.2.3 [deque.modifiers]
+ 23.2.2.4 [deque.special]
+ 23.2.3 [forwardlist]
+ 23.2.3.1 [forwardlist.cons]
+ 23.2.3.2 [forwardlist.iter]
+ 23.2.3.3 [forwardlist.access]
+ 23.2.3.4 [forwardlist.modifiers]
+ 23.2.3.5 [forwardlist.ops]
+ 23.2.3.6 [forwardlist.spec]
+ 23.2.4 [list]
+ 23.2.4.1 [list.cons]
+ 23.2.4.2 [list.capacity]
+ 23.2.4.3 [list.modifiers]
+ 23.2.4.4 [list.ops]
+ 23.2.4.5 [list.special]
+ 23.2.5 [container.adaptors]
+ 23.2.5.1 [queue]
+ 23.2.5.1.1 [queue.defn]
+ 23.2.5.1.2 [queue.ops]
+ 23.2.5.1.3 [queue.special]
+ 23.2.5.2 [priority.queue]
+ 23.2.5.2.1 [priqueue.cons]
+ 23.2.5.2.2 [priqueue.members]
+ 23.2.5.2.3 [priqueue.special]
+ 23.2.5.3 [stack]
+ 23.2.5.3.1 [stack.defn]
+ 23.2.5.3.2 [stack.ops]
+ 23.2.5.3.3 [stack.special]
+ 23.2.6 [vector]
+ 23.2.6.1 [vector.cons]
+ 23.2.6.2 [vector.capacity]
+ 23.2.6.3 [vector.data]
+ 23.2.6.4 [vector.modifiers]
+ 23.2.6.5 [vector.special]
+ 23.2.7 [vector.bool]
+ 23.3 [associative]
+ 23.3.1 [map]
+ 23.3.1.1 [map.cons]
+ 23.3.1.2 [map.access]
+ 23.3.1.3 [map.modifiers]
+ 23.3.1.4 [map.ops]
+ 23.3.1.5 [map.special]
+ 23.3.2 [multimap]
+ 23.3.2.1 [multimap.cons]
+ 23.3.2.2 [multimap.modifiers]
+ 23.3.2.3 [multimap.ops]
+ 23.3.2.4 [multimap.special]
+ 23.3.3 [set]
+ 23.3.3.1 [set.cons]
+ 23.3.3.2 [set.special]
+ 23.3.4 [multiset]
+ 23.3.4.1 [multiset.cons]
+ 23.3.4.2 [multiset.special]
+ 23.4 [unord]
+ 23.4.1 [unord.map]
+ 23.4.1.1 [unord.map.cnstr]
+ 23.4.1.2 [unord.map.elem]
+ 23.4.1.3 [unord.map.swap]
+ 23.4.2 [unord.multimap]
+ 23.4.2.1 [unord.multimap.cnstr]
+ 23.4.2.2 [unord.multimap.swap]
+ 23.4.3 [unord.set]
+ 23.4.3.1 [unord.set.cnstr]
+ 23.4.3.2 [unord.set.swap]
+ 23.4.4 [unord.multiset]
+ 23.4.4.1 [unord.multiset.cnstr]
+ 23.4.4.2 [unord.multiset.swap]
+24 [iterators]
+ 24.1 [iterator.concepts]
+ 24.1.1 [iterator.iterators]
+ 24.1.2 [input.iterators]
+ 24.1.3 [output.iterators]
+ 24.1.4 [forward.iterators]
+ 24.1.5 [bidirectional.iterators]
+ 24.1.6 [random.access.iterators]
+ 24.1.7 [shuffle.iterators]
+ 24.1.8 [iterator.concepts.range]
+ 24.2 [iterator.synopsis]
+ 24.3 [iterator.operations]
+ 24.4 [predef.iterators]
+ 24.4.1 [reverse.iterators]
+ 24.4.1.1 [reverse.iterator]
+ 24.4.1.2 [reverse.iter.requirements]
+ 24.4.1.3 [reverse.iter.ops]
+ 24.4.1.3.1 [reverse.iter.cons]
+ 24.4.1.3.2 [reverse.iter.op=]
+ 24.4.1.3.3 [reverse.iter.conv]
+ 24.4.1.3.4 [reverse.iter.op.star]
+ 24.4.1.3.5 [reverse.iter.opref]
+ 24.4.1.3.6 [reverse.iter.op++]
+ 24.4.1.3.7 [reverse.iter.op--]
+ 24.4.1.3.8 [reverse.iter.op+]
+ 24.4.1.3.9 [reverse.iter.op+=]
+ 24.4.1.3.10 [reverse.iter.op-]
+ 24.4.1.3.11 [reverse.iter.op-=]
+ 24.4.1.3.12 [reverse.iter.opindex]
+ 24.4.1.3.13 [reverse.iter.op==]
+ 24.4.1.3.14 [reverse.iter.op&lt;]
+ 24.4.1.3.15 [reverse.iter.op!=]
+ 24.4.1.3.16 [reverse.iter.op&gt;]
+ 24.4.1.3.17 [reverse.iter.op&gt;=]
+ 24.4.1.3.18 [reverse.iter.op&lt;=]
+ 24.4.1.3.19 [reverse.iter.opdiff]
+ 24.4.1.3.20 [reverse.iter.opsum]
+ 24.4.1.4 [reverse.iter.maps]
+ 24.4.2 [insert.iterators]
+ 24.4.2.1 [back.insert.iterator]
+ 24.4.2.2 [back.insert.iter.ops]
+ 24.4.2.2.1 [back.insert.iter.cons]
+ 24.4.2.2.2 [back.insert.iter.op=]
+ 24.4.2.2.3 [back.insert.iter.op*]
+ 24.4.2.2.4 [back.insert.iter.op++]
+ 24.4.2.2.5 [back.inserter]
+ 24.4.2.2.6 [back.insert.iter.maps]
+ 24.4.2.3 [front.insert.iterator]
+ 24.4.2.4 [front.insert.iter.ops]
+ 24.4.2.4.1 [front.insert.iter.cons]
+ 24.4.2.4.2 [front.insert.iter.op=]
+ 24.4.2.4.3 [front.insert.iter.op*]
+ 24.4.2.4.4 [front.insert.iter.op++]
+ 24.4.2.4.5 [front.inserter]
+ 24.4.2.4.6 [front.insert.iter.maps]
+ 24.4.2.5 [insert.iterator]
+ 24.4.2.6 [insert.iter.ops]
+ 24.4.2.6.1 [insert.iter.cons]
+ 24.4.2.6.2 [insert.iter.op=]
+ 24.4.2.6.3 [insert.iter.op*]
+ 24.4.2.6.4 [insert.iter.op++]
+ 24.4.2.6.5 [inserter]
+ 24.4.2.6.6 [insert.iter.maps]
+ 24.4.3 [move.iterators]
+ 24.4.3.1 [move.iterator]
+ 24.4.3.2 [move.iter.requirements]
+ 24.4.3.3 [move.iter.ops]
+ 24.4.3.3.1 [move.iter.op.const]
+ 24.4.3.3.2 [move.iter.op=]
+ 24.4.3.3.3 [move.iter.op.conv]
+ 24.4.3.3.4 [move.iter.op.star]
+ 24.4.3.3.5 [move.iter.op.ref]
+ 24.4.3.3.6 [move.iter.op.incr]
+ 24.4.3.3.7 [move.iter.op.decr]
+ 24.4.3.3.8 [move.iter.op.+]
+ 24.4.3.3.9 [move.iter.op.+=]
+ 24.4.3.3.10 [move.iter.op.-]
+ 24.4.3.3.11 [move.iter.op.-=]
+ 24.4.3.3.12 [move.iter.op.index]
+ 24.4.3.3.13 [move.iter.op.comp]
+ 24.4.3.3.14 [move.iter.nonmember]
+ 24.4.3.3.15 [move.iter.maps]
+ 24.5 [stream.iterators]
+ 24.5.1 [istream.iterator]
+ 24.5.1.1 [istream.iterator.cons]
+ 24.5.1.2 [istream.iterator.ops]
+ 24.5.2 [ostream.iterator]
+ 24.5.2.1 [ostream.iterator.cons.des]
+ 24.5.2.2 [ostream.iterator.ops]
+ 24.5.3 [istreambuf.iterator]
+ 24.5.3.1 [istreambuf.iterator::proxy]
+ 24.5.3.2 [istreambuf.iterator.cons]
+ 24.5.3.3 [istreambuf.iterator::op*]
+ 24.5.3.4 [istreambuf.iterator::op++]
+ 24.5.3.5 [istreambuf.iterator::equal]
+ 24.5.3.6 [istreambuf.iterator::op==]
+ 24.5.3.7 [istreambuf.iterator::op!=]
+ 24.5.4 [ostreambuf.iterator]
+ 24.5.4.1 [ostreambuf.iter.cons]
+ 24.5.4.2 [ostreambuf.iter.ops]
+25 [algorithms]
+ 25.1 [alg.nonmodifying]
+ 25.1.1 [alg.all_of]
+ 25.1.2 [alg.any_of]
+ 25.1.3 [alg.none_of]
+ 25.1.4 [alg.foreach]
+ 25.1.5 [alg.find]
+ 25.1.6 [alg.find.end]
+ 25.1.7 [alg.find.first.of]
+ 25.1.8 [alg.adjacent.find]
+ 25.1.9 [alg.count]
+ 25.1.10 [mismatch]
+ 25.1.11 [alg.equal]
+ 25.1.12 [alg.search]
+ 25.2 [alg.modifying.operations]
+ 25.2.1 [alg.copy]
+ 25.2.2 [alg.move]
+ 25.2.3 [alg.swap]
+ 25.2.4 [alg.transform]
+ 25.2.5 [alg.replace]
+ 25.2.6 [alg.fill]
+ 25.2.7 [alg.generate]
+ 25.2.8 [alg.remove]
+ 25.2.9 [alg.unique]
+ 25.2.10 [alg.reverse]
+ 25.2.11 [alg.rotate]
+ 25.2.12 [alg.random.shuffle]
+ 25.2.13 [alg.partitions]
+ 25.3 [alg.sorting]
+ 25.3.1 [alg.sort]
+ 25.3.1.1 [sort]
+ 25.3.1.2 [stable.sort]
+ 25.3.1.3 [partial.sort]
+ 25.3.1.4 [partial.sort.copy]
+ 25.3.1.5 [is.sorted]
+ 25.3.2 [alg.nth.element]
+ 25.3.3 [alg.binary.search]
+ 25.3.3.1 [lower.bound]
+ 25.3.3.2 [upper.bound]
+ 25.3.3.3 [equal.range]
+ 25.3.3.4 [binary.search]
+ 25.3.4 [alg.merge]
+ 25.3.5 [alg.set.operations]
+ 25.3.5.1 [includes]
+ 25.3.5.2 [set.union]
+ 25.3.5.3 [set.intersection]
+ 25.3.5.4 [set.difference]
+ 25.3.5.5 [set.symmetric.difference]
+ 25.3.6 [alg.heap.operations]
+ 25.3.6.1 [push.heap]
+ 25.3.6.2 [pop.heap]
+ 25.3.6.3 [make.heap]
+ 25.3.6.4 [sort.heap]
+ 25.3.6.5 [is.heap]
+ 25.3.7 [alg.min.max]
+ 25.3.8 [alg.lex.comparison]
+ 25.3.9 [alg.permutation.generators]
+ 25.4 [alg.c.library]
+26 [numerics]
+ 26.1 [numeric.requirements]
+ 26.2 [cfenv]
+ 26.2.1 [cfenv.syn]
+ 26.2.2 [fenv]
+ 26.3 [complex.numbers]
+ 26.3.1 [complex.synopsis]
+ 26.3.2 [complex]
+ 26.3.3 [complex.special]
+ 26.3.4 [complex.members]
+ 26.3.5 [complex.member.ops]
+ 26.3.6 [complex.ops]
+ 26.3.7 [complex.value.ops]
+ 26.3.8 [complex.transcendentals]
+ 26.3.9 [cmplx.over]
+ 26.3.10 [ccmplx]
+ 26.3.11 [cmplxh]
+ 26.4 [rand]
+ 26.4.1 [rand.req]
+ 26.4.1.1 [rand.req.genl]
+ 26.4.1.2 [rand.req.urng]
+ 26.4.1.3 [rand.req.eng]
+ 26.4.1.4 [rand.req.adapt]
+ 26.4.1.5 [rand.req.dist]
+ 26.4.2 [rand.synopsis]
+ 26.4.3 [rand.eng]
+ 26.4.3.1 [rand.eng.lcong]
+ 26.4.3.2 [rand.eng.mers]
+ 26.4.3.3 [rand.eng.sub]
+ 26.4.4 [rand.adapt]
+ 26.4.4.1 [rand.adapt.disc]
+ 26.4.4.2 [rand.adapt.ibits]
+ 26.4.4.3 [rand.adapt.shuf]
+ X [rand.adapt.xor]
+ 26.4.5 [rand.predef]
+ 26.4.6 [rand.device]
+ 26.4.7 [rand.util]
+ 26.4.7.1 [rand.util.seedseq]
+ 26.4.7.2 [rand.util.canonical]
+ 26.4.8 [rand.dist]
+ 26.4.8.1 [rand.dist.uni]
+ 26.4.8.1.1 [rand.dist.uni.int]
+ 26.4.8.1.2 [rand.dist.uni.real]
+ 26.4.8.2 [rand.dist.bern]
+ 26.4.8.2.1 [rand.dist.bern.bernoulli]
+ 26.4.8.2.2 [rand.dist.bern.bin]
+ 26.4.8.2.3 [rand.dist.bern.geo]
+ 26.4.8.2.4 [rand.dist.bern.negbin]
+ 26.4.8.3 [rand.dist.pois]
+ 26.4.8.3.1 [rand.dist.pois.poisson]
+ 26.4.8.3.2 [rand.dist.pois.exp]
+ 26.4.8.3.3 [rand.dist.pois.gamma]
+ 26.4.8.3.4 [rand.dist.pois.weibull]
+ 26.4.8.3.5 [rand.dist.pois.extreme]
+ 26.4.8.4 [rand.dist.norm]
+ 26.4.8.4.1 [rand.dist.norm.normal]
+ 26.4.8.4.2 [rand.dist.norm.lognormal]
+ 26.4.8.4.3 [rand.dist.norm.chisq]
+ 26.4.8.4.4 [rand.dist.norm.cauchy]
+ 26.4.8.4.5 [rand.dist.norm.f]
+ 26.4.8.4.6 [rand.dist.norm.t]
+ 26.4.8.5 [rand.dist.samp]
+ 26.4.8.5.1 [rand.dist.samp.discrete]
+ 26.4.8.5.2 [rand.dist.samp.pconst]
+ 26.4.8.5.3 [rand.dist.samp.genpdf]
+ 26.5 [numarray]
+ 26.5.1 [valarray.synopsis]
+ 26.5.2 [template.valarray]
+ 26.5.2.1 [valarray.cons]
+ 26.5.2.2 [valarray.assign]
+ 26.5.2.3 [valarray.access]
+ 26.5.2.4 [valarray.sub]
+ 26.5.2.5 [valarray.unary]
+ 26.5.2.6 [valarray.cassign]
+ 26.5.2.7 [valarray.members]
+ 26.5.3 [valarray.nonmembers]
+ 26.5.3.1 [valarray.binary]
+ 26.5.3.2 [valarray.comparison]
+ 26.5.3.3 [valarray.transcend]
+ 26.5.3.4 [valarray.special]
+ 26.5.4 [class.slice]
+ 26.5.4.1 [cons.slice]
+ 26.5.4.2 [slice.access]
+ 26.5.5 [template.slice.array]
+ 26.5.5.1 [slice.arr.assign]
+ 26.5.5.2 [slice.arr.comp.assign]
+ 26.5.5.3 [slice.arr.fill]
+ 26.5.6 [class.gslice]
+ 26.5.6.1 [gslice.cons]
+ 26.5.6.2 [gslice.access]
+ 26.5.7 [template.gslice.array]
+ 26.5.7.1 [gslice.array.assign]
+ 26.5.7.2 [gslice.array.comp.assign]
+ 26.5.7.3 [gslice.array.fill]
+ 26.5.8 [template.mask.array]
+ 26.5.8.1 [mask.array.assign]
+ 26.5.8.2 [mask.array.comp.assign]
+ 26.5.8.3 [mask.array.fill]
+ 26.5.9 [template.indirect.array]
+ 26.5.9.1 [indirect.array.assign]
+ 26.5.9.2 [indirect.array.comp.assign]
+ 26.5.9.3 [indirect.array.fill]
+ 26.5.9.4 [valarray.concepts]
+ 26.6 [numeric.ops]
+ 26.6.1 [accumulate]
+ 26.6.2 [inner.product]
+ 26.6.3 [partial.sum]
+ 26.6.4 [adjacent.difference]
+ 26.6.5 [numeric.iota]
+ 26.7 [c.math]
+27 [input.output]
+ 27.1 [iostreams.requirements]
+ 27.1.1 [iostream.limits.imbue]
+ 27.1.2 [iostreams.limits.pos]
+ 27.1.3 [iostreams.threadsafety]
+ 27.2 [iostream.forward]
+ 27.3 [iostream.objects]
+ 27.3.1 [narrow.stream.objects]
+ 27.3.2 [wide.stream.objects]
+ 27.4 [iostreams.base]
+ 27.4.1 [stream.types]
+ 27.4.2 [ios.base]
+ 27.4.2.1 [ios.types]
+ 27.4.2.1.1 [ios::failure]
+ 27.4.2.1.2 [ios::fmtflags]
+ 27.4.2.1.3 [ios::iostate]
+ 27.4.2.1.4 [ios::openmode]
+ 27.4.2.1.5 [ios::seekdir]
+ 27.4.2.1.6 [ios::Init]
+ 27.4.2.2 [fmtflags.state]
+ 27.4.2.3 [ios.base.locales]
+ 27.4.2.4 [ios.members.static]
+ 27.4.2.5 [ios.base.storage]
+ 27.4.2.6 [ios.base.callback]
+ 27.4.2.7 [ios.base.cons]
+ 27.4.3 [fpos]
+ 27.4.3.1 [fpos.members]
+ 27.4.3.2 [fpos.operations]
+ 27.4.4 [ios]
+ 27.4.4.1 [basic.ios.cons]
+ 27.4.4.2 [basic.ios.members]
+ 27.4.4.3 [iostate.flags]
+ 27.4.5 [std.ios.manip]
+ 27.4.5.1 [fmtflags.manip]
+ 27.4.5.2 [adjustfield.manip]
+ 27.4.5.3 [basefield.manip]
+ 27.4.5.4 [floatfield.manip]
+ 27.4.5.5 [error.reporting]
+ 27.5 [stream.buffers]
+ 27.5.1 [streambuf.reqts]
+ 27.5.2 [streambuf]
+ 27.5.2.1 [streambuf.cons]
+ 27.5.2.2 [streambuf.members]
+ 27.5.2.2.1 [streambuf.locales]
+ 27.5.2.2.2 [streambuf.buffer]
+ 27.5.2.2.3 [streambuf.pub.get]
+ 27.5.2.2.4 [streambuf.pub.pback]
+ 27.5.2.2.5 [streambuf.pub.put]
+ 27.5.2.3 [streambuf.protected]
+ 27.5.2.3.1 [streambuf.assign]
+ 27.5.2.3.2 [streambuf.get.area]
+ 27.5.2.3.3 [streambuf.put.area]
+ 27.5.2.4 [streambuf.virtuals]
+ 27.5.2.4.1 [streambuf.virt.locales]
+ 27.5.2.4.2 [streambuf.virt.buffer]
+ 27.5.2.4.3 [streambuf.virt.get]
+ 27.5.2.4.4 [streambuf.virt.pback]
+ 27.5.2.4.5 [streambuf.virt.put]
+ 27.6 [iostream.format]
+ 27.6.1 [input.streams]
+ 27.6.1.1 [istream]
+ 27.6.1.1.1 [istream.cons]
+ 27.6.1.1.2 [istream.assign]
+ 27.6.1.1.3 [istream::sentry]
+ 27.6.1.2 [istream.formatted]
+ 27.6.1.2.1 [istream.formatted.reqmts]
+ 27.6.1.2.2 [istream.formatted.arithmetic]
+ 27.6.1.2.3 [istream::extractors]
+ 27.6.1.3 [istream.unformatted]
+ 27.6.1.4 [istream.manip]
+ 27.6.1.5 [iostreamclass]
+ 27.6.1.5.1 [iostream.cons]
+ 27.6.1.5.2 [iostream.dest]
+ 27.6.1.5.3 [iostream.assign]
+ 27.6.2 [output.streams]
+ 27.6.2.1 [ostream]
+ 27.6.2.2 [ostream.cons]
+ 27.6.2.3 [ostream.assign]
+ 27.6.2.4 [ostream::sentry]
+ 27.6.2.5 [ostream.seeks]
+ 27.6.2.6 [ostream.formatted]
+ 27.6.2.6.1 [ostream.formatted.reqmts]
+ 27.6.2.6.2 [ostream.inserters.arithmetic]
+ 27.6.2.6.3 [ostream.inserters]
+ 27.6.2.6.4 [ostream.inserters.character]
+ 27.6.2.7 [ostream.unformatted]
+ 27.6.2.8 [ostream.manip]
+ 27.6.3 [std.manip]
+ 27.6.4 [ext.manip]
+ 27.7 [string.streams]
+ 27.7.1 [stringbuf]
+ 27.7.1.1 [stringbuf.cons]
+ 27.7.1.2 [stringbuf.assign]
+ 27.7.1.3 [stringbuf.members]
+ 27.7.1.4 [stringbuf.virtuals]
+ 27.7.2 [istringstream]
+ 27.7.2.1 [istringstream.cons]
+ 27.7.2.2 [istringstream.assign]
+ 27.7.2.3 [istringstream.members]
+ 27.7.3 [ostringstream]
+ 27.7.3.1 [ostringstream.cons]
+ 27.7.3.2 [ostringstream.assign]
+ 27.7.3.3 [ostringstream.members]
+ 27.7.4 [stringstream]
+ 27.7.5 [stringstream.cons]
+ 27.7.5.1 [stringstream.assign]
+ 27.7.6 [stringstream.members]
+ 27.8 [file.streams]
+ 27.8.1 [fstreams]
+ 27.8.1.1 [filebuf]
+ 27.8.1.2 [filebuf.cons]
+ 27.8.1.3 [filebuf.assign]
+ 27.8.1.4 [filebuf.members]
+ 27.8.1.5 [filebuf.virtuals]
+ 27.8.1.6 [ifstream]
+ 27.8.1.7 [ifstream.cons]
+ 27.8.1.8 [ifstream.assign]
+ 27.8.1.9 [ifstream.members]
+ 27.8.1.10 [ofstream]
+ 27.8.1.11 [ofstream.cons]
+ 27.8.1.12 [ofstream.assign]
+ 27.8.1.13 [ofstream.members]
+ 27.8.1.14 [fstream]
+ 27.8.1.15 [fstream.cons]
+ 27.8.1.16 [fstream.assign]
+ 27.8.1.17 [fstream.members]
+ 27.8.2 [c.files]
+28 [re]
+ 28.1 [re.def]
+ 28.1.1 [defns.regex.collating.element]
+ 28.1.2 [defns.regex.finite.state.machine]
+ 28.1.3 [defns.regex.format.specifier]
+ 28.1.4 [defns.regex.matched]
+ 28.1.5 [defns.regex.primary.equivalence.class]
+ 28.1.6 [defns.regex.regular.expression]
+ 28.1.7 [defns.regex.subexpression]
+ 28.2 [re.req]
+ 28.3 [re.sum]
+ 28.4 [re.syn]
+ 28.5 [re.const]
+ 28.5.1 [re.synopt]
+ 28.5.2 [re.matchflag]
+ 28.5.3 [re.err]
+ 28.6 [re.badexp]
+ 28.7 [re.traits]
+ 28.8 [re.regex]
+ 28.8.1 [re.regex.const]
+ 28.8.2 [re.regex.construct]
+ 28.8.3 [re.regex.assign]
+ 28.8.4 [re.regex.operations]
+ 28.8.5 [re.regex.locale]
+ 28.8.6 [re.regex.swap]
+ 28.8.7 [re.regex.nonmemb]
+ 28.8.7.1 [re.regex.nmswap]
+ 28.9 [re.submatch]
+ 28.9.1 [re.submatch.members]
+ 28.9.2 [re.submatch.op]
+ 28.9.3 [re.submatch.concepts]
+ 28.10 [re.results]
+ 28.10.1 [re.results.const]
+ 28.10.2 [re.results.size]
+ 28.10.3 [re.results.acc]
+ 28.10.4 [re.results.form]
+ 28.10.5 [re.results.all]
+ 28.10.6 [re.results.swap]
+ 28.10.7 [re.results.nonmember]
+ 28.11 [re.alg]
+ 28.11.1 [re.except]
+ 28.11.2 [re.alg.match]
+ 28.11.3 [re.alg.search]
+ 28.11.4 [re.alg.replace]
+ 28.12 [re.iter]
+ 28.12.1 [re.regiter]
+ 28.12.1.1 [re.regiter.cnstr]
+ 28.12.1.2 [re.regiter.comp]
+ 28.12.1.3 [re.regiter.deref]
+ 28.12.1.4 [re.regiter.incr]
+ 28.12.2 [re.tokiter]
+ 28.12.2.1 [re.tokiter.cnstr]
+ 28.12.2.2 [re.tokiter.comp]
+ 28.12.2.3 [re.tokiter.deref]
+ 28.12.2.4 [re.tokiter.incr]
+ 28.13 [re.grammar]
+29 [atomics]
+ 29.1 [atomics.order]
+ 29.2 [atomics.lockfree]
+ 29.3 [atomics.types]
+ 29.3.1 [atomics.types.integral]
+ 29.3.2 [atomics.types.address]
+ 29.3.3 [atomics.types.generic]
+ 29.4 [atomics.types.operations]
+ 29.5 [atomics.flag]
+ 29.6 [atomics.fences]
+30 [thread]
+ 30.1 [thread.req]
+ 30.1.1 [thread.req.paramname]
+ 30.1.2 [thread.req.exception]
+ 30.1.3 [thread.req.native]
+ 30.1.4 [thread.req.timing]
+ 30.2 [thread.threads]
+ 30.2.1 [thread.thread.class]
+ 30.2.1.1 [thread.thread.id]
+ 30.2.1.2 [thread.thread.constr]
+ 30.2.1.3 [thread.thread.destr]
+ 30.2.1.4 [thread.thread.assign]
+ 30.2.1.5 [thread.thread.member]
+ 30.2.1.6 [thread.thread.static]
+ 30.2.1.7 [thread.thread.algorithm]
+ 30.2.2 [thread.thread.this]
+ 30.3 [thread.mutex]
+ 30.3.1 [thread.mutex.requirements]
+ 30.3.1.1 [thread.mutex.class]
+ 30.3.1.2 [thread.mutex.recursive]
+ 30.3.2 [thread.timedmutex.requirements]
+ 30.3.2.1 [thread.timedmutex.class]
+ 30.3.2.2 [thread.timedmutex.recursive]
+ 30.3.3 [thread.lock]
+ 30.3.3.1 [thread.lock.guard]
+ 30.3.3.2 [thread.lock.unique]
+ 30.3.3.2.1 [thread.lock.unique.cons]
+ 30.3.3.2.2 [thread.lock.unique.locking]
+ 30.3.3.2.3 [thread.lock.unique.mod]
+ 30.3.3.2.4 [thread.lock.unique.obs]
+ 30.3.4 [thread.lock.algorithm]
+ 30.3.5 [thread.once]
+ 30.3.5.1 [thread.once.onceflag]
+ 30.3.5.2 [thread.once.callonce]
+ 30.4 [thread.condition]
+ 30.4.1 [thread.condition.condvar]
+ 30.4.2 [thread.condition.condvarany]
+ 30.5 [futures]
+ 30.5.1 [futures.overview]
+ 30.5.2 [futures.errors]
+ 30.5.3 [futures.future_error]
+ 30.5.4 [futures.unique_future]
+ 30.5.5 [future.shared_future]
+ 30.5.6 [futures.promise]
+ 30.5.7 [futures.allocators]
+ 30.5.8 [futures.task]
+X [datetime]
+ X [datetime.req]
+ X [datetime.syn]
+ X [datetime.duration]
+ X [datetime.nanoseconds]
+ X [datetime.microseconds]
+ X [datetime.milliseconds]
+ X [datetime.seconds]
+ X [datetime.minutes]
+ X [datetime.hours]
+ X [datetime.system]
+ X [datetime.nonmembers]
+A [gram]
+ A.1 [gram.key]
+ A.2 [gram.lex]
+ A.3 [gram.basic]
+ A.4 [gram.expr]
+ A.5 [gram.stmt]
+ A.6 [gram.dcl]
+ A.7 [gram.decl]
+ A.8 [gram.class]
+ A.9 [gram.derived]
+ A.10 [gram.special]
+ A.11 [gram.over]
+ A.12 [gram.temp]
+ A.13 [gram.except]
+ A.14 [gram.cpp]
+B [implimits]
+C [diff]
+ C.1 [diff.iso]
+ C.1.1 [diff.lex]
+ C.1.2 [diff.basic]
+ C.1.3 [diff.expr]
+ C.1.4 [diff.stat]
+ C.1.5 [diff.dcl]
+ C.1.6 [diff.decl]
+ C.1.7 [diff.class]
+ C.1.8 [diff.special]
+ C.1.9 [diff.cpp]
+ C.2 [diff.library]
+ C.2.1 [diff.mods.to.headers]
+ C.2.2 [diff.mods.to.definitions]
+ C.2.2.1 [diff.char16]
+ C.2.2.2 [diff.wchar.t]
+ C.2.2.3 [diff.header.iso646.h]
+ C.2.2.4 [diff.null]
+ C.2.3 [diff.mods.to.declarations]
+ C.2.4 [diff.mods.to.behavior]
+ C.2.4.1 [diff.offsetof]
+ C.2.4.2 [diff.malloc]
+D [depr]
+ D.1 [depr.incr.bool]
+ D.2 [depr.static]
+ D.3 [depr.access.dcl]
+ D.4 [depr.string]
+ D.5 [depr.c.headers]
+ D.6 [depr.ios.members]
+ D.7 [depr.str.strstreams]
+ D.7.1 [depr.strstreambuf]
+ D.7.1.1 [depr.strstreambuf.cons]
+ D.7.1.2 [depr.strstreambuf.members]
+ D.7.1.3 [depr.strstreambuf.virtuals]
+ D.7.2 [depr.istrstream]
+ D.7.2.1 [depr.istrstream.cons]
+ D.7.2.2 [depr.istrstream.members]
+ D.7.3 [depr.ostrstream]
+ D.7.3.1 [depr.ostrstream.cons]
+ D.7.3.2 [depr.ostrstream.members]
+ D.7.4 [depr.strstream]
+ D.7.4.1 [depr.strstream.cons]
+ D.7.4.2 [depr.strstream.dest]
+ D.7.4.3 [depr.strstream.oper]
+ D.8 [depr.lib.binders]
+ D.8.1 [depr.lib.binder.1st]
+ D.8.2 [depr.lib.bind.1st]
+ D.8.3 [depr.lib.binder.2nd]
+ D.8.4 [depr.lib.bind.2nd]
+ D.9 [depr.auto.ptr]
+ D.9.1 [auto.ptr]
+ D.9.1.1 [auto.ptr.cons]
+ D.9.1.2 [auto.ptr.members]
+ D.9.1.3 [auto.ptr.conv]
+ D.10 [depr.lib.iterator.primitives]
+ D.10.1 [iterator.traits]
+ D.10.2 [iterator.basic]
+ D.10.3 [std.iterator.tags]
+ D.10.4 [iterator.backward]
+E [xref]
+X [garbage.collection]
+
+TR1 1 [tr.intro]
+ TR1 1.1 [tr.description]
+ TR1 1.2 [tr.intro.ext]
+ TR1 1.3 [tr.intro.namespaces]
+TR1 2 [tr.util]
+ TR1 2.1 [tr.util.refwrap]
+ TR1 2.1.1 [tr.util.refwrp.synopsis]
+ TR1 2.1.2 [tr.util.refwrp.refwrp]
+ TR1 2.1.2.1 [tr.util.refwrp.const]
+ TR1 2.1.2.2 [tr.util.refwrp.assign]
+ TR1 2.1.2.3 [tr.util.refwrp.access]
+ TR1 2.1.2.4 [tr.util.refwrp.invoke]
+ TR1 2.1.2.5 [tr.util.refwrp.helpers]
+ TR1 2.2 [tr.util.smartptr]
+ TR1 2.2.1 [tr.util.smartptr.synopsis]
+ TR1 2.2.2 [tr.util.smartptr.weakptr]
+ TR1 2.2.3 [tr.util.smartptr.shared]
+ TR1 2.2.3.1 [tr.util.smartptr.shared.const]
+ TR1 2.2.3.2 [tr.util.smartptr.shared.dest]
+ TR1 2.2.3.3 [tr.util.smartptr.shared.assign]
+ TR1 2.2.3.4 [tr.util.smartptr.shared.mod]
+ TR1 2.2.3.5 [tr.util.smartptr.shared.obs]
+ TR1 2.2.3.6 [tr.util.smartptr.shared.cmp]
+ TR1 2.2.3.7 [tr.util.smartptr.shared.io]
+ TR1 2.2.3.8 [tr.util.smartptr.shared.spec]
+ TR1 2.2.3.9 [tr.util.smartptr.shared.cast]
+ TR1 2.2.3.10 [tr.util.smartptr.getdeleter]
+ TR1 2.2.4 [tr.util.smartptr.weak]
+ TR1 2.2.4.1 [tr.util.smartptr.weak.const]
+ TR1 2.2.4.2 [tr.util.smartptr.weak.dest]
+ TR1 2.2.4.3 [tr.util.smartptr.weak.assign]
+ TR1 2.2.4.4 [tr.util.smartptr.weak.mod]
+ TR1 2.2.4.5 [tr.util.smartptr.weak.obs]
+ TR1 2.2.4.6 [tr.util.smartptr.weak.cmp]
+ TR1 2.2.4.7 [tr.util.smartptr.weak.spec]
+ TR1 2.2.5 [tr.util.smartptr.enab]
+TR1 3 [tr.func]
+ TR1 3.1 [tr.func.def]
+ TR1 3.2 [tr.func.syn]
+ TR1 3.3 [tr.func.require]
+ TR1 3.4 [tr.func.ret]
+ TR1 3.5 [tr.func.memfn]
+ TR1 3.6 [tr.func.bind]
+ TR1 3.6.1 [tr.func.bind.isbind]
+ TR1 3.6.2 [tr.func.bind.isplace]
+ TR1 3.6.3 [tr.func.bind.bind]
+ TR1 3.6.4 [tr.func.bind.place]
+ TR1 3.7 [tr.func.wrap]
+ TR1 3.7.1 [tr.func.wrap.badcall]
+ TR1 3.7.1.1 [tr.func.wrap.badcall.const]
+ TR1 3.7.2 [tr.func.wrap.func]
+ TR1 3.7.2.1 [tr.func.wrap.func.con]
+ TR1 3.7.2.2 [tr.func.wrap.func.mod]
+ TR1 3.7.2.3 [tr.func.wrap.func.cap]
+ TR1 3.7.2.4 [tr.func.wrap.func.inv]
+ TR1 3.7.2.5 [tr.func.wrap.func.targ]
+ TR1 3.7.2.6 [tr.func.wrap.func.undef]
+ TR1 3.7.2.7 [tr.func.wrap.func.nullptr]
+ TR1 3.7.2.8 [tr.func.wrap.func.alg]
+TR1 4 [tr.meta]
+ TR1 4.1 [tr.meta.rqmts]
+ TR1 4.2 [tr.meta.type.synop]
+ TR1 4.3 [tr.meta.help]
+ TR1 4.4 [tr.meta.requirements]
+ TR1 4.5 [tr.meta.unary]
+ TR1 4.5.1 [tr.meta.unary.cat]
+ TR1 4.5.2 [tr.meta.unary.comp]
+ TR1 4.5.3 [tr.meta.unary.prop]
+ TR1 4.6 [tr.meta.rel]
+ TR1 4.7 [tr.meta.trans]
+ TR1 4.7.1 [tr.meta.trans.cv]
+ TR1 4.7.2 [tr.meta.trans.ref]
+ TR1 4.7.3 [tr.meta.trans.arr]
+ TR1 4.7.4 [tr.meta.trans.ptr]
+ TR1 4.8 [tr.meta.trans.other]
+ TR1 4.9 [tr.meta.req]
+TR1 5 [tr.num]
+ TR1 5.1 [tr.rand]
+ TR1 5.1.1 [tr.rand.req]
+ TR1 5.1.2 [tr.rand.synopsis]
+ TR1 5.1.3 [tr.rand.var]
+ TR1 5.1.4 [tr.rand.eng]
+ TR1 5.1.4.1 [tr.rand.eng.lcong]
+ TR1 5.1.4.2 [tr.rand.eng.mers]
+ TR1 5.1.4.3 [tr.rand.eng.sub]
+ TR1 5.1.4.4 [tr.rand.eng.sub1]
+ TR1 5.1.4.5 [tr.rand.eng.disc]
+ TR1 5.1.4.6 [tr.rand.eng.xor]
+ TR1 5.1.5 [tr.rand.predef]
+ TR1 5.1.6 [tr.rand.device]
+ TR1 5.1.7 [tr.rand.dist]
+ TR1 5.1.7.1 [tr.rand.dist.iunif]
+ TR1 5.1.7.2 [tr.rand.dist.bern]
+ TR1 5.1.7.3 [tr.rand.dist.geom]
+ TR1 5.1.7.4 [tr.rand.dist.pois]
+ TR1 5.1.7.5 [tr.rand.dist.bin]
+ TR1 5.1.7.6 [tr.rand.dist.runif]
+ TR1 5.1.7.7 [tr.rand.dist.exp]
+ TR1 5.1.7.8 [tr.rand.dist.norm]
+ TR1 5.1.7.9 [tr.rand.dist.gamma]
+ TR1 5.2 [tr.num.sf]
+ TR1 5.2.1 [tr.num.sf.cmath]
+ TR1 5.2.1.1 [tr.num.sf.Lnm]
+ TR1 5.2.1.2 [tr.num.sf.Plm]
+ TR1 5.2.1.3 [tr.num.sf.beta]
+ TR1 5.2.1.4 [tr.num.sf.ellK]
+ TR1 5.2.1.5 [tr.num.sf.ellEx]
+ TR1 5.2.1.6 [tr.num.sf.ellPx]
+ TR1 5.2.1.7 [tr.num.sf.conhyp]
+ TR1 5.2.1.8 [tr.num.sf.I]
+ TR1 5.2.1.9 [tr.num.sf.J]
+ TR1 5.2.1.10 [tr.num.sf.K]
+ TR1 5.2.1.11 [tr.num.sf.N]
+ TR1 5.2.1.12 [tr.num.sf.ellF]
+ TR1 5.2.1.13 [tr.num.sf.ellE]
+ TR1 5.2.1.14 [tr.num.sf.ellP]
+ TR1 5.2.1.15 [tr.num.sf.ei]
+ TR1 5.2.1.16 [tr.num.sf.Hn]
+ TR1 5.2.1.17 [tr.num.sf.hyper]
+ TR1 5.2.1.18 [tr.num.sf.Ln]
+ TR1 5.2.1.19 [tr.num.sf.Pl]
+ TR1 5.2.1.20 [tr.num.sf.riemannzeta]
+ TR1 5.2.1.21 [tr.num.sf.j]
+ TR1 5.2.1.22 [tr.num.sf.Ylm]
+ TR1 5.2.1.23 [tr.num.sf.n]
+ TR1 5.2.2 [tr.num.sf.mathh]
+TR1 6 [tr.cont]
+ TR1 6.1 [tr.tuple]
+ TR1 6.1.1 [tr.tuple.synopsis]
+ TR1 6.1.2 [tr.tuple.synopsis.pair]
+ TR1 6.1.3 [tr.tuple.tuple]
+ TR1 6.1.3.1 [tr.tuple.cnstr]
+ TR1 6.1.3.2 [tr.tuple.creation]
+ TR1 6.1.3.3 [tr.tuple.helper]
+ TR1 6.1.3.4 [tr.tuple.elem]
+ TR1 6.1.3.5 [tr.tuple.rel]
+ TR1 6.1.4 [tr.tuple.pairs]
+ TR1 6.2 [tr.array]
+ TR1 6.2.1 [tr.array.syn]
+ TR1 6.2.2 [tr.array.array]
+ TR1 6.2.2.1 [tr.array.cons]
+ TR1 6.2.2.2 [tr.array.special]
+ TR1 6.2.2.3 [tr.array.size]
+ TR1 6.2.2.4 [tr.array.zero]
+ TR1 6.2.2.5 [tr.array.tuple]
+ TR1 6.3 [tr.hash]
+ TR1 6.3.1 [tr.unord.req]
+ TR1 6.3.1.1 [tr.unord.req.except]
+ TR1 6.3.2 [tr.unord.fun.syn]
+ TR1 6.3.3 [tr.unord.hash]
+ TR1 6.3.4 [tr.unord.unord]
+ TR1 6.3.4.1 [tr.unord.syn.set]
+ TR1 6.3.4.2 [tr.unord.syn.map]
+ TR1 6.3.4.3 [tr.unord.set]
+ TR1 6.3.4.3.1 [tr.unord.set.cnstr]
+ TR1 6.3.4.3.2 [tr.unord.set.swap]
+ TR1 6.3.4.4 [tr.unord.map]
+ TR1 6.3.4.4.1 [tr.unord.map.cnstr]
+ TR1 6.3.4.4.2 [tr.unord.map.elem]
+ TR1 6.3.4.4.3 [tr.unord.map.swap]
+ TR1 6.3.4.5 [tr.unord.multiset]
+ TR1 6.3.4.5.1 [tr.unord.multiset.cnstr]
+ TR1 6.3.4.5.2 [tr.unord.multiset.swap]
+ TR1 6.3.4.6 [tr.unord.multimap]
+ TR1 6.3.4.6.1 [tr.unord.multimap.cnstr]
+ TR1 6.3.4.6.2 [tr.unord.multimap.swap]
+TR1 7 [tr.re]
+ TR1 7.1 [tr.re.def]
+ TR1 7.2 [tr.re.req]
+ TR1 7.3 [tr.re.sum]
+ TR1 7.4 [tr.re.syn]
+ TR1 7.5 [tr.re.const]
+ TR1 7.5.1 [tr.re.synopt]
+ TR1 7.5.2 [tr.re.matchflag]
+ TR1 7.5.3 [tr.re.err]
+ TR1 7.6 [tr.re.badexp]
+ TR1 7.7 [tr.re.traits]
+ TR1 7.8 [tr.re.regex]
+ TR1 7.8.1 [tr.re.regex.const]
+ TR1 7.8.2 [tr.re.regex.construct]
+ TR1 7.8.3 [tr.re.regex.assign]
+ TR1 7.8.4 [tr.re.regex.operations]
+ TR1 7.8.5 [tr.re.regex.locale]
+ TR1 7.8.6 [tr.re.regex.swap]
+ TR1 7.8.7 [tr.re.regex.nonmemb]
+ TR1 7.8.7.1 [tr.re.regex.nmswap.]
+ TR1 7.9 [tr.re.submatch]
+ TR1 7.9.1 [tr.re.submatch.members]
+ TR1 7.9.2 [tr.re.submatch.op]
+ TR1 7.10 [tr.re.results]
+ TR1 7.10.1 [tr.re.results.const]
+ TR1 7.10.2 [tr.re.results.size]
+ TR1 7.10.3 [tr.re.results.acc]
+ TR1 7.10.4 [tr.re.results.form]
+ TR1 7.10.5 [tr.re.results.all]
+ TR1 7.10.1 [tr.re.results.swap]
+ TR1 7.11 [tr.re.alg]
+ TR1 7.11.1 [tr.re.except]
+ TR1 7.11.2 [tr.re.alg.match]
+ TR1 7.11.3 [tr.re.alg.search]
+ TR1 7.11.4 [tr.re.alg.replace]
+ TR1 7.12 [tr.re.iter]
+ TR1 7.12.1 [tr.re.regiter]
+ TR1 7.12.1.1 [tr.re.regiter.cnstr]
+ TR1 7.12.1.2 [tr.re.regiter.comp]
+ TR1 7.12.1.3 [tr.re.regiter.deref]
+ TR1 7.12.1.4 [tr.re.regiter.incr]
+ TR1 7.12.2 [tr.re.tokiter]
+ TR1 7.12.2.1 [tr.re.tokiter.cnstr]
+ TR1 7.12.2.2 [tr.re.tokiter.comp]
+ TR1 7.12.2.3 [tr.re.tokiter.deref]
+ TR1 7.12.2.4 [tr.re.tokiter.incr]
+ TR1 7.13 [tr.re.grammar]
+TR1 8 [tr.c99]
+ TR1 8.1 [tr.c99.cmplx]
+ TR1 8.1.1 [tr.c99.cmplx.syn]
+ TR1 8.1.2 [tr.c99.cmplx.acos]
+ TR1 8.1.3 [tr.c99.cmplx.asin]
+ TR1 8.1.4 [tr.c99.cmplx.atan]
+ TR1 8.1.5 [tr.c99.cmplx.acosh]
+ TR1 8.1.6 [tr.c99.cmplx.asinh]
+ TR1 8.1.7 [tr.c99.cmplx.atanh]
+ TR1 8.1.8 [tr.c99.cmplx.fabs]
+ TR1 8.1.9 [tr.c99.cmplx.over]
+ TR1 8.2 [tr.c99.ccmplx]
+ TR1 8.3 [tr.c99.cmplxh]
+ TR1 8.4 [tr.c99.cctype]
+ TR1 8.4.1 [tr.c99.cctype.syn]
+ TR1 8.4.2 [tr.c99.cctype.blank]
+ TR1 8.5 [tr.c99.ctypeh]
+ TR1 8.6 [tr.c99.cfenv]
+ TR1 8.6.1 [tr.c99.cfenv.syn]
+ TR1 8.6.2 [tr.c99.cfenv.def]
+ TR1 8.7 [tr.c99.fenv]
+ TR1 8.8 [tr.c99.cfloat]
+ TR1 8.9 [tr.c99.floath]
+ TR1 8.10 [tr.c99.ios]
+ TR1 8.10.1 [tr.c99.ios.syn]
+ TR1 8.10.2 [tr.c99.ios.hex]
+ TR1 8.11 [tr.c99.cinttypes]
+ TR1 8.11.1 [tr.c99.cinttypes.syn]
+ TR1 8.11.2 [tr.c99.cinttypes.def]
+ TR1 8.12 [tr.c99.inttypesh]
+ TR1 8.13 [tr.c99.climits]
+ TR1 8.14 [tr.c99.limitsh]
+ TR1 8.15 [tr.c99.locale]
+ TR1 8.16 [tr.c99.cmath]
+ TR1 8.16.1 [tr.c99.cmath.syn]
+ TR1 8.16.2 [tr.c99.cmath.def]
+ TR1 8.16.3 [tr.c99.cmath.tmpl]
+ TR1 8.16.4 [tr.c99.cmath.over]
+ TR1 8.17 [tr.c99.mathh]
+ TR1 8.18 [tr.c99.cstdarg]
+ TR1 8.19 [tr.c99.stdargh]
+ TR1 8.20 [tr.c99.cbool]
+ TR1 8.21 [tr.c99.boolh]
+ TR1 8.22 [tr.c99.cstdint]
+ TR1 8.22.1 [tr.c99.cstdint.syn]
+ TR1 8.22.2 [tr.c99.cstdint.def]
+ TR1 8.23 [tr.c99.stdinth]
+ TR1 8.24 [tr.c99.cstdio]
+ TR1 8.24.1 [tr.c99.cstdio.syn]
+ TR1 8.24.2 [tr.c99.cstdio.def]
+ TR1 8.24.3 [tr.c99.cstdio.spec]
+ TR1 8.24.4 [tr.c99.stdioh]
+ TR1 8.25 [tr.c99.cstdlib]
+ TR1 8.25.1 [tr.c99.cstdlib.syn]
+ TR1 8.25.2 [tr.c99.cstdlib.def]
+ TR1 8.25.3 [tr.c99.cstdlib.abs]
+ TR1 8.25.4 [tr.c99.cstdlib.div]
+ TR1 8.26 [tr.c99.stdlibh]
+ TR1 8.27 [tr.c99.ctgmath]
+ TR1 8.28 [tr.c99.tgmathh]
+ TR1 8.29 [tr.c99.ctime]
+ TR1 8.30 [tr.c99.cwchar]
+ TR1 8.30.1 [tr.c99.cwchar.syn]
+ TR1 8.30.2 [tr.c99.cwchar.def]
+ TR1 8.30.3 [tr.c99.cwchar.spec]
+ TR1 8.31 [tr.c99.wcharh]
+ TR1 8.32 [tr.c99.cwctype]
+ TR1 8.32.1 [tr.c99.cwctype.syn]
+ TR1 8.32.2 [tr.c99.cwctype.iswblank]
+ TR1 8.33 [tr.c99.wctypeh]
+TR1 A [tr.limits]
+
+TRDecimal 1 [trdec.intro]
+ TRDecimal 1.1 [trdec.model]
+ TRDecimal 1.2 [trdec.encodings]
+ TRDecimal 1.3 [trdec.refs]
+TRDecimal 2 [trdec.conventions]
+ TRDecimal 2.1 [trdec.relation.intro]
+ TRDecimal 2.2 [trdec.relation.tr1]
+ TRDecimal 2.3 [trdec.categories]
+ TRDecimal 2.4 [trdec.namespace]
+TRDecimal 3 [trdec.types]
+ TRDecimal 3.1 [trdec.types.encodings]
+ TRDecimal 3.2 [trdec.types.types]
+ TRDecimal 3.2.1 [trdec.types.types.synopsis]
+ TRDecimal 3.2.2 [trdec.types.types.decimal32]
+ TRDecimal 3.2.2.1 [trdec.types.types.decimal32.cons]
+ TRDecimal 3.2.2.2 [trdec.types.types.decimal32.conv.float]
+ TRDecimal 3.2.2.3 [trdec.types.types.decimal32.conv.from.int]
+ TRDecimal 3.2.2.4 [trdec.types.types.decimal32.conv.to.int]
+ TRDecimal 3.2.2.5 [trdec.types.types.decimal32.incr]
+ TRDecimal 3.2.2.6 [trdec.types.types.decimal32.comp.ass]
+ TRDecimal 3.2.3 [trdec.types.types.decimal64]
+ TRDecimal 3.2.3.1 [trdec.types.types.decimal64.cons]
+ TRDecimal 3.2.3.2 [trdec.types.types.decimal64.float]
+ TRDecimal 3.2.3.3 [trdec.types.types.decimal64.from.int]
+ TRDecimal 3.2.3.4 [trdec.types.types.decimal64.to.int]
+ TRDecimal 3.2.3.5 [trdec.types.types.decimal64.incr]
+ TRDecimal 3.2.3.6 [trdec.types.types.decimal64.comp.ass]
+ TRDecimal 3.2.4 [trdec.types.types.decimal128]
+ TRDecimal 3.2.4.1 [trdec.types.types.decimal128.cons]
+ TRDecimal 3.2.4.2 [trdec.types.types.decimal128.float]
+ TRDecimal 3.2.4.3 [trdec.types.types.decimal128.from.int]
+ TRDecimal 3.2.4.4 [trdec.types.types.decimal128.to.int]
+ TRDecimal 3.2.4.5 [trdec.types.types.decimal128.incr]
+ TRDecimal 3.2.4.6 [trdec.types.types.decimal128.comp.ass]
+ TRDecimal 3.2.5 [trdec.types.types.init]
+ TRDecimal 3.2.6 [trdec.types.types.conv.float]
+ TRDecimal 3.2.7 [trdec.types.types.unary]
+ TRDecimal 3.2.8 [trdec.types.types.binary]
+ TRDecimal 3.2.9 [trdec.types.types.comp]
+ TRDecimal 3.2.10 [trdec.types.types.input]
+ TRDecimal 3.2.11 [trdec.types.types.output]
+ TRDecimal 3.3 [trdec.types.limits]
+ TRDecimal 3.4 [trdec.types.cdecfloat]
+ TRDecimal 3.4.1 [trdec.types.cdecfloat.synopsis]
+ TRDecimal 3.4.2 [trdec.types.decfloat.h.synopsis]
+ TRDecimal 3.4.3 [trdec.types.cdecfloat.max.value]
+ TRDecimal 3.4.4 [trdec.types.cdecfloat.epsilon]
+ TRDecimal 3.4.5 [trdec.types.cdecfloat.min.normal.value]
+ TRDecimal 3.4.6 [trdec.types.cdecfloat.min.subnormal.value]
+ TRDecimal 3.4.7 [trdec.types.cdecfloat.eval.format]
+ TRDecimal 3.5 [trdec.types.cfenv]
+ TRDecimal 3.5.1 [trdec.types.cfenv.synopsis]
+ TRDecimal 3.5.2 [trdec.types.cfenv.round]
+ TRDecimal 3.5.3 [trdec.types.cfenv.fe_dec_getround]
+ TRDecimal 3.5.4 [trdec.types.cfenv.fe_dec_setround]
+ TRDecimal 3.5.5 [trdec.types.cfenv.fenv.h]
+ TRDecimal 3.6 [trdec.types.cmath]
+ TRDecimal 3.6.1 [trdec.types.cmath.synopsis]
+ TRDecimal 3.6.2 [trdec.types.cmath.macros]
+ TRDecimal 3.6.3 [trdec.types.cmath.eval.format]
+ TRDecimal 3.6.4 [trdec.types.cmath.samequantum]
+ TRDecimal 3.6.5 [trdec.types.cmath.quantize]
+ TRDecimal 3.6.6 [trdec.types.cmath.elementary]
+ TRDecimal 3.6.6.1 [trdec.types.cmath.elementary.abs]
+ TRDecimal 3.6.7 [trdec.types.cmath.math.h]
+ TRDecimal 3.6.7.1 [trdec.types.cmath.math.h.synopsis]
+ TRDecimal 3.7 [trdec.types.cstdio]
+ TRDecimal 3.8 [trdec.types.cstdlib]
+ TRDecimal 3.8.1 [trdec.types.cstdlib.synopsis]
+ TRDecimal 3.8.2 [trdec.types.cstdlib.strtod]
+ TRDecimal 3.8.3 [trdec.types.cstdlib.stdlib.h]
+ TRDecimal 3.9 [trdec.types.cwchar]
+ TRDecimal 3.9.1 [trdec.types.cwchar.synopsis]
+ TRDecimal 3.9.2 [trdec.types.cwchar.wcstod]
+ TRDecimal 3.9.3 [trdec.types.cwchar.wchar.h]
+ TRDecimal 3.10 [trdec.types.facets]
+ TRDecimal 3.10.1 [trdec.types.facets.locale]
+ TRDecimal 3.10.2 [trdec.types.facets.extended_num_get]
+ TRDecimal 3.10.2.1 [trdec.types.facets.extended_num_get.mem]
+ TRDecimal 3.10.2.2 [trdec.types.facets.extended_num_get.virt]
+ TRDecimal 3.10.3 [trdec.types.facets.extended_num_put]
+ TRDecimal 3.10.3.1 [trdec.types.facets.extended_num_put.mem]
+ TRDecimal 3.10.3.2 [trdec.types.facets.extended_num_put.virt]
+ TRDecimal 3.11 [trdec.types.traits]
+ TRDecimal 3.11.1 [trdec.types.traits.synopsis]
+ TRDecimal 3.11.2 [trdec.types.traits.is_decimal_floating_point]
+ TRDecimal 3.12 [trdec.types.hash]
+ TRDecimal 3.12.1 [trdec.types.hash.synopsis]
+ TRDecimal 3.12.2 [trdec.types.hash.spec]
+TRDecimal 4 [trdec.compat]
+ TRDecimal 4.1 [trdec.compat.decfloat.h]
+ TRDecimal 4.2 [trdec.compat.literals]
+ TRDecimal 4.3 [trdec.compat.conv]
diff --git a/test/make_test_dirs.pl b/test/make_test_dirs.pl
new file mode 100755
index 000000000000..3a524d2adb1b
--- /dev/null
+++ b/test/make_test_dirs.pl
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -w
+#
+# Simple little Perl script that takes the cxx-sections.data file as
+# input and generates a directory structure that mimics the standard's
+# structure.
+use English;
+
+$current_indent_level = -4;
+while ($line = <STDIN>) {
+ $line =~ /^\s*/;
+ $next_indent_level = length($MATCH);
+ if ($line =~ /\[([^\]]*)\]/) {
+ my $section = $1;
+ while ($next_indent_level < $current_indent_level) {
+ chdir("..");
+ $current_indent_level -= 4;
+ }
+
+ if ($next_indent_level == $current_indent_level) {
+ chdir("..");
+ } else {
+ $current_indent_level = $next_indent_level;
+ }
+ mkdir($section);
+ chdir($section);
+ }
+}
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index c58340c3eee7..840f0157cf98 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -2002,9 +2002,10 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
PP.getTargetInfo(),
PP.getIdentifierTable(),
PP.getSelectorTable(),
+ PP.getBuiltinInfo(),
/* FreeMemory = */ !DisableFree,
- /* size_reserve = */0,
- /* InitializeBuiltins = */ImplicitIncludePCH.empty()));
+ /* size_reserve = */0));
+
llvm::OwningPtr<PCHReader> Reader;
llvm::OwningPtr<ExternalASTSource> Source;
@@ -2298,9 +2299,15 @@ int main(int argc, char **argv) {
PhonyDependencyTarget);
}
- if (ImplicitIncludePCH.empty() &&
- InitializeSourceManager(*PP.get(), InFile))
- continue;
+ if (ImplicitIncludePCH.empty()) {
+ if (InitializeSourceManager(*PP.get(), InFile))
+ continue;
+
+ // Initialize builtin info.
+ PP->getBuiltinInfo().InitializeBuiltins(PP->getIdentifierTable(),
+ PP->getTargetInfo(),
+ PP->getLangOptions().NoBuiltin);
+ }
if (!HTMLDiag.empty())
((PathDiagnosticClient*)DiagClient.get())->SetPreprocessor(PP.get());
diff --git a/www/OpenProjects.html b/www/OpenProjects.html
index 69b398457fb1..4ed6614e360e 100644
--- a/www/OpenProjects.html
+++ b/www/OpenProjects.html
@@ -24,15 +24,9 @@ verify that one of these isn't already completed. :)</p>
<li><b>Compile your favorite C/ObjC project with Clang</b>:
Clang's type-checking and code generation is very close to complete (but not bug free!) for C and Objective-C. We appreciate all reports of code that is
rejected or miscompiled by the front-end. If you notice invalid code that is not rejected, or poor diagnostics when code is rejected, that is also very important to us. For make-based projects,
-the <a href="get_started.html#ccc"><code>ccc</code></a> driver works as a drop-in replacement for GCC.</li>
+the <a href="get_started.html#driver"><code>clang</code></a> driver works as a drop-in replacement for GCC.</li>
-<li><b>Overflow detection</b>: an interesting project would be to add a -ftrapv
-compilation mode that causes -emit-llvm to generate overflow tests for all
-signed integer arithmetic operators, and call abort if they overflow. Overflow
-is undefined in C and hard for people to reason about. LLVM IR also has
-intrinsics for generating arithmetic with overflow checks directly.</li>
-
-<li><b>Undefined behavior checking</b>: similar to adding -ftrapv, codegen could
+<li><b>Undefined behavior checking</b>: CodeGen could
insert runtime checks for all sorts of different undefined behaviors, from
reading uninitialized variables, buffer overflows, and many other things. This
checking would be expensive, but the optimizers could eliminate many of the
@@ -58,7 +52,7 @@ Clang is built as a set of libraries, which means that it is possible to
implement capabilities similar to other source language tools, improving them
in various ways. Two examples are <a href="http://distcc.samba.org/">distcc</a>
and the <a href="http://delta.tigris.org/">delta testcase reduction tool</a>.
-The former can be improved to scale better and be more efficient. The later
+The former can be improved to scale better and be more efficient. The latter
could also be faster and more efficient at reducing C-family programs if built
on the clang preprocessor.</li>
@@ -86,14 +80,11 @@ improve the quality of clang by self-testing. Some examples:
<li><b>Continue work on C++ support</b>: Implementing all of C++ is a very big
job, but there are lots of little pieces that can be picked off and implemented. Here are some small- to mid-sized C++ implementation projects:
<ul>
- <li>Using declarations: These are completely unsupported at the moment.</li>
- <li>Type-checking for the conditional operator (? :): this currently follows C semantics, not C++ semantics.</li>
<li>Type-checking for explicit conversions: currently follows C semantics, not C++ semantics.</li>
- <li>Type-checking for copy assignment: Clang parses overloaded copy-assignment operators, but they aren't used as part of assignment syntax ("a = b").</li>
<li>Qualified member references: C++ supports qualified member references such as <code>x-&gt;Base::foo</code>, but Clang has no parsing or semantic analysis for them.</li>
- <li>Virtual functions: Clang parses <code>virtual</code> and attaches it to the AST. However, it does not determine whether a given function overrides a virtual function in a base class.</li>
<li>Implicit definitions of special member functions: Clang implicitly declares the various special member functions (default constructor, copy constructor, copy assignment operator, destructor) when necessary, but is not yet able to provide definitions for these functions.</li>
<li>Parsing and AST representations of friend classes and functions</li>
+ <li>Explicit calls to destructors and pseudo-destructor expressions (<code>x.~X()</code>).</li>
<li>AST representation for implicit C++ conversions: implicit conversions that involve non-trivial operations (e.g., invoking a user-defined conversion function, performing a base-to-derived or derived-to-base conversion) need explicit representation in Clang's AST.</li>
<li>Improved diagnostics for overload resolution failures: after an overload resolution failure, we currently print out the overload resolution candidates. We should also print out the reason that each candidate failed, e.g., "too few arguments", "too many arguments", "cannot initialize parameter with an lvalue of type 'foo'", etc.</li>
</ul>
diff --git a/www/StaticAnalysis.html b/www/StaticAnalysis.html
index 81176a96acf4..a701c0ff067c 100644
--- a/www/StaticAnalysis.html
+++ b/www/StaticAnalysis.html
@@ -2,6 +2,7 @@
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
+ <meta HTTP-EQUIV="REFRESH" content="0; url=http://clang-analyzer.llvm.org">
<title>LLVM/Clang Static Analyzer</title>
<link type="text/css" rel="stylesheet" href="menu.css" />
<link type="text/css" rel="stylesheet" href="content.css" />
@@ -12,143 +13,7 @@
<div id="content">
-<h1>LLVM/Clang Static Analyzer</h1>
-
-<p>The LLVM/Clang static analyzer is a standalone tool that finds bugs in C and
-Objective-C programs. Currently the analyzer is invoked as a command-line tool.
-It is intended to run in tandem with a build of a project or code base.</p>
-
-<p>Here are some important points we ask you to consider when using the static
-analyzer:</p>
-
-<ul>
-
-<li><b>This tool is <b>very early</b> in development.</b> There are many planned
-enhancements to improve both the precision and scope of its analysis algorithms
-as well as the kinds bugs it will find.</li>
-
-<li><b>Static analysis can be much slower than compilation.</b> While the
-analyzer is being designed to be as fast and light-weight as possible, please do
-not expect it to be as fast as compiling a program (even with optimizations
-enabled). Some of the algorithms needed to find bugs require in the worst case
-exponential time. The analyzer runs in a reasonable amount of time by both
-bounding the amount of checking work it will do as well as using clever
-algorithms to reduce the amount of work it must do to find bugs.</li>
-
-<li><b>False positives.</b> Static analysis is not perfect. It can falsely flag
-bugs in a program where the code behaves correctly. Because some code checks
-require more analysis precision than others, the frequency of false positives
-can vary widely between different checks. Our eventual goal is to have the
-analyzer have a low false positive rate for most code on all checks.</li>
-</ul>
-
-<h3>Please tell us about False Positives</h3>
-
-<p>If you encounter a false positive, <b>please let us know</b> by <a
-href="StaticAnalysisUsage.html#filingbugs">filing a bug report</a>. False
-positives cannot be addressed unless we know about them.</p>
-
-<h3>Want more bugs?</h3>
-
-<p>If there are specific kinds of bugs you would like the tool to find,
-please feel free to file <a href="StaticAnalysisUsage.html#filingbugs">feature
-requests</a>.</p>
-
-<!-- Generated from: http://www.spiffycorners.com/index.php -->
-
-<style type="text/css">
-.spiffy{display:block}
-.spiffy *{
- display:block;
- height:1px;
- overflow:hidden;
- font-size:.01em;
- background:#EBF0FA}
-.spiffy1{
- margin-left:3px;
- margin-right:3px;
- padding-left:1px;
- padding-right:1px;
- border-left:1px solid #f6f8fc;
- border-right:1px solid #f6f8fc;
- background:#f0f3fb}
-.spiffy2{
- margin-left:1px;
- margin-right:1px;
- padding-right:1px;
- padding-left:1px;
- border-left:1px solid #fdfdfe;
- border-right:1px solid #fdfdfe;
- background:#eef2fa}
-.spiffy3{
- margin-left:1px;
- margin-right:1px;
- border-left:1px solid #eef2fa;
- border-right:1px solid #eef2fa;}
-.spiffy4{
- border-left:1px solid #f6f8fc;
- border-right:1px solid #f6f8fc}
-.spiffy5{
- border-left:1px solid #f0f3fb;
- border-right:1px solid #f0f3fb}
-.spiffyfg{
- background:#EBF0FA}
-
-.spiffyfg h2 {
- margin:0px; padding:10px;
-}
-</style>
-
-<style type="text/css">
- #left { float:left; }
- #left h2 { margin:1px; padding-top:0px; }
- #right { float:left; margin-left:50px; padding:0px ;}
- #right h2 { padding:0px; margin:0px; }
- #wrappedcontent { padding:15px;}
-</style>
-
-<div id="left">
- <h2>Using the Analyzer</h2>
- <ul>
- <li><a href="StaticAnalysisUsage.html#Obtaining">Obtaining the Analyzer</a></li>
- <li><a href="StaticAnalysisUsage.html#BasicUsage">Basic Usage</a></li>
- <li><a href="StaticAnalysisUsage.html#Output">Output of the Analyzer</a></li>
- <li><a href="StaticAnalysisUsage.html#RecommendedUsageGuidelines">Recommended Usage Guidelines</a></li>
- <li><a href="StaticAnalysisUsage.html#Debugging">Debugging the Analyzer</a></li>
- <li><a href="StaticAnalysisUsage.html#filingbugs">Filing Bugs and Feature Requests</a></li>
- </ul>
-</div>
-
-<div id="right">
- <b class="spiffy">
- <b class="spiffy1"><b></b></b>
- <b class="spiffy2"><b></b></b>
- <b class="spiffy3"></b>
- <b class="spiffy4"></b>
- <b class="spiffy5"></b></b>
-
- <div class="spiffyfg">
- <div id="wrappedcontent">
- <h2>Download</h2>
- <ul>
- <li>Mac OS X (Universal, 10.5+):
- <p>
- <!--#include virtual="latest_checker.html.incl"-->
- </p>
- </li>
- <li><a href="StaticAnalysisUsage.html#OtherUsage">Other Platforms</a> (Building from Source)</li>
- </div>
-
- </div>
-
- <b class="spiffy">
- <b class="spiffy5"></b>
- <b class="spiffy4"></b>
- <b class="spiffy3"></b>
- <b class="spiffy2"><b></b></b>
- <b class="spiffy1"><b></b></b></b>
-</div>
-
+<p>This page has moved: <a href="http://clang-analyzer.llvm.org">clang.analyzer.llvm.org</a>.</p>
</div>
</body>
diff --git a/www/StaticAnalysisUsage.html b/www/StaticAnalysisUsage.html
index daab89f724aa..a701c0ff067c 100644
--- a/www/StaticAnalysisUsage.html
+++ b/www/StaticAnalysisUsage.html
@@ -2,26 +2,10 @@
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
- <title>Information on using the Static Analyzer ("Clang Checker")</title>
+ <meta HTTP-EQUIV="REFRESH" content="0; url=http://clang-analyzer.llvm.org">
+ <title>LLVM/Clang Static Analyzer</title>
<link type="text/css" rel="stylesheet" href="menu.css" />
<link type="text/css" rel="stylesheet" href="content.css" />
- <style>
- thead {
- background-color:#eee; color:#666666;
- font-weight: bold; cursor: default;
- text-align:center;
- border-top: 2px solid #000000;
- border-bottom: 2px solid #000000;
- font-weight: bold; font-family: Verdana
- }
- table { border: 1px #000000 solid }
- table { border-collapse: collapse; border-spacing: 0px }
- table { margin-left:20px; margin-top:20px; margin-bottom:20px }
- td { border-bottom: 1px #000000 dotted }
- td { padding:5px; padding-left:8px; padding-right:8px }
- td { text-align:left; font-size:9pt }
- td.View { padding-left: 10px }
- </style>
</head>
<body>
@@ -29,244 +13,7 @@
<div id="content">
-<h1>Information on using the Static Analyzer</h1>
-
-<h2 id="Obtaining">Obtaining the Analyzer</h2>
-
-<p> Using the analyzer involves executing <tt>scan-build</tt> (see <a
-href="#BasicUsage">Basic Usage</a>). <tt>scan-build</tt> will first look for a
-<tt>clang</tt> executable in the same directory as <tt>scan-build</tt>, and then
-search your path.</p>
-
-<p>If one is using the analyzer directly from the Clang sources, it suffices to
-just directly execute <tt>scan-build</tt> in the <tt>utils</tt> directory. No
-other special installation is needed.</p>
-
-<h3>Packaged Builds (Mac OS X)</h3>
-
-<p>Semi-regular pre-built binaries of the analyzer are available on Mac OS X
-(10.5).</p>
-
-<p>The latest build is:
- <!--#include virtual="latest_checker.html.incl"-->
-</p>
-
-Packaged builds for other platforms may eventually be provided, but as the tool
-is in its early stages we are not actively promoting releases yet. If you wish
-to help contribute regular builds of the analyzer on other platforms, please
-email the <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev">Clang
-Developers' mailing list</a>.</p>
-
-<p>Packaged builds of the analyzer expand to the following files:</p>
-
-<table id="package">
-<thead><tr><td>File</td><td>Purpose</td></tr></thead>
-<tr><td><tt><b>scan-build</b></tt></td><td>Script for running the analyzer over a project build. <b>This is the only file you care about.</b></td></tr>
-<tr><td><tt>ccc-analyzer</tt></td><td>GCC interceptor (called by scan-build)</td></tr>
-<tr><td><tt>clang</tt></td><td>Static Analyzer (called by ccc-analyzer)</td><tr>
-<tr><td><tt>sorttable.js</tt></td><td>JavaScript used for displaying error reports</td></tr>
-</table>
-
-<h3 id="OtherPlatforms">Other Platforms (Building the Analyzer from Source)</h3>
-
-<p>Packaged builds simply consist of a few files from the Clang source tree,
-meaning that <b>anyone</b> who can build Clang can use the static analyzer.
-Please see the <a href="get_started.html">Getting Started</a> page for more
-details on downloading and compiling Clang.</p>
-
-<p>All files used by the analyzer (and included in packaged builds; <a
-href="#package">see above</a>) other than a compiled <tt>clang</tt> executable
-are found in the <tt>utils</tt> subdirectory in the Clang tree.</p>
-
-<h2 id="BasicUsage">Basic Usage</h2>
-
-<p>The analyzer is executed from the command-line. To run the analyzer, you will
-use <tt>scan-build</tt> to analyze the source files compiled by <tt>gcc</tt>
-during a project build.</p>
-
-<p>For example, to analyze the files compiled under a build:</p>
-
-<pre>
- $ <b>scan-build</b> make
- $ <b>scan-build</b> xcodebuild
-</pre>
-
-<p> In the first case <tt>scan-build</tt> analyzes the code of a project built
-with <tt>make</tt>, and in the second case <tt>scan-build</tt> analyzes a project
-built using <tt>xcodebuild</tt>. In general, the format is: </p>
-
-<pre>
- $ <b>scan-build</b> <i>[scan-build options]</i> <b>&lt;command&gt;</b> <i>[command options]</i>
-</pre>
-
-<p> Operationally, <tt>scan-build</tt> literally runs <command> with all of the
-subsequent options passed to it. For example:</p>
-
-<pre>
- $ scan-build make <b>-j4</b>
-</pre>
-
-<p>In this example, <tt>scan-build</tt> makes no effort to interpret the options
-after the build command (in this case, <tt>make</tt>); it just passes them
-through. In general, <tt>scan-build</tt> should support parallel builds, but
-<b>not distributed builds</b>. Similarly, you can use <tt>scan-build</tt> to
-analyze specific files:
-
-<pre>
- $ scan-build gcc -c <b>t1.c t2.c</b>
-</pre>
-
-<p>
-This example causes the files <tt>t1.c</tt> and <tt>t2.c</tt> to be analyzed.
-</p>
-
-<h3>Other Options</h3>
-
-<p>
-As mentioned above, extra options can be passed to <tt>scan-build</tt>. These
-options prefix the build command. For example:</p>
-
-<pre>
- $ scan-build <b>-k -V</b> make
- $ scan-build <b>-k -V</b> xcodebuild
-</pre>
-
-<p>Here is a subset of useful options:</p>
-
-<table>
- <thead><tr><td>Option</td><td>Description</td></tr></thead>
-
- <tr><td><b>-o</b></td><td>Target directory for HTML report files. Subdirectories will be
- created as needed to represent separate "runs" of the analyzer. If this option
-is not specified, a directory is created in <tt>/tmp</tt> to store the
-reports.</td><tr>
-
- <tr><td><b>-h</b><br><i><nobr>(or no arguments)</nobr></i></td><td>Display all <tt>scan-build</tt> options.</td></tr>
-
- <tr><td><b>-k</b><br><nobr><b>--keep-going</b></nobr></td><td>Add a "keep on going" option to the
- specified build command. <p>This option currently supports <tt>make</tt> and
- <tt>xcodebuild</tt>.</p> <p>This is a convenience option; one can specify this
- behavior directly using build options.</p></td></tr>
-
- <tr><td><b>-v<b></td><td>Verbose output from scan-build and the analyzer. <b>A second and third
- "-v" increases verbosity</b>, and is useful for filing bug reports against the analyzer.</td></tr>
-
- <tr><td><b>-V</b></td><td>View analysis results in a web browser when the build command completes.</td></tr>
-</table>
-
-<h2 id="Output">Output of the Analyzer</h2>
-
-<p>
-The output of the analyzer is a set of HTML files, each one which represents a
-separate bug report. A single <tt>index.html</tt> file is generated for
-surveying all of the bugs. You can then just open <tt>index.html</tt> in a web
-browser to view the bug reports.
-</p>
-
-<p>
-Where the HTML files are generated is specified with a <b>-o</b> option to
-<tt>scan-build</tt>. If <b>-o</b> isn't specified, a directory in <tt>/tmp</tt>
-is created to store the files (<tt>scan-build</tt> will print a message telling
-you where they are). If you want to view the reports immediately after the build
-completes, pass <b>-V</b> to <tt>scan-build</tt>.
-</p>
-
-
-<h2 id="RecommendedUsageGuidelines">Recommended Usage Guidelines</h2>
-
-Here are a few recommendations with running the analyzer:
-
-<h3>Always Analyze a Project in its "Debug" Configuration</h3>
-
-<p>Most projects can be built in a "debug" mode that enables assertions.
-Assertions are picked up by the static analyzer to prune infeasible paths, which
-in some cases can greatly reduce the number of false positives (bogus error
-reports) emitted by the tool.</p>
-
-<h3>Pass -k to scan-build</h3>
-
-<p>While <tt>ccc-analyzer</tt> invokes <tt>gcc</tt> to compile code, any
-problems in correctly forwarding arguments to <tt>gcc</tt> may result in a build
-failure. Passing <b>-k</b> to <tt>scan-build</tt> potentially allows you to
-analyze other code in a project for which this problem doesn't occur.</p>
-
-<p> Also, it is useful to analyze a project even if not all of the source files
-are compilable. This is great when using <tt>scan-build</tt> as part of your
-compile-debug cycle.</p>
-
-<h3>Use Verbose Output when Debugging scan-build</h3>
-
-<p><tt>scan-build</tt> takes a <b>-v</b> option to emit verbose output about
-what it's doing; two <b>-v</b> options emit more information. Redirecting the
-output of <tt>scan-build</tt> to a text file (make sure to redirect standard
-error) is useful for filing bug reports against <tt>scan-build</tt> or the
-analyzer, as we can see the exact options (and files) passed to the analyzer.
-For more comprehensible logs, don't perform a parallel build.</p>
-
-<h2 id="Debugging">Debugging the Analyzer</h2>
-
-<p>This section provides information on debugging the analyzer, and troubleshooting
-it when you have problems analyzing a particular project.</p>
-
-<h3>How it Works</h3>
-
-<p>To analyze a project, <tt>scan-build</tt> simply sets the environment variable
-<tt>CC</tt> to the full path to <tt>ccc-analyzer</tt>. It also sets a few other
-environment variables to communicate to <tt>ccc-analyzer</tt> where to dump HTML
-report files.</p>
-
-<p>Some Makefiles (or equivalent project files) hardcode the compiler; for such
-projects simply overriding <tt>CC</tt> won't cause <tt>ccc-analyzer</tt> to be
-called. This will cause the compiled code <b>to not be analyzed.</b></p> If you
-find that your code isn't being analyzed, check to see if <tt>CC</tt> is
-hardcoded. If this is the case, you can hardcode it instead to the <b>full
-path</b> to <tt>ccc-analyzer</tt>.</p>
-
-<p>When applicable, you can also run <tt>./configure</tt> for a project through
-<tt>scan-build</tt> so that configure sets up the location of <tt>CC</tt> based
-on the environment passed in from <tt>scan-build</tt>:
-
-<pre>
- $ scan-build <b>./configure</b>
-</pre>
-
-<p><tt>scan-build</tt> has special knowledge about <tt>configure</tt>, so it in
-most cases will not actually analyze the configure tests run by
-<tt>configure</tt>.</p>
-
-<p>Under the hood, <tt>ccc-analyzer</tt> directly invokes <tt>gcc</tt> to
-compile the actual code in addition to running the analyzer (which occurs by it
-calling <tt>clang</tt>). <tt>ccc-analyzer</tt> tries to correctly forward all
-the arguments over to <tt>gcc</tt>, but this may not work perfectly (please
-report bugs of this kind).
-
-<h2 id="filingbugs">Filing Bugs and Feature Requests</h2>
-
-<p>We encourage users to file bug reports for any problems that they encounter.
-We also welcome feature requests. When filing a bug report, please do the
-following:</p>
-
-<ul>
-
-<li>Include the checker build (for prebuilt Mac OS X binaries) or the SVN
-revision number.</li>
-
-<li>Provide a self-encapsulated, reduced test case that exhibits the issue
- you are experiencing.</li>
-
-<li>Test cases don't tell us everything. Please briefly describe the problem you are seeing.</li>
-
-</ul>
-
-<h3>Outside Apple</h3>
-
-<p>Please <a href="http://llvm.org/bugs/enter_bug.cgi?product=clang">file
-bugs</a> in LLVM's Bugzilla database against the Clang <b>Static Analyzer</b>
-component.</p>
-
-<h3>Apple-internal Users</h3>
-
-<p>Please file bugs in Radar against the <b>llvm - checker</b> component.</p>
+<p>This page has moved: <a href="http://clang-analyzer.llvm.org">clang.analyzer.llvm.org</a>.</p>
</div>
</body>
diff --git a/www/analyzer/annotations.html b/www/analyzer/annotations.html
new file mode 100644
index 000000000000..129748e9b0cc
--- /dev/null
+++ b/www/analyzer/annotations.html
@@ -0,0 +1,386 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Source Annotations</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Source Annotations</h1>
+
+<p>The Clang frontend supports several source-level annotations in the form of
+<a href="http://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html">GCC-style
+attributes</a> and pragmas that can help make using the Clang Static Analyzer
+more useful. These annotations can both help suppress false positives as well as
+enhance the analyzer's ability to find bugs.</p>
+
+<p>This page gives a practical overview of such annotations. For more technical
+specifics regarding Clang-specific annotations please see the Clang's list of <a
+href="http://clang.llvm.org/docs/LanguageExtensions.html">language
+extensions</a>. Details of &quot;standard&quot; GCC attributes (that Clang also
+supports) can be found in the <a href="http://gcc.gnu.org/onlinedocs/gcc/">GCC
+manual</a>, with the majority of the relevant attributes being in the section on
+<a href="http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html">function
+attributes</a>.</p>
+
+<p>Note that attributes that are labeled <b>Clang-specific</b> are not
+recognized by GCC. Their use can be conditioned using preprocessor macros
+(examples included on this page).</p>
+
+<ul>
+<li><a href="#generic">Annotations to Enhance Generic Checks</a></li>
+ <ul>
+ <li><a href="#null_checking">Null Pointer Checking</a></li>
+ <ul>
+ <li><a href="#attr_nonnull">Attribute 'nonnull'</a></li>
+ </ul>
+ </ul>
+<li><a href="#macosx">Mac OS X API Annotations</a></li>
+ <ul>
+ <li><a href="#cocoa_mem">Cocoa &amp; Core Foundation Memory Management
+ Annotations</a></li>
+ <ul>
+ <li><a href="#attr_ns_returns_retained">Attribute
+ 'ns_returns_retained'</a></li>
+ <li><a href="#attr_cf_returns_retained">Attribute
+ 'cf_returns_retained'</a></li>
+ </ul>
+ </ul>
+<li><a href="#custom_assertions">Custom Assertion Handlers</a></li>
+ <ul>
+ <li><a href="#attr_noreturn">Attribute 'noreturn'</a></li>
+ <li><a href="#attr_analyzer_noreturn">Attribute 'analyzer_noreturn'</a></li>
+ </ul>
+</ul>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h2 id="generic">Annotations to Enhance Generic Checks</h2>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<h3 id="null_checking">Null Pointer Checking</h3>
+
+<h4 id="attr_nonnull">Attribute 'nonnull'</h4>
+
+<p>The analyzer recognizes the GCC attribute 'nonnull', which indicates that a
+function expects that a given function parameter is not a null pointer. Specific
+details of the syntax of using the 'nonnull' attribute can be found in <a
+href="http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#index-g_t_0040code_007bnonnull_007d-function-attribute-2263">GCC's
+documentation</a>.</p>
+
+<p>Both the Clang compiler and GCC will flag warnings for simple cases where a
+null pointer is directly being passed to a function with a 'nonnull' parameter
+(e.g., as a constant). The analyzer extends this checking by using its deeper
+symbolic analysis to track what pointer values are potentially null and then
+flag warnings when they are passed in a function call via a 'nonnull'
+parameter.</p>
+
+<p><b>Example</b></p>
+
+<pre class="code_example">
+<span class="command">$ cat test.m</span>
+int bar(int*p, int q, int *r) __attribute__((nonnull(1,3)));
+
+int foo(int *p, int *q) {
+ return !p ? bar(q, 2, p)
+ : bar(p, 2, q);
+}
+
+<span class="command">$ clang --analyze test.m</span>
+test.m:4:16: warning: Null pointer passed as an argument to a 'nonnull' parameter
+ return !p ? bar(q, 2, p)
+ ^ ~
+1 diagnostic generated.
+</pre>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h2 id="macosx">Mac OS X API Annotations</h2>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<h3 id="cocoa_mem">Cocoa &amp; Core Foundation Memory Management
+Annotations</h3>
+
+<!--
+<p>As described in <a href="/available_checks.html#retain_release">Available
+Checks</a>,
+-->
+<p>The analyzer supports the proper management of retain counts for
+both Cocoa and Core Foundation objects. This checking is largely based on
+enforcing Cocoa and Core Foundation naming conventions for Objective-C methods
+(Cocoa) and C functions (Core Foundation). Not strictly following these
+conventions can cause the analyzer to miss bugs or flag false positives.</p>
+
+<p>One can educate the analyzer (and others who read your code) about methods or
+functions that deviate from the Cocoa and Core Foundation conventions using the
+attributes described here.</p>
+
+<h4 id="attr_ns_returns_retained">Attribute 'ns_returns_retained'
+(Clang-specific)</h4>
+
+<p>The GCC-style (Clang-specific) attribute 'ns_returns_retained' allows one to
+annotate an Objective-C method or C function as returning a retained Cocoa
+object that the caller is responsible for releasing (via sending a
+<tt>release</tt> message to the object).</p>
+
+<p><b>Placing on Objective-C methods</b>: For Objective-C methods, this
+annotation essentially tells the analyzer to treat the method as if its name
+begins with &quot;alloc&quot; or &quot;new&quot; or contais the word
+&quot;copy&quot;.</p>
+
+<p><b>Placing on C functions</b>: For C functions returning Cocoa objects, the
+analyzer typically does not make any assumptions about whether or not the object
+is returned retained. Explicitly adding the 'ns_returns_retained' attribute to C
+functions allows the analyzer to perform extra checking.</p>
+
+<p><b>Important note when using Garbage Collection</b>: Note that the analyzer
+interprets this attribute slightly differently when using Objective-C garbage
+collection (available on Mac OS 10.5+). When analyzing Cocoa code that uses
+garbage collection, &quot;alloc&quot; methods are assumed to return an object
+that is managed by the garbage collector (and thus doesn't have a retain count
+the caller must balance). These same assumptions are applied to methods or
+functions annotated with 'ns_returns_retained'. If you are returning a Core
+Foundation object (which may not be managed by the garbage collector) you should
+use 'cf_returns_retained'.</p>
+
+<p><b>Example</b></p>
+
+<pre class="code_example">
+<span class="command">$ cat test.m</span>
+#import &lt;Foundation/Foundation.h&gt;
+
+#ifndef NS_RETURNS_RETAINED
+#if __clang__
+<span class="code_highlight">#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))</span>
+#else
+#define NS_RETURNS_RETAINED
+#endif
+#endif
+
+@interface MyClass : NSObject {}
+- (NSString*) returnsRetained <span class="code_highlight">NS_RETURNS_RETAINED</span>;
+- (NSString*) alsoReturnsRetained;
+@end
+
+@implementation MyClass
+- (NSString*) returnsRetained {
+ return [[NSString alloc] initWithCString:"no leak here"];
+}
+- (NSString*) alsoReturnsRetained {
+ return [[NSString alloc] initWithCString:"flag a leak"];
+}
+@end
+
+<span class="command">$ clang --analyze test.m</span>
+$ clang --analyze test.m
+test.m:21:10: warning: Potential leak of an object allocated on line 21
+ return [[NSString alloc] initWithCString:"flag a leak"];
+ ^
+1 diagnostic generated.
+</pre>
+
+<h4 id="attr_cf_returns_retained">Attribute 'cf_returns_retained'
+(Clang-specific)</h4>
+
+<p>The GCC-style (Clang-specific) attribute 'cf_returns_retained' allows one to
+annotate an Objective-C method or C function as returning a retained Core
+Foundation object that the caller is responsible for releasing.
+
+<p><b>Placing on Objective-C methods</b>: With respect to Objective-C methods.,
+this attribute is identical in its behavior and usage to 'ns_returns_retained'
+except for the distinction of returning a Core Foundation object instead of a
+Cocoa object. This distinction is important for two reasons:</p>
+
+<ul>
+ <li>Core Foundation objects are not automatically managed by the Objective-C
+ garbage collector.</li>
+ <li>Because Core Foundation is a C API, the analyzer cannot always tell that a
+ pointer return value refers to a Core Foundation object. In contrast, it is
+ trivial for the analyzer to recognize if a pointer refers to a Cocoa object
+ (given the Objective-C type system).</p>
+</ul>
+
+<p><b>Placing on C functions</b>: When placing the attribute
+'cf_returns_retained' on the declarations of C functions, the analyzer
+interprets the function as:</p>
+
+<ol>
+ <li>Returning a Core Foundation Object</li>
+ <li>Treating the function as if it its name
+contained the keywords &quot;create&quot; or &quot;copy&quot;. This means the
+returned object as a +1 retain count that must be released by the caller, either
+by sending a <tt>release</tt> message (via toll-free bridging to an Objective-C
+object pointer), calling <tt>CFRelease</tt> (or similar function), or using
+<tt>CFMakeCollectable</tt> to register the object with the Objective-C garbage
+collector.</li>
+</ol>
+
+<p><b>Example</b></p>
+
+<p>In this example, observe the difference in output when the code is compiled
+to not use garbage collection versus when it is compiled to only use garbage
+collection (<tt>-fobjc-gc-only</tt>).</p>
+
+<pre class="code_example">
+<span class="command">$ cat test.m</span>
+$ cat test.m
+#import &lt;Cocoa/Cocoa.h&gt;
+
+#ifndef CF_RETURNS_RETAINED
+#if __clang__
+<span class="code_highlight">#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))</span>
+#else
+#define CF_RETURNS_RETAINED
+#endif
+#endif
+
+@interface MyClass : NSObject {}
+- (NSDate*) returnsCFRetained <span class="code_highlight">CF_RETURNS_RETAINED</span>;
+- (NSDate*) alsoReturnsRetained;
+- (NSDate*) returnsNSRetained <span class="code_highlight">NS_RETURNS_RETAINED</span>;
+@end
+
+<span class="code_highlight">CF_RETURNS_RETAINED</span>
+CFDateRef returnsRetainedCFDate() {
+ return CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+}
+
+@implementation MyClass
+- (NSDate*) returnsCFRetained {
+ return (NSDate*) returnsRetainedCFDate(); // No leak.
+}
+
+- (NSDate*) alsoReturnsRetained {
+ return (NSDate*) returnsRetainedCFDate(); // Always report a leak.
+}
+
+- (NSDate*) returnsNSRetained {
+ return (NSDate*) returnsRetainedCFDate(); // Report a leak when using GC.
+}
+@end
+
+<span class="command">$ clang --analyze test.m</span>
+test.m:28:20: warning: Potential leak of an object allocated on line 28
+ return (NSDate*) returnsRetainedCFDate(); // Always report a leak.
+ ^
+1 diagnostic generated.
+
+<span class="command">$ clang --analyze test.m <span class="code_highlight">-fobjc-gc-only</span></span>
+test.m:28:20: warning: Potential leak (when using garbage collection) of an object allocated on line 28
+ return (NSDate*) returnsRetainedCFDate(); // Always report a leak.
+ ^
+test.m:32:20: warning: Potential leak (when using garbage collection) of an object allocated on line 32
+ return (NSDate*) returnsRetainedCFDate(); // Report a leak when using GC.
+ ^
+2 diagnostics generated.
+</pre>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h2 id="custom_assertions">Custom Assertion Handlers</h2>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<p>The analyzer exploits code assertions by pruning off paths where the
+assertion condition is false. The idea is capture any program invariants
+specified in the assertion that the developer may know but is not immediately
+apparent in the code itself. In this way assertions make implicit assumptions
+explicit in the code, which not only makes the analyzer more accurate when
+finding bugs, but can help others better able to understand your code as well.
+It can also help remove certain kinds of analyzer false positives by pruning off
+false paths.</p>
+
+<p>In order to exploit assertions, however, the analyzer must understand when it
+encounters an &quot;assertion handler.&quot; Typically assertions are
+implemented with a macro, with the macro performing a check for the assertion
+condition and, when the check fails, calling an assertion handler. For example, consider the following code
+fragment:</p>
+
+<pre class="code_example">
+void foo(int *p) {
+ assert(p != NULL);
+}
+</pre>
+
+<p>When this code is preprocessed on Mac OS X it expands to the following:</p>
+
+<pre class="code_example">
+void foo(int *p) {
+ (__builtin_expect(!(p != NULL), 0) ? __assert_rtn(__func__, "t.c", 4, "p != NULL") : (void)0);
+}
+</pre>
+
+<p>In this example, the assertion handler is <tt>__assert_rtn</tt>. When called,
+most assertion handlers typically print an error and terminate the program. The
+analyzer can exploit such semantics by ending the analysis of a path once it
+hits a call to an assertion handler.</p>
+
+<p>The trick, however, is that the analyzer needs to know that a called function
+is an assertion handler; otherwise the analyzer might assume the function call
+returns and it will continue analyzing the path where the assertion condition
+failed. This can lead to false positives, as the assertion condition usually
+implies a safety condition (e.g., a pointer is not null) prior to performing
+some action that depends on that condition (e.g., dereferencing a pointer).</p>
+
+<p>The analyzer knows about several well-known assertion handlers, but can
+automatically infer if a function should be treated as an assertion handler if
+it is annotated with the 'noreturn' attribute or the (Clang-specific)
+'analyzer_noreturn' attribute.</p>
+
+<h4 id="attr_noreturn">Attribute 'noreturn'</h4>
+
+<p>The 'noreturn' attribute is a GCC-attribute that can be placed on the
+declarations of functions. It means exactly what its name implies: a function
+with a 'noreturn' attribute should never return.</p>
+
+<p>Specific details of the syntax of using the 'noreturn' attribute can be found
+in <a
+href="http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#index-g_t_0040code_007bnoreturn_007d-function-attribute-2264">GCC's
+documentation</a>.</p>
+
+<p>Not only does the analyzer exploit this information when pruning false paths,
+but the compiler also takes it seriously and will generate different code (and
+possibly better optimized) under the assumption that the function does not
+return.</p>
+
+<p><b>Example</b></p>
+
+<p>On Mac OS X, the function prototype for <tt>__assert_rtn</tt> (declared in
+<tt>assert.h</tt>) is specifically annotated with the 'noreturn' attribute:</p>
+
+<pre class="code_example">
+void __assert_rtn(const char *, const char *, int, const char *) <span class="code_highlight">__attribute__((__noreturn__))</span>;
+</pre>
+
+<h4 id="attr_analyzer_noreturn">Attribute 'analyzer_noreturn' (Clang-specific)</h4>
+
+<p>The Clang-specific 'analyzer_noreturn' attribute is almost identical to
+'noreturn' except that it is ignored by the compiler for the purposes of code
+generation.</p>
+
+<p>This attribute is useful for annotating assertion handlers that actually
+<em>can</em> return, but for the purpose of using the analyzer we want to
+pretend that such functions do not return.</p>
+
+<p>Because this attribute is Clang-specific, its use should be conditioned with
+the use of preprocessor macros.</p>
+
+<p><b>Example</b>
+
+<pre class="code_example">
+#ifndef CLANG_ANALYZER_NORETURN
+#if __clang__
+<span class="code_highlight">#define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))</span>
+#else
+#define CLANG_ANALYZER_NORETURN
+#endif
+
+void my_assert_rtn(const char *, const char *, int, const char *) <span class="code_highlight">CLANG_ANALYZER_NORETURN</span>;
+</pre>
+
+</div>
+</body>
+</html>
+
diff --git a/www/analyzer/available_checks.html b/www/analyzer/available_checks.html
new file mode 100644
index 000000000000..5e74fd8ea239
--- /dev/null
+++ b/www/analyzer/available_checks.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Available Checks</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Available Checks</h1>
+
+<p>This page is slated to contain a list of the current checks the analyzer
+performs along with some self-contained code examples. In the meantime, please
+check out any of the following writeups about the analyzer that contain examples
+of some of the bugs that it finds:</p>
+
+<ul>
+<li><a href="http://www.mobileorchard.com/bug-finding-with-clang-5-resources-to-get-you-started/">Bug Finding With Clang: 5 Resources To Get You Started</a></li>
+<li><a href="http://fruitstandsoftware.com/blog/index.php/2008/08/finding-memory-leaks-with-the-llvmclang-static-analyzer/#comment-2">Finding Memory Leaks With The LLVM/Clang Static Analyzer</a></li>
+<li><a href="http://www.therareair.com/howto-static-analyze-your-objective-c-code-using-the-clang-static-analyzer-tool-gallery/">HOWTO: Static Analyze Your Objective-C Code Using the Clang Static Analyzer Tool Gallery</a></li>
+<li><a href="http://www.rogueamoeba.com/utm/2008/07/14/the-clang-static-analyzer/">Under the Microscope - The Clang Static Analyzer</a></li>
+<li><a href="http://www.mikeash.com/?page=pyblog/friday-qa-2009-03-06-using-the-clang-static-analyzer.html">Mike Ash - Using the Clang Static Analyzer</a></li>
+</ul>
+
+
+</div>
+</body>
+</html>
+
diff --git a/www/analyzer/content.css b/www/analyzer/content.css
new file mode 100644
index 000000000000..01a3af2a6cb6
--- /dev/null
+++ b/www/analyzer/content.css
@@ -0,0 +1,31 @@
+html, body {
+ padding:0px;
+ font-size:small; font-family:"Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, Helvetica, sans-serif; background-color: #fff; color: #222;
+ line-height:1.5;
+}
+
+h1, h2, h3, tt { color: #000 }
+
+h1 { padding-top:0px; margin-top:0px;}
+h2 { color:#333333; padding-top:0.5em; }
+h3 { padding-top: 0.5em; margin-bottom: -0.25em; color:#2d58b7 }
+h4 { color:#2d58b7 }
+li { padding-bottom: 0.5em }
+ul { padding-left:1.5em; }
+
+.command { font-weight:bold }
+.code_highlight { font-weight:bold; color:#2d58b7 }
+.code_example { border-width:1px; border-style:solid; border-color:#cccccc;
+ background-color:#eeeeee; padding:10px }
+
+/* Slides */
+IMG.img_slide {
+ display: block;
+ margin-left: auto;
+ margin-right: auto
+}
+
+.itemTitle { color:#2d58b7 }
+
+/* Tables */
+tr { vertical-align:top }
diff --git a/www/analyzer/filing_bugs.html b/www/analyzer/filing_bugs.html
new file mode 100644
index 000000000000..1ce02bee9286
--- /dev/null
+++ b/www/analyzer/filing_bugs.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Filing Bugs and Feature Requests</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Filing Bugs and Feature Requests</h1>
+
+<p>We encourage users to file bug reports for any problems that they encounter.
+We also welcome feature requests. When filing a bug report, please do the
+following:</p>
+
+<ul>
+
+<li>Include the checker build (for prebuilt Mac OS X binaries) or the SVN
+revision number.</li>
+
+<li>Provide a self-contained, reduced test case that exhibits the issue you are
+experiencing.</li>
+
+<li>Test cases don't tell us everything. Please briefly describe the problem you
+are seeing, including what you thought should have been the expected behavior
+and why.</li>
+
+</ul>
+
+<h2>Outside of Apple</h2>
+
+<h3>Bugzilla</h3>
+
+<p>Please <a href="http://llvm.org/bugs/enter_bug.cgi?product=clang">file
+bugs</a> in LLVM's Bugzilla database against the Clang <b>Static Analyzer</b>
+component.</p>
+
+<h3>Bugreporter.apple.com</h3>
+
+<p>If you are using the analyzer to analyze code associated with an Apple NDA
+(e.g., preview versions of SDKs or seed releases of Mac OS X) please file bug
+reports to Apple's <a href="http://bugreporter.apple.com">Bug Reporter</a> web
+site.</p>
+
+<p>You are free to always file bugs through this website, but this option less
+attractive than filing bug reports through Bugzilla as not everyone who works on
+the analyzer has access to that bug database.</p>
+
+<h2>Apple-internal Users</h2>
+
+<p>Please file bugs in Radar against the <b>llvm - checker</b> component.</p>
+
+
+</div>
+</body>
+</html>
+
diff --git a/www/analyzer/index.html b/www/analyzer/index.html
new file mode 100644
index 000000000000..d180e830e185
--- /dev/null
+++ b/www/analyzer/index.html
@@ -0,0 +1,186 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Clang Static Analyzer</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Clang Static Analyzer</h1>
+
+<p>The Clang Static Analyzer consists of both a source code analysis framework
+and a standalone tool that finds bugs in C and Objective-C programs. The
+standalone tool is invoked from the command-line, and is intended to run in
+tandem with a build of a project or code base.</p>
+
+<p>Both are 100% open source and are part of the <a
+href="http://clang.llvm.org">Clang</a> project.</p>
+
+<!-- Generated from: http://www.spiffycorners.com/index.php -->
+
+<style type="text/css">
+.spiffy{display:block}
+.spiffy *{
+ display:block;
+ height:1px;
+ overflow:hidden;
+ font-size:.01em;
+ background:#EBF0FA}
+.spiffy1{
+ margin-left:3px;
+ margin-right:3px;
+ padding-left:1px;
+ padding-right:1px;
+ border-left:1px solid #f6f8fc;
+ border-right:1px solid #f6f8fc;
+ background:#f0f3fb}
+.spiffy2{
+ margin-left:1px;
+ margin-right:1px;
+ padding-right:1px;
+ padding-left:1px;
+ border-left:1px solid #fdfdfe;
+ border-right:1px solid #fdfdfe;
+ background:#eef2fa}
+.spiffy3{
+ margin-left:1px;
+ margin-right:1px;
+ border-left:1px solid #eef2fa;
+ border-right:1px solid #eef2fa;}
+.spiffy4{
+ border-left:1px solid #f6f8fc;
+ border-right:1px solid #f6f8fc}
+.spiffy5{
+ border-left:1px solid #f0f3fb;
+ border-right:1px solid #f0f3fb}
+.spiffyfg{
+ background:#EBF0FA}
+
+.spiffyfg h2 {
+ margin:0px; padding:10px;
+}
+</style>
+
+<style type="text/css">
+ #left { float:left; }
+ #left h2 { margin:1px; padding-top:0px; }
+ #right { float:left; margin-left:20px; margin-right:20px; padding:0px ;}
+ #right h2 { padding:0px; margin:0px; }
+ #wrappedcontent { padding:15px;}
+</style>
+
+<div style="padding:0px">
+ <b class="spiffy">
+ <b class="spiffy1"><b></b></b>
+ <b class="spiffy2"><b></b></b>
+ <b class="spiffy3"></b>
+ <b class="spiffy4"></b>
+ <b class="spiffy5"></b></b>
+ <div class="spiffyfg">
+ <div style="padding:15px">
+ <h2 style="padding:0px; margin:0px">Download</h2>
+ <h3 style="margin-top:5px">Mac OS X</h3>
+ <ul>
+ <li>Latest build (Universal binary, 10.5+):
+ <!--#include virtual="latest_checker.html.incl"-->
+ </li>
+ <li><a href="/installation.html">Installation</a> and <a
+ href="/scan-build.html">usage</a></li>
+ </ul>
+ <h3>Other Platforms</h3>
+ <p>For other platforms, please follow the instructions for <a
+ href="/installation#OtherPlatforms">building the analyzer</a> from
+ source code.<p>
+ </div>
+ </div>
+ <b class="spiffy">
+ <b class="spiffy5"></b>
+ <b class="spiffy4"></b>
+ <b class="spiffy3"></b>
+ <b class="spiffy2"><b></b></b>
+ <b class="spiffy1"><b></b></b></b>
+</div>
+
+<h2 id="StaticAnalysis">What is Static Analysis?</h2>
+
+<p>The term &quot;static analysis&quot; is conflated, but here we use it to mean
+a collection of algorithms and techniques used to analyze source code in order
+to automatically find bugs. The idea is similar in spirit to compiler warnings
+(which can be useful for finding coding errors) but to take that idea a step
+further and find bugs that are traditionally found using run-time debugging
+techniques such as testing.</p>
+
+<p>Static analysis bug-finding tools have evolved over the last several decades
+from basic syntactic checkers to those that find deep bugs by reasoning about
+the semantics of code. The goal of the Clang Static Analyzer is to provide a
+industrial-quality static analysis framework for analyzing C and Objective-C
+programs that is freely available, extensible, and has a high quality of
+implementation.</p>
+
+<h3 id="Clang">Part of Clang and LLVM</h3>
+
+<p>As its name implies, the Clang Static Analyzer is built on top of <a
+href="http://clang.llvm.org">Clang</a> and <a href="http://llvm.org">LLVM</a>.
+Strictly speaking, the analyzer is part of Clang, as Clang consists of a set of
+reusable C++ libraries for building powerful source-level tools. The static
+analysis engine used by the Clang Static Analyzer is a Clang library, and has
+the capability to be reused in different contexts and by different clients.</p>
+
+<h2>Important Points to Consider</h2>
+
+<p>While we believe that the static analyzer is already very useful for finding
+bugs, we ask you to bear in mind a few points when using it.</p>
+
+<h3>Work-in-Progress</h3>
+
+<p>The analyzer is a continuous work-in-progress.
+There are many planned enhancements to improve both the precision and scope of
+its analysis algorithms as well as the kinds bugs it will find. While there are
+fundamental limitations to what static analysis can do, we have a long way to go
+before hitting that wall.</p>
+
+<h3>Slower than Compilation</h3>
+
+<p>Operationally, using static analysis to
+automatically find deep program bugs is about trading CPU time for the hardening
+of code. Because of the deep analysis performed by state-of-the-art static
+analysis tools, static analysis can be much slower than compilation.</p>
+
+<p>While the Clang Static Analyzer is being designed to be as fast and
+light-weight as possible, please do not expect it to be as fast as compiling a
+program (even with optimizations enabled). Some of the algorithms needed to find
+bugs require in the worst case exponential time.</p>
+
+<p>The Clang Static Analyzer runs in a reasonable amount of time by both
+bounding the amount of checking work it will do as well as using clever
+algorithms to reduce the amount of work it must do to find bugs.</p></li>
+
+<h3>False Positives</h3>
+
+<p>Static analysis is not perfect. It can falsely flag bugs in a program where
+the code behaves correctly. Because some code checks require more analysis
+precision than others, the frequency of false positives can vary widely between
+different checks. Our long-term goal is to have the analyzer have a low false
+positive rate for most code on all checks.</p>
+
+<p>Please help us in this endeavor by <a href="filing_bugs.html">reporting false
+positives</a>. False positives cannot be addressed unless we know about
+them.</p>
+
+<h3>More Checks</h3>
+
+<p>Static analysis not magic; a static analyzer can only find bugs that it has
+been specifically engineered to find. If there are specific kinds of bugs you
+would like the Clang Static Analyzer to find, please feel free to file <a
+href="filing_bugs.html">feature requests</a> or contribute your own patches.</p>
+
+</div>
+</body>
+</html>
+
diff --git a/www/analyzer/installation.html b/www/analyzer/installation.html
new file mode 100644
index 000000000000..891353562136
--- /dev/null
+++ b/www/analyzer/installation.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Obtaining the Static Analyzer</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Obtaining the Static Analyzer</h1>
+
+<p>This page describes how to download and install the analyzer. Once
+the analyzer is installed, follow the <a
+href="/scan-build.html">instructions</a> on using <tt>scan-build</tt> to
+get started analyzing your code.</p>
+
+<h2>Packaged Builds (Mac OS X)</h2>
+
+<p>Semi-regular pre-built binaries of the analyzer are available on Mac
+OS X. These are built to run on Mac OS 10.5 and later.</p>
+
+<p>Builds are released frequently. Often the differences between build
+numbers being a few bug fixes or minor feature improvements. When using
+the analyzer, we recommend that you check back here occasionally for new
+builds, especially if the build you are using is more than a couple
+weeks old.</p>
+
+<p>The latest build is:
+ <!--#include virtual="latest_checker.html.incl"-->
+</p>
+
+<p>Packaged builds for other platforms may eventually be provided, but
+we need volunteers who are willing to help provide such regular builds.
+If you wish to help contribute regular builds of the analyzer on other
+platforms, please email the <a
+href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev">Clang
+Developers' mailing list</a>.</p>
+
+<h3>Using Packaged Builds</h3>
+
+<p>To use a package build, simply unpack it anywhere. If the build
+archive has the name <b><tt>checker-XXX.tar.bz2</tt></b> then the
+archive will expand to a directory called <b><tt>checker-XXX</tt></b>.
+You do not need to place this directory or the contents of this
+directory in any special place. Uninstalling the analyzer is as simple
+as deleting this directory.</p>
+
+<p>Most of the files in the <b><tt>checker-XXX</tt></b> directory will
+be supporting files for the analyzer that you can simply ignore. Most
+users will only care about two files, which are located at the top of
+the <b><tt>checker-XXX</tt></b> directory:</p>
+
+<ul>
+<li><b>scan-build</b>: <tt>scan-build</tt> is the high-level command line utility for running the analyzer</li>
+<li><b>scan-view</b>: <tt>scan-view</tt> a companion comannd line
+utility to <tt>scan-build</tt>, <tt>scan-view</tt> is used to view
+analysis results generated by <tt>scan-build</tt>. There is an option
+that one can pass to <tt>scan-build</tt> to cause <tt>scan-view</tt> to
+run as soon as it the analysis of a build completes</li>
+</ul>
+
+<h4>Running scan-build</h4>
+
+<p>For specific details on using <tt>scan-build</tt>, please see
+<tt>scan-build</tt>'s <a href="/scan-build">documentation</a>.</p>
+
+<p>To run <tt>scan-build</tt>, either add the
+<b><tt>checker-XXX</tt></b> directory to your path or specify a complete
+path for <tt>scan-build</tt> when running it. It is also possible to use
+a symbolic link to <tt>scan-build</tt>, such one located in a directory
+in your path. When <tt>scan-build</tt> runs it will automatically
+determine where to find its accompanying files.</p>
+
+<h2 id="OtherPlatforms">Other Platforms (Building the Analyzer from Source)</h2>
+
+<p>For other platforms, you must build Clang and LLVM manually. To do
+so, please follow the instructions for <a
+href="http://clang.llvm.org/get_started.html#build">building Clang from
+source code</a>.<p>
+
+<p>Once the Clang is built, you need to add the following to your path:</p>
+
+<ul>
+
+<li>The locations of the <tt>clang-cc</tt> and <tt>clang</tt> binaries.
+
+<p>For example, if you built a <em>Debug</em> build of LLVM/Clang, the
+resultant binaries will be in $(OBJDIR)/Debug (where <tt>$(OBJDIR)</tt>
+is often the same as the root source directory). You can also do
+<tt>make install</tt> to install the LLVM/Clang libaries and binaries to
+the installation directory of your choice (specified when you run
+<tt>configure</tt>).</p></li>
+
+<li>The locations of the <tt>scan-build</tt> and <tt>scan-view</tt>
+programs.
+
+<p>Currently these are not installed using <tt>make install</tt>, and
+are located in <tt>$(SRCDIR)/tools/clang/util</tt> and
+<tt>$(SRCDIR)/tools/clang/tools/scan-view</tt> respectively (where
+<tt>$(SRCDIR)</tt> is the root LLVM source directory). These locations
+are subject to change.</p></li>
+
+</ul>
+
+</div>
+</body>
+</html>
+
diff --git a/www/latest_checker.html.incl b/www/analyzer/latest_checker.html.incl
index c465cac88539..c465cac88539 100644
--- a/www/latest_checker.html.incl
+++ b/www/analyzer/latest_checker.html.incl
diff --git a/www/analyzer/menu.css b/www/analyzer/menu.css
new file mode 100644
index 000000000000..8249c14197e4
--- /dev/null
+++ b/www/analyzer/menu.css
@@ -0,0 +1,40 @@
+/***************/
+/* page layout */
+/***************/
+
+[id=menu] {
+ position:fixed;
+ width:25ex;
+}
+[id=content] {
+ /* ***** EDIT THIS VALUE IF CONTENT OVERLAPS MENU ***** */
+ position:absolute;
+ left:29ex;
+ padding-right:4ex;
+}
+
+/**************/
+/* menu style */
+/**************/
+
+#menu .submenu {
+ padding-top:1em;
+ display:block;
+}
+
+#menu label {
+ display:block;
+ font-weight: bold;
+ text-align: center;
+ color: #ffffff;
+ background-color: #2d58b7;
+}
+#menu a {
+ padding:0 .2em;
+ display:block;
+ text-align: center;
+ background-color: #EBF0FA;
+}
+#menu a:visited {
+ color:rgb(100,50,100);
+} \ No newline at end of file
diff --git a/www/analyzer/menu.html.incl b/www/analyzer/menu.html.incl
new file mode 100644
index 000000000000..a5e7f31f6275
--- /dev/null
+++ b/www/analyzer/menu.html.incl
@@ -0,0 +1,28 @@
+<div id="menu">
+ <div>
+ <a href="http://llvm.org/">LLVM Home</a>
+ <a href="http://clang.llvm.org/">Clang Home</a>
+ </div>
+
+ <div class="submenu">
+ <label>Quick Links</label>
+ <a href="/index.html">About the Analyzer</a>
+ <a href="/filing_bugs.html">Filing Bugs</a>
+ </div>
+
+ <div class="submenu">
+ <label>User Manual</label>
+<!-- <a href="/design_philosphy.html">Design&nbsp;Philosophy</a> -->
+ <a href="/installation.html">Obtaining&nbsp;the&nbsp;Analyzer</a>
+ <a href="/scan-build.html">Running&nbsp;the&nbsp;Analyzer</tt></a>
+ <a href="/available_checks.html">Available&nbsp;Checks</a>
+<!-- <a href="/false_positives.html">False&nbsp;Positives</a> -->
+ <a href="/annotations.html">Source-level Annotations</a>
+ </div>
+
+ <div class="submenu">
+ <label>Clang Mailing Lists</label>
+ <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev">cfe-dev</a>
+ <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">cfe-commits</a>
+ </div>
+</div>
diff --git a/www/analyzer/scan-build.html b/www/analyzer/scan-build.html
new file mode 100644
index 000000000000..5bd5319e8d0b
--- /dev/null
+++ b/www/analyzer/scan-build.html
@@ -0,0 +1,257 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Running the Analyzer</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+ <style>
+ thead {
+ background-color:#eee; color:#666666;
+ font-weight: bold; cursor: default;
+ text-align:center;
+ border-top: 2px solid #cccccc;
+ border-bottom: 2px solid #cccccc;
+ font-weight: bold; font-family: Verdana
+ }
+ table { border: 1px #cccccc solid }
+ table { border-collapse: collapse; border-spacing: 0px }
+ table { margin-left:0px; margin-top:20px; margin-bottom:20px }
+ td { border-bottom: 1px #cccccc dotted }
+ td { padding:5px; padding-left:8px; padding-right:8px }
+ td { text-align:left; font-size:9pt }
+ td.View { padding-left: 10px }
+ </style>
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Running the Analyzer</h1>
+
+<p>While the static analyzer engine can be used as a library, many users will
+likely use the command-line interface to the analyzer to analyze projects. There
+are essentially two commands one can use the run the analyzer:</p>
+
+<ul>
+<li><b>scan-build</b>: The <tt>scan-build</tt> command can be used to analyze
+an entire project.</li>
+<li><b>clang</b>: The <tt>clang</tt> command is both Clang's compiler and
+static analysis driver. This can be used both to compile and analyze
+individual source files.
+</ul>
+
+<h3>Contents</h3>
+
+<ul>
+<li><a href="#scanbuild">scan-build</a></li>
+ <ul>
+ <li><a href="#scanbuild_basicusage">Basic Usage</a></li>
+ <li><a href="#scanbuild_otheroptions">Other Options</a></li>
+ <li><a href="#scanbuild_output">Output of scan-build</a></li>
+ </ul>
+<li><a href="#recommendedguidelines">Recommended Usage Guidelines</a></li>
+ <ul>
+ <li><a href="#recommended_debug">Always Analyze a Project in its &quot;Debug&quot; Configuration</a></li>
+ <li><a href="#recommended_verbose">Use Verbose Output when Debugging scan-build</a></li>
+ <li><a href="#recommended_autoconf">Run './configure' through scan-build</a></li>
+ </ul>
+</ul>
+
+<h2 id="scanbuild">scan-build</h2>
+
+<p>The <tt>scan-build</tt> command can be used to analyze an entire project by
+essentially interposing on a project's build process. This means that to run the
+analyzer using <tt>scan-build</tt>, you will use <tt>scan-build</tt> to analyze
+the source files compiled by <tt>gcc</tt> during a project build. This means
+that any files that are not compiled will also not be analyzed.</p>
+
+<h3 id="scanbuild_basicusage">Basic Usage</h3>
+
+<p>Basic usage of <tt>scan-build</tt> is designed to be simple: just place the
+word &quot;scan-build&quot; in front of your build command:</p>
+
+<pre class="code_example">
+$ <span class="code_highlight">scan-build</span> make
+$ <span class="code_highlight">scan-build</span> xcodebuild
+</pre>
+
+<p>In the first case <tt>scan-build</tt> analyzes the code of a project built
+with <tt>make</tt> and in the second case <tt>scan-build</tt> analyzes a project
+built using <tt>xcodebuild</tt>.<p>
+
+<p>Here is the general format for invoking <tt>scan-build</tt>:</p>
+
+<pre class="code_example">
+$ <span class="code_highlight">scan-build</span> <i>[scan-build options]</i> <span class="code_highlight">&lt;command&gt;</span> <i>[command options]</i>
+</pre>
+
+<p>Operationally, <tt>scan-build</tt> literally runs <command> with all of the
+subsequent options passed to it. For example, one can pass <nobr><tt>-j4</tt></nobr> to
+<tt>make</tt> get a parallel build over 4 cores:</p>
+
+<pre class="code_example">
+$ scan-build make <span class="code_highlight">-j4</span>
+</pre>
+
+<p>In almost all cases, <tt>scan-build</tt> makes no effort to interpret the
+options after the build command; it simply passes them through. In general,
+<tt>scan-build</tt> should support parallel builds, but <b>not distributed
+builds</b>.</p>
+
+<p>It is also possible to use <tt>scan-build</tt> to analyze specific
+files:</p>
+
+<pre class="code_example">
+ $ scan-build gcc -c <span class="code_highlight">t1.c t2.c</span>
+</pre>
+
+<p>This example causes the files <tt>t1.c</tt> and <tt>t2.c</tt> to be analyzed.
+</p>
+
+<h3 id="scanbuild_otheroptions">Other Options</h3>
+
+<p>As mentioned above, extra options can be passed to <tt>scan-build</tt>. These
+options prefix the build command. For example:</p>
+
+<pre class="code_example">
+ $ scan-build <span class="code_highlight">-k -V</span> make
+ $ scan-build <span class="code_highlight">-k -V</span> xcodebuild
+</pre>
+
+<p>Here is a subset of useful options:</p>
+
+<table>
+<thead><tr><td>Option</td><td>Description</td></tr></thead>
+
+<tr><td><b>-o</b></td><td>Target directory for HTML report files. Subdirectories
+will be created as needed to represent separate "runs" of the analyzer. If this
+option is not specified, a directory is created in <tt>/tmp</tt> to store the
+reports.</td><tr>
+
+<tr><td><b>-h</b><br><i><nobr>(or no arguments)</nobr></i></td><td>Display all
+<tt>scan-build</tt> options.</td></tr>
+
+<tr><td><b>-k</b><br><nobr><b>--keep-going</b></nobr></td><td>Add a "keep on
+going" option to the specified build command. <p>This option currently supports
+<tt>make</tt> and <tt>xcodebuild</tt>.</p> <p>This is a convenience option; one
+can specify this behavior directly using build options.</p></td></tr>
+
+<tr><td><b>-v<b></td><td>Verbose output from scan-build and the analyzer. <b>A
+second and third "-v" increases verbosity</b>, and is useful for filing bug
+reports against the analyzer.</td></tr>
+
+<tr><td><b>-V</b></td><td>View analysis results in a web browser when the build
+command completes.</td></tr> </table>
+
+<p>A complete list of options can be obtained by running <tt>scan-build</tt>
+with no arguments.</p>
+
+<h3 id="scanbuild_output">Output of scan-build</h3>
+
+<p>
+The output of scan-build is a set of HTML files, each one which represents a
+separate bug report. A single <tt>index.html</tt> file is generated for
+surveying all of the bugs. You can then just open <tt>index.html</tt> in a web
+browser to view the bug reports.
+</p>
+
+<p>
+Where the HTML files are generated is specified with a <b>-o</b> option to
+<tt>scan-build</tt>. If <b>-o</b> isn't specified, a directory in <tt>/tmp</tt>
+is created to store the files (<tt>scan-build</tt> will print a message telling
+you where they are). If you want to view the reports immediately after the build
+completes, pass <b>-V</b> to <tt>scan-build</tt>.
+</p>
+
+
+<h2 id="recommendedguidelines">Recommended Usage Guidelines</h2>
+
+<p>This section describes a few recommendations with running the analyzer.</p>
+
+<h3 id="recommended_debug">Always Analyze a Project in its &quot;Debug&quot; Configuration</h3>
+
+<p>Most projects can be built in a &quot;debug&quot; mode that enables assertions.
+Assertions are picked up by the static analyzer to prune infeasible paths, which
+in some cases can greatly reduce the number of false positives (bogus error
+reports) emitted by the tool.</p>
+
+<h3 id="recommend_verbose">Use Verbose Output when Debugging scan-build</h3>
+
+<p><tt>scan-build</tt> takes a <b>-v</b> option to emit verbose output about
+what it's doing; two <b>-v</b> options emit more information. Redirecting the
+output of <tt>scan-build</tt> to a text file (make sure to redirect standard
+error) is useful for filing bug reports against <tt>scan-build</tt> or the
+analyzer, as we can see the exact options (and files) passed to the analyzer.
+For more comprehensible logs, don't perform a parallel build.</p>
+
+<h3 id="recommended_autoconf">Run './configure' through scan-build</h3>
+
+<p>If an analyzed project uses an autoconf generated <tt>configure</tt> script,
+you will probably need to run <tt>configure</tt> script through
+<tt>scan-build</tt> in order to analyze the project.</p>
+
+<p><b>Example</b></p>
+
+<pre class="code_example">
+$ scan-build ./configure
+$ scan-build make
+</pre>
+
+<p>The reason <tt>configure</tt> also needs to be run through
+<tt>scan-build</tt> is because <tt>scan-build</tt> scans your source files by
+<i>interposing</i> on the compiler. This interposition is currently done by
+<tt>scan-build</tt> temporarily setting the environment variable <tt>CC</tt> to
+<tt>ccc-analyzer</tt>. The program <tt>ccc-analyzer</tt> acts like a fake
+compiler, forwarding its command line arguments over to <tt>gcc</tt> to perform
+regular compilation and <tt>clang</tt> to perform static analysis.</p>
+
+<p>Running <tt>configure</tt> typically generates makefiles that have hardwired
+paths to the compiler, and by running <tt>configure</tt> through
+<tt>scan-build</tt> that path is set to <tt>ccc-analyzer</tt>.</p.>
+
+<!--
+<h2 id="Debugging">Debugging the Analyzer</h2>
+
+<p>This section provides information on debugging the analyzer, and troubleshooting
+it when you have problems analyzing a particular project.</p>
+
+<h3>How it Works</h3>
+
+<p>To analyze a project, <tt>scan-build</tt> simply sets the environment variable
+<tt>CC</tt> to the full path to <tt>ccc-analyzer</tt>. It also sets a few other
+environment variables to communicate to <tt>ccc-analyzer</tt> where to dump HTML
+report files.</p>
+
+<p>Some Makefiles (or equivalent project files) hardcode the compiler; for such
+projects simply overriding <tt>CC</tt> won't cause <tt>ccc-analyzer</tt> to be
+called. This will cause the compiled code <b>to not be analyzed.</b></p> If you
+find that your code isn't being analyzed, check to see if <tt>CC</tt> is
+hardcoded. If this is the case, you can hardcode it instead to the <b>full
+path</b> to <tt>ccc-analyzer</tt>.</p>
+
+<p>When applicable, you can also run <tt>./configure</tt> for a project through
+<tt>scan-build</tt> so that configure sets up the location of <tt>CC</tt> based
+on the environment passed in from <tt>scan-build</tt>:
+
+<pre>
+ $ scan-build <b>./configure</b>
+</pre>
+
+<p><tt>scan-build</tt> has special knowledge about <tt>configure</tt>, so it in
+most cases will not actually analyze the configure tests run by
+<tt>configure</tt>.</p>
+
+<p>Under the hood, <tt>ccc-analyzer</tt> directly invokes <tt>gcc</tt> to
+compile the actual code in addition to running the analyzer (which occurs by it
+calling <tt>clang</tt>). <tt>ccc-analyzer</tt> tries to correctly forward all
+the arguments over to <tt>gcc</tt>, but this may not work perfectly (please
+report bugs of this kind).
+ -->
+
+</div>
+</body>
+</html>
+
diff --git a/www/cxx_status.html b/www/cxx_status.html
index d85d451f559e..d5ff8ac05773 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -1885,22 +1885,22 @@ welcome!</p>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;14.5.4 [temp.class.spec]</td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
+ <td class="complete" align="center"></td>
+ <td class="complete" align="center"></td>
+ <td class="complete" align="center"></td>
+ <td class="na" align="center">N/A</td>
<td></td>
</tr>
<tr>
- <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14.5.5.1 [temp.class.spec.match]</td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14.5.4.1 [temp.class.spec.match]</td>
+ <td class="na" align="center">N/A</td>
+ <td class="na" align="center">N/A</td>
+ <td class="complete" align="center"></td>
<td class="na" align="center">N/A</td>
<td></td>
</tr>
<tr>
- <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14.5.5.2 [temp.class.order]</td>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14.5.4.2 [temp.class.order]</td>
<td class="broken" align="center"></td>
<td class="broken" align="center"></td>
<td class="broken" align="center"></td>
@@ -2085,10 +2085,10 @@ welcome!</p>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;14.8.2 [temp.deduct]</td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
+ <td class="na" align="center">N/A</td>
+ <td class="na" align="center">N/A</td>
+ <td class="medium" align="center"></td>
+ <td class="na" align="center">N/A</td>
<td></td>
</tr>
<tr>
@@ -2117,10 +2117,10 @@ welcome!</p>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14.8.2.4 [temp.deduct.type]</td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
- <td class="broken" align="center"></td>
+ <td class="na" align="center">N/A</td>
+ <td class="complete" align="center"></td>
+ <td class="medium" align="center"></td>
+ <td class="na" align="center">N/A</td>
<td></td>
</tr>
<tr>
diff --git a/www/menu.html.incl b/www/menu.html.incl
index 44f68610ab63..561969b5d51c 100644
--- a/www/menu.html.incl
+++ b/www/menu.html.incl
@@ -25,7 +25,7 @@
<div class="submenu">
<label>Clang Tools</label>
- <a href="/StaticAnalysis.html">Automatic Bug-Finding</a>
+ <a href="http://clang-analyzer.llvm.org">Automatic Bug-Finding</a>
</div>
<div class="submenu">